diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index ba0f33f7d942..8ddfc5e8e33c 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -14,6 +14,11 @@ # The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last. # +# 20101101: headers moved to machine/ to x86/ +.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "i386" +OLD_FILES+=usr/include/machine/apicreg.h +OLD_FILES+=usr/include/machine/mca.h +.endif # 20101020: catch up with vm_page_sleep_if_busy rename OLD_FILES+=usr/share/man/man9/vm_page_sleep_busy.9.gz # 20101011: removed subblock.h from liblzma diff --git a/bin/sh/parser.c b/bin/sh/parser.c index 23db5e73ad38..01907e84e9b2 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -69,6 +69,11 @@ __FBSDID("$FreeBSD$"); #define EOFMARKLEN 79 #define PROMPTLEN 128 +/* values of checkkwd variable */ +#define CHKALIAS 0x1 +#define CHKKWD 0x2 +#define CHKNL 0x4 + /* values returned by readtoken */ #include "token.h" @@ -102,9 +107,6 @@ static int startlinno; /* line # where last token started */ static int funclinno; /* line # where the current function started */ static struct parser_temp *parser_temp; -/* XXX When 'noaliases' is set to one, no alias expansion takes place. */ -static int noaliases = 0; - static union node *list(int, int); static union node *andor(void); @@ -230,7 +232,7 @@ list(int nlflag, int erflag) union node *ntop, *n1, *n2, *n3; int tok; - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; if (!nlflag && !erflag && tokendlist[peektoken()]) return NULL; ntop = n1 = NULL; @@ -283,7 +285,7 @@ list(int nlflag, int erflag) } else { tokpushback++; } - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; if (!nlflag && !erflag && tokendlist[peektoken()]) return ntop; break; @@ -339,7 +341,7 @@ pipeline(void) int negate, t; negate = 0; - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; TRACE(("pipeline: entered\n")); while (readtoken() == TNOT) negate = !negate; @@ -355,7 +357,7 @@ pipeline(void) do { prev = lp; lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; t = readtoken(); tokpushback++; if (t == TNOT) @@ -388,7 +390,7 @@ command(void) union node *redir, **rpp; int t; - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; redir = NULL; n1 = NULL; rpp = &redir; @@ -429,7 +431,7 @@ command(void) } if (readtoken() != TFI) synexpect(TFI); - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; case TWHILE: case TUNTIL: { @@ -445,7 +447,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); n1->nbinary.ch2 = list(0, 0); if (readtoken() != TDONE) synexpect(TDONE); - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; } case TFOR: @@ -487,7 +489,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); if (lasttoken != TNL && lasttoken != TSEMI) tokpushback++; } - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; if ((t = readtoken()) == TDO) t = TDONE; else if (t == TBEGIN) @@ -497,7 +499,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); n1->nfor.body = list(0, 0); if (readtoken() != t) synexpect(t); - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; case TCASE: n1 = (union node *)stalloc(sizeof (struct ncase)); @@ -513,8 +515,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); if (lasttoken != TWORD || ! equal(wordtext, "in")) synerror("expecting \"in\""); cpp = &n1->ncase.cases; - noaliases = 1; /* turn off alias expansion */ - checkkwd = 2, readtoken(); + checkkwd = CHKNL | CHKKWD, readtoken(); while (lasttoken != TESAC) { *cpp = cp = (union node *)stalloc(sizeof (struct nclist)); cp->type = NCLIST; @@ -526,28 +527,28 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); ap->type = NARG; ap->narg.text = wordtext; ap->narg.backquote = backquotelist; - if (checkkwd = 2, readtoken() != TPIPE) + checkkwd = CHKNL | CHKKWD; + if (readtoken() != TPIPE) break; app = &ap->narg.next; readtoken(); } ap->narg.next = NULL; if (lasttoken != TRP) - noaliases = 0, synexpect(TRP); + synexpect(TRP); cp->nclist.body = list(0, 0); - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; if ((t = readtoken()) != TESAC) { if (t != TENDCASE) - noaliases = 0, synexpect(TENDCASE); + synexpect(TENDCASE); else - checkkwd = 2, readtoken(); + checkkwd = CHKNL | CHKKWD, readtoken(); } cpp = &cp->nclist.next; } - noaliases = 0; /* reset alias expansion */ *cpp = NULL; - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; case TLP: n1 = (union node *)stalloc(sizeof (struct nredir)); @@ -556,13 +557,13 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); n1->nredir.redirect = NULL; if (readtoken() != TRP) synexpect(TRP); - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; case TBEGIN: n1 = list(0, 0); if (readtoken() != TEND) synexpect(TEND); - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; /* Handle an empty command like other simple commands. */ case TBACKGND: @@ -796,7 +797,6 @@ static int readtoken(void) { int t; - int savecheckkwd = checkkwd; struct alias *ap; #ifdef DEBUG int alreadyseen = tokpushback; @@ -805,25 +805,24 @@ readtoken(void) top: t = xxreadtoken(); - if (checkkwd) { - /* - * eat newlines - */ - if (checkkwd == 2) { - checkkwd = 0; - while (t == TNL) { - parseheredoc(); - t = xxreadtoken(); - } - } else - checkkwd = 0; - /* - * check for keywords and aliases - */ - if (t == TWORD && !quoteflag) - { - const char * const *pp; + /* + * eat newlines + */ + if (checkkwd & CHKNL) { + while (t == TNL) { + parseheredoc(); + t = xxreadtoken(); + } + } + /* + * check for keywords and aliases + */ + if (t == TWORD && !quoteflag) + { + const char * const *pp; + + if (checkkwd & CHKKWD) for (pp = parsekwd; *pp; pp++) { if (**pp == *wordtext && equal(*pp, wordtext)) { @@ -832,16 +831,16 @@ readtoken(void) goto out; } } - if (noaliases == 0 && - (ap = lookupalias(wordtext, 1)) != NULL) { - pushstring(ap->val, strlen(ap->val), ap); - checkkwd = savecheckkwd; - goto top; - } + if (checkkwd & CHKALIAS && + (ap = lookupalias(wordtext, 1)) != NULL) { + pushstring(ap->val, strlen(ap->val), ap); + goto top; } -out: - checkkwd = (t == TNOT) ? savecheckkwd : 0; } +out: + if (t != TNOT) + checkkwd = 0; + #ifdef DEBUG if (!alreadyseen) TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); diff --git a/bin/stty/key.c b/bin/stty/key.c index 413f4d58dfa9..12413019f964 100644 --- a/bin/stty/key.c +++ b/bin/stty/key.c @@ -257,14 +257,15 @@ f_rows(struct info *ip) void f_sane(struct info *ip) { + struct termios def; - ip->t.c_cflag = TTYDEF_CFLAG | (ip->t.c_cflag & CLOCAL); - ip->t.c_iflag = TTYDEF_IFLAG; - ip->t.c_iflag |= ICRNL; + cfmakesane(&def); + ip->t.c_cflag = def.c_cflag | (ip->t.c_cflag & CLOCAL); + ip->t.c_iflag = def.c_iflag; /* preserve user-preference flags in lflag */ #define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH) - ip->t.c_lflag = TTYDEF_LFLAG | (ip->t.c_lflag & LKEEP); - ip->t.c_oflag = TTYDEF_OFLAG; + ip->t.c_lflag = def.c_lflag | (ip->t.c_lflag & LKEEP); + ip->t.c_oflag = def.c_oflag; ip->set = 1; } diff --git a/contrib/gdb/gdb/dwarf2read.c b/contrib/gdb/gdb/dwarf2read.c index 4cfc1fe1b6fe..400750d969be 100644 --- a/contrib/gdb/gdb/dwarf2read.c +++ b/contrib/gdb/gdb/dwarf2read.c @@ -5178,7 +5178,7 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd, line_ptr = dwarf_line_buffer + offset; /* read in the header */ - lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read); + lh->total_length = read_initial_length (abfd, line_ptr, &cu->header, &bytes_read); line_ptr += bytes_read; if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size) { diff --git a/contrib/gdb/gdb/mipsfbsd-tdep.c b/contrib/gdb/gdb/mipsfbsd-tdep.c index 0be5d2762c4b..06b01668a71d 100644 --- a/contrib/gdb/gdb/mipsfbsd-tdep.c +++ b/contrib/gdb/gdb/mipsfbsd-tdep.c @@ -187,6 +187,14 @@ static struct core_fns mipsfbsd_core_fns = NULL /* next */ }; +static struct core_fns mipsfbsd_elfcore_fns = +{ + bfd_target_elf_flavour, /* core_flavour */ + default_check_format, /* check_format */ + default_core_sniffer, /* core_sniffer */ + fetch_elfcore_registers, /* core_read_registers */ + NULL /* next */ +}; /* * MIPSFBSD Offsets @@ -576,4 +584,6 @@ _initialize_mipsfbsd_tdep (void) { gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_FREEBSD_ELF, mipsfbsd_init_abi); + add_core_fns (&mipsfbsd_core_fns); + add_core_fns (&mipsfbsd_elfcore_fns); } diff --git a/contrib/top/display.c b/contrib/top/display.c index 94765302dfb2..de91c6cfa45e 100644 --- a/contrib/top/display.c +++ b/contrib/top/display.c @@ -694,7 +694,7 @@ char *text; int width; s = NULL; - width = display_width; + width = screen_width; header_length = strlen(text); if (header_length >= width) { s = malloc((width + 1) * sizeof(char)); @@ -702,6 +702,14 @@ char *text; return (NULL); strncpy(s, text, width); s[width] = '\0'; + } else { + s = malloc((width + 1) * sizeof(char)); + if (s == NULL) + return (NULL); + strncpy(s, text, width); + while (screen_width > header_length) + s[header_length++] = ' '; + s[width] = '\0'; } return (s); } @@ -726,7 +734,7 @@ char *text; if (header_status == ON) { putchar('\n'); - fputs(text, stdout); + standout(text, stdout); lastline++; } else if (header_status == ERASE) diff --git a/contrib/top/top.h b/contrib/top/top.h index a281957c34bd..c51485a558d5 100644 --- a/contrib/top/top.h +++ b/contrib/top/top.h @@ -14,7 +14,7 @@ extern int Header_lines; /* 7 */ /* Maximum number of columns allowed for display */ -#define MAX_COLS 128 +#define MAX_COLS 512 /* Log base 2 of 1024 is 10 (2^10 == 1024) */ #define LOG1024 10 diff --git a/contrib/tzdata/australasia b/contrib/tzdata/australasia index 36a81b0fba24..2c8f7dbfe36c 100644 --- a/contrib/tzdata/australasia +++ b/contrib/tzdata/australasia @@ -1,5 +1,5 @@ #
-# @(#)australasia	8.18
+# @(#)australasia	8.20
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -284,13 +284,26 @@ Zone	Indian/Cocos	6:27:40	-	LMT	1900
 # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
 # 
 
+# From Alexander Krivenyshev (2010-10-24):
+# According to Radio Fiji and Fiji Times online, Fiji will end DST 3 
+# weeks earlier than expected - on March 6, 2011, not March 27, 2011...
+# Here is confirmation from Government of the Republic of the Fiji Islands, 
+# Ministry of Information (fiji.gov.fj) web site:
+# 
+# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
+# 
+# or
+# 
+# http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
+# 
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Fiji	1998	1999	-	Nov	Sun>=1	2:00	1:00	S
 Rule	Fiji	1999	2000	-	Feb	lastSun	3:00	0	-
 Rule	Fiji	2009	only	-	Nov	29	2:00	1:00	S
 Rule	Fiji	2010	only	-	Mar	lastSun	3:00	0	-
 Rule	Fiji	2010	only	-	Oct	24	2:00	1:00	S
-Rule	Fiji	2011	only	-	Mar	lastSun 3:00	0	-
+Rule	Fiji	2011	only	-	Mar	Sun>=1	3:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fiji	11:53:40 -	LMT	1915 Oct 26	# Suva
 			12:00	Fiji	FJ%sT	# Fiji Time
@@ -487,11 +500,21 @@ Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
 # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
 # 
 
+# From Raymond Hughes (2010-10-07):
+# Please see
+# 
+# http://www.mcil.gov.ws
+# ,
+# the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
+# September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
+# to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
+# backwards from 1:00am to 12:00am"
+
 Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
 			-11:26:56 -	LMT	1911
 			-11:30	-	SAMT	1950		# Samoa Time
 			-11:00	-	WST	2010 Sep 26
-			-11:00	1:00	WSDT	2011 Apr 3
+			-11:00	1:00	WSDT	2011 Apr 3 1:00
 			-11:00	-	WST
 
 # Solomon Is
diff --git a/contrib/wpa/hostapd/.gitignore b/contrib/wpa/hostapd/.gitignore
new file mode 100644
index 000000000000..6dd2c2fd35c4
--- /dev/null
+++ b/contrib/wpa/hostapd/.gitignore
@@ -0,0 +1,7 @@
+*.d
+.config
+driver_conf.c
+hostapd
+hostapd_cli
+hlr_auc_gw
+nt_password_hash
diff --git a/contrib/wpa/hostapd/ChangeLog b/contrib/wpa/hostapd/ChangeLog
index 18af4b176b9b..a7f1f108f9a0 100644
--- a/contrib/wpa/hostapd/ChangeLog
+++ b/contrib/wpa/hostapd/ChangeLog
@@ -1,42 +1,108 @@
 ChangeLog for hostapd
 
-2010-01-12 - v0.6.10
-	* 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]
-	* fixed WPS selected registrar expiration for internal PIN registrar
-	* disable PMTU discovery for RADIUS packets
-	* fixed WPS UPnP SSDP on 32-bit targets
-	* fixed WPS AP reconfiguration with drivers that do not use hostapd
-	  MLME
-	* fixed RSN parameter setting for multi-BSS case
-	* added WPS workarounds for known interoperability issues with broken,
-	  deployed implementation
-	* update IEEE 802.11w implementation to match with the published
-	  standard
-	* fixed OpCode when proxying WSC_ACK or WSC_NACK from WPS ER
-	* fixed proxying of WSC_NACK to WPS ER
-	* fixed compilation with newer GnuTLS versions
-	* added support for defining timeout for WPS PINs
+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-03-23 - v0.6.9
-	* driver_nl80211: fixed STA accounting data collection (TX/RX bytes
-	  reported correctly; TX/RX packets not yet available from kernel)
-	* fixed EAPOL/EAP reauthentication when using an external RADIUS
-	  authentication server
-	* driver_prism54: fixed segmentation fault on initialization
-	* 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]
-
-2009-02-15 - v0.6.8
+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)
 	* 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)
diff --git a/contrib/wpa/hostapd/Makefile b/contrib/wpa/hostapd/Makefile
index 3b3d7feb58c0..6d344d2a92ff 100644
--- a/contrib/wpa/hostapd/Makefile
+++ b/contrib/wpa/hostapd/Makefile
@@ -6,14 +6,8 @@ ifndef CFLAGS
 CFLAGS = -MMD -O2 -Wall -g
 endif
 
-# 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
-
 CFLAGS += -I../src
-CFLAGS += -I../src/crypto
 CFLAGS += -I../src/utils
-CFLAGS += -I../src/common
 
 # Uncomment following line and set the path to your kernel tree include
 # directory if your C library does not include all header files.
@@ -38,12 +32,45 @@ CFLAGS += -DCONFIG_NATIVE_WINDOWS
 LIBS += -lws2_32
 endif
 
-OBJS =	hostapd.o ieee802_1x.o eapol_sm.o \
-	ieee802_11.o config.o ieee802_11_auth.o accounting.o \
-	sta_info.o wpa.o ctrl_iface.o \
-	drivers.o preauth.o pmksa_cache.o beacon.o \
-	hw_features.o wme.o ap_list.o \
-	mlme.o vlan_init.o wpa_auth_ie.o
+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
@@ -55,24 +82,51 @@ 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
-OBJS += ../src/crypto/rc4.o
-OBJS += ../src/crypto/md4.o
-OBJS += ../src/crypto/sha1.o
-OBJS += ../src/crypto/des.o
-OBJS += ../src/crypto/aes_wrap.o
-OBJS += ../src/crypto/aes.o
-
-HOBJS=../src/hlr_auc_gw/hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/hlr_auc_gw/milenage.o ../src/crypto/aes_wrap.o ../src/crypto/aes.o
 
 CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
 
 ifdef CONFIG_IAPP
 CFLAGS += -DCONFIG_IAPP
-OBJS += iapp.o
+OBJS += ../src/ap/iapp.o
 endif
 
 ifdef CONFIG_RSN_PREAUTH
@@ -82,78 +136,32 @@ endif
 
 ifdef CONFIG_PEERKEY
 CFLAGS += -DCONFIG_PEERKEY
-OBJS += peerkey.o
+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 += wpa_ft.o
+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
 
-ifdef CONFIG_DRIVER_HOSTAP
-CFLAGS += -DCONFIG_DRIVER_HOSTAP
-OBJS += driver_hostap.o
-endif
-
-ifdef CONFIG_DRIVER_WIRED
-CFLAGS += -DCONFIG_DRIVER_WIRED
-OBJS += driver_wired.o
-endif
-
-ifdef CONFIG_DRIVER_MADWIFI
-CFLAGS += -DCONFIG_DRIVER_MADWIFI
-OBJS += driver_madwifi.o
-CONFIG_L2_PACKET=y
-endif
-
-ifdef CONFIG_DRIVER_ATHEROS
-CFLAGS += -DCONFIG_DRIVER_ATHEROS
-OBJS += driver_atheros.o
-CONFIG_L2_PACKET=y
-endif
-
-ifdef CONFIG_DRIVER_PRISM54
-CFLAGS += -DCONFIG_DRIVER_PRISM54
-OBJS += driver_prism54.o
-endif
-
-ifdef CONFIG_DRIVER_NL80211
-CFLAGS += -DCONFIG_DRIVER_NL80211
-OBJS += driver_nl80211.o radiotap.o
-LIBS += -lnl
-ifdef CONFIG_LIBNL20
-LIBS += -lnl-genl
-CFLAGS += -DCONFIG_LIBNL20
-endif
-endif
-
-ifdef CONFIG_DRIVER_BSD
-CFLAGS += -DCONFIG_DRIVER_BSD
-OBJS += driver_bsd.o
-CONFIG_L2_PACKET=y
-CONFIG_DNET_PCAP=y
-CONFIG_L2_FREEBSD=y
-endif
-
-ifdef CONFIG_DRIVER_TEST
-CFLAGS += -DCONFIG_DRIVER_TEST
-OBJS += driver_test.o
-endif
-
-ifdef CONFIG_DRIVER_NONE
-CFLAGS += -DCONFIG_DRIVER_NONE
-OBJS += driver_none.o
-endif
+include ../src/drivers/drivers.mak
+OBJS += $(DRV_AP_OBJS)
+CFLAGS += $(DRV_AP_CFLAGS)
+LDFLAGS += $(DRV_AP_LDFLAGS)
+LIBS += $(DRV_AP_LIBS)
 
 ifdef CONFIG_L2_PACKET
 ifdef CONFIG_DNET_PCAP
@@ -173,58 +181,60 @@ endif
 
 
 ifdef CONFIG_EAP_MD5
-CFLAGS += -DEAP_MD5
-OBJS += ../src/eap_server/eap_md5.o
+CFLAGS += -DEAP_SERVER_MD5
+OBJS += ../src/eap_server/eap_server_md5.o
 CHAP=y
 endif
 
 ifdef CONFIG_EAP_TLS
-CFLAGS += -DEAP_TLS
-OBJS += ../src/eap_server/eap_tls.o
+CFLAGS += -DEAP_SERVER_TLS
+OBJS += ../src/eap_server/eap_server_tls.o
 TLS_FUNCS=y
 endif
 
 ifdef CONFIG_EAP_PEAP
-CFLAGS += -DEAP_PEAP
-OBJS += ../src/eap_server/eap_peap.o
+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_TTLS
-OBJS += ../src/eap_server/eap_ttls.o
+CFLAGS += -DEAP_SERVER_TTLS
+OBJS += ../src/eap_server/eap_server_ttls.o
 TLS_FUNCS=y
 CHAP=y
 endif
 
 ifdef CONFIG_EAP_MSCHAPV2
-CFLAGS += -DEAP_MSCHAPv2
-OBJS += ../src/eap_server/eap_mschapv2.o
+CFLAGS += -DEAP_SERVER_MSCHAPV2
+OBJS += ../src/eap_server/eap_server_mschapv2.o
 MS_FUNCS=y
 endif
 
 ifdef CONFIG_EAP_GTC
-CFLAGS += -DEAP_GTC
-OBJS += ../src/eap_server/eap_gtc.o
+CFLAGS += -DEAP_SERVER_GTC
+OBJS += ../src/eap_server/eap_server_gtc.o
 endif
 
 ifdef CONFIG_EAP_SIM
-CFLAGS += -DEAP_SIM
-OBJS += ../src/eap_server/eap_sim.o
+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_AKA
-OBJS += ../src/eap_server/eap_aka.o
+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_AKA_PRIME
+CFLAGS += -DEAP_SERVER_AKA_PRIME
 endif
 
 ifdef CONFIG_EAP_SIM_COMMON
@@ -237,47 +247,52 @@ NEED_FIPS186_2_PRF=y
 endif
 
 ifdef CONFIG_EAP_PAX
-CFLAGS += -DEAP_PAX
-OBJS += ../src/eap_server/eap_pax.o ../src/eap_common/eap_pax_common.o
+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_PSK
-OBJS += ../src/eap_server/eap_psk.o ../src/eap_common/eap_psk_common.o
+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_SAKE
-OBJS += ../src/eap_server/eap_sake.o ../src/eap_common/eap_sake_common.o
+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_GPSK
-OBJS += ../src/eap_server/eap_gpsk.o ../src/eap_common/eap_gpsk_common.o
+CFLAGS += -DEAP_SERVER_GPSK
+OBJS += ../src/eap_server/eap_server_gpsk.o ../src/eap_common/eap_gpsk_common.o
 ifdef CONFIG_EAP_GPSK_SHA256
-CFLAGS += -DEAP_GPSK_SHA256
+CFLAGS += -DEAP_SERVER_GPSK_SHA256
 endif
 NEED_SHA256=y
+NEED_AES_OMAC1=y
 endif
 
 ifdef CONFIG_EAP_VENDOR_TEST
-CFLAGS += -DEAP_VENDOR_TEST
-OBJS += ../src/eap_server/eap_vendor_test.o
+CFLAGS += -DEAP_SERVER_VENDOR_TEST
+OBJS += ../src/eap_server/eap_server_vendor_test.o
 endif
 
 ifdef CONFIG_EAP_FAST
-CFLAGS += -DEAP_FAST
-OBJS += ../src/eap_server/eap_fast.o
+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_WSC
+CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
 OBJS += ../src/utils/uuid.o
-OBJS += wps_hostapd.o
-OBJS += ../src/eap_server/eap_wsc.o ../src/eap_common/eap_wsc_common.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
@@ -288,8 +303,35 @@ OBJS += ../src/wps/wps_enrollee.o
 OBJS += ../src/wps/wps_registrar.o
 NEED_DH_GROUPS=y
 NEED_SHA256=y
-NEED_CRYPTO=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
@@ -297,22 +339,28 @@ 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_IKEV2
-OBJS += ../src/eap_server/eap_ikev2.o ../src/eap_server/ikev2.o
+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_TNC
-OBJS += ../src/eap_server/eap_tnc.o
+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
@@ -321,135 +369,150 @@ endif
 endif
 
 # Basic EAP functionality is needed for EAPOL
-OBJS += ../src/eap_server/eap.o
+OBJS += eap_register.o
+OBJS += ../src/eap_server/eap_server.o
 OBJS += ../src/eap_common/eap_common.o
-OBJS += ../src/eap_server/eap_methods.o
-OBJS += ../src/eap_server/eap_identity.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
 
-ifndef CONFIG_TLS
-CONFIG_TLS=openssl
-endif
-
-ifeq ($(CONFIG_TLS), internal)
-ifndef CONFIG_CRYPTO
-CONFIG_CRYPTO=internal
-endif
-endif
-ifeq ($(CONFIG_CRYPTO), libtomcrypt)
-CFLAGS += -DCONFIG_INTERNAL_X509
-endif
-ifeq ($(CONFIG_CRYPTO), internal)
-CFLAGS += -DCONFIG_INTERNAL_X509
-endif
-
-
-ifdef TLS_FUNCS
-# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
-CFLAGS += -DEAP_TLS_FUNCS
-OBJS += ../src/eap_server/eap_tls_common.o
-NEED_TLS_PRF=y
-ifeq ($(CONFIG_TLS), openssl)
-OBJS += ../src/crypto/tls_openssl.o
-LIBS += -lssl -lcrypto
-LIBS_p += -lcrypto
-LIBS_h += -lcrypto
-endif
-ifeq ($(CONFIG_TLS), gnutls)
-OBJS += ../src/crypto/tls_gnutls.o
-LIBS += -lgnutls -lgcrypt -lgpg-error
-LIBS_p += -lgcrypt
-LIBS_h += -lgcrypt
-endif
-ifdef CONFIG_GNUTLS_EXTRA
-CFLAGS += -DCONFIG_GNUTLS_EXTRA
-LIBS += -lgnutls-extra
-endif
-ifeq ($(CONFIG_TLS), internal)
-OBJS += ../src/crypto/tls_internal.o
-OBJS += ../src/tls/tlsv1_common.o ../src/tls/tlsv1_record.o
-OBJS += ../src/tls/tlsv1_cred.o ../src/tls/tlsv1_server.o
-OBJS += ../src/tls/tlsv1_server_write.o ../src/tls/tlsv1_server_read.o
-OBJS += ../src/tls/asn1.o ../src/tls/x509v3.o
-OBJS_p += ../src/tls/asn1.o
-OBJS_p += ../src/crypto/rc4.o ../src/crypto/aes_wrap.o ../src/crypto/aes.o
-NEED_BASE64=y
-CFLAGS += -DCONFIG_TLS_INTERNAL
-CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
-ifeq ($(CONFIG_CRYPTO), internal)
-ifdef CONFIG_INTERNAL_LIBTOMMATH
-CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
-else
-LIBS += -ltommath
-LIBS_p += -ltommath
-endif
-endif
-ifeq ($(CONFIG_CRYPTO), libtomcrypt)
-LIBS += -ltomcrypt -ltfm
-LIBS_p += -ltomcrypt -ltfm
-endif
-endif
-NEED_CRYPTO=y
-else
-OBJS += ../src/crypto/tls_none.o
-endif
-
 ifdef CONFIG_PKCS12
 CFLAGS += -DPKCS12_FUNCS
 endif
 
 ifdef MS_FUNCS
 OBJS += ../src/crypto/ms_funcs.o
-NEED_CRYPTO=y
+NEED_DES=y
+NEED_MD4=y
 endif
 
 ifdef CHAP
 OBJS += ../src/eap_common/chap.o
 endif
 
-ifdef NEED_CRYPTO
-ifndef TLS_FUNCS
+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_p += -lcrypto
 LIBS_h += -lcrypto
 endif
+
 ifeq ($(CONFIG_TLS), gnutls)
-LIBS += -lgcrypt
-LIBS_p += -lgcrypt
-LIBS_h += -lgcrypt
-endif
-ifeq ($(CONFIG_TLS), internal)
-ifeq ($(CONFIG_CRYPTO), libtomcrypt)
-LIBS += -ltomcrypt -ltfm
-LIBS_p += -ltomcrypt -ltfm
+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
-endif
-ifeq ($(CONFIG_TLS), openssl)
-OBJS += ../src/crypto/crypto_openssl.o
-OBJS_p += ../src/crypto/crypto_openssl.o
-HOBJS += ../src/crypto/crypto_openssl.o
-CONFIG_INTERNAL_SHA256=y
-endif
-ifeq ($(CONFIG_TLS), gnutls)
 OBJS += ../src/crypto/crypto_gnutls.o
-OBJS_p += ../src/crypto/crypto_gnutls.o
 HOBJS += ../src/crypto/crypto_gnutls.o
-CONFIG_INTERNAL_SHA256=y
+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
-OBJS_p += ../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 ../src/tls/rsa.o ../src/tls/bignum.o
-OBJS_p += ../src/crypto/crypto_internal.o ../src/tls/rsa.o ../src/tls/bignum.o
+OBJS += ../src/crypto/crypto_internal.o
+NEED_AES_DEC=y
 CFLAGS += -DCONFIG_CRYPTO_INTERNAL
 ifdef CONFIG_INTERNAL_LIBTOMMATH
 CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
@@ -458,7 +521,7 @@ CFLAGS += -DLTM_FAST
 endif
 else
 LIBS += -ltommath
-LIBS_p += -ltommath
+LIBS_h += -ltommath
 endif
 CONFIG_INTERNAL_AES=y
 CONFIG_INTERNAL_DES=y
@@ -466,55 +529,140 @@ 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
-else
+
+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
-CFLAGS += -DINTERNAL_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
-CFLAGS += -DINTERNAL_SHA1
+SHA1OBJS += ../src/crypto/sha1-internal.o
+ifdef NEED_FIPS186_2_PRF
+SHA1OBJS += ../src/crypto/fips_prf_internal.o
 endif
-ifdef CONFIG_INTERNAL_SHA256
-CFLAGS += -DINTERNAL_SHA256
 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
-CFLAGS += -DINTERNAL_MD5
+OBJS += ../src/crypto/md5-internal.o
 endif
+endif
+
+ifdef NEED_MD4
 ifdef CONFIG_INTERNAL_MD4
-CFLAGS += -DINTERNAL_MD4
+OBJS += ../src/crypto/md4-internal.o
 endif
+endif
+
+ifdef NEED_DES
 ifdef CONFIG_INTERNAL_DES
-CFLAGS += -DINTERNAL_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
-
-ifndef NEED_FIPS186_2_PRF
-CFLAGS += -DCONFIG_NO_FIPS186_2_PRF
-endif
-
-ifndef NEED_T_PRF
-CFLAGS += -DCONFIG_NO_T_PRF
-endif
-
-ifndef NEED_TLS_PRF
-CFLAGS += -DCONFIG_NO_TLS_PRF
 endif
 
 ifdef CONFIG_RADIUS_SERVER
@@ -540,16 +688,20 @@ ifdef NEED_BASE64
 OBJS += ../src/utils/base64.o
 endif
 
-ifdef CONFIG_NO_STDOUT_DEBUG
-CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
+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_AES_EXTRAS
-CFLAGS += -DCONFIG_NO_AES_UNWRAP
-CFLAGS += -DCONFIG_NO_AES_CTR -DCONFIG_NO_AES_OMAC1
-CFLAGS += -DCONFIG_NO_AES_EAX -DCONFIG_NO_AES_CBC
-CFLAGS += -DCONFIG_NO_AES_DECRYPT
-CFLAGS += -DCONFIG_NO_AES_ENCRYPT_BLOCK
+ifdef CONFIG_NO_STDOUT_DEBUG
+CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
 endif
 
 ALL=hostapd hostapd_cli
@@ -577,59 +729,63 @@ verify_config:
 	fi
 
 install: all
-	for i in $(ALL); do cp $$i /usr/local/bin/$$i; done
+	for i in $(ALL); do cp -f $$i /usr/local/bin/$$i; done
 
-hostapd: $(OBJS)
-	$(CC) -o hostapd $(OBJS) $(LIBS)
+../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) -o hostapd_cli $(OBJS_c)
+	$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
 
-NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o ../src/crypto/sha1.o ../src/crypto/rc4.o ../src/crypto/md5.o
+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) -o nt_password_hash $(NOBJS) $(LIBS_n)
+	$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
 
 hlr_auc_gw: $(HOBJS)
-	$(CC) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
+	$(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
 
-%.eps: %.fig
-	fig2dev -L eps $*.fig $*.eps
-
-%.png: %.fig
-	fig2dev -L png -m 3 $*.fig | pngtopnm | pnmscale 0.4 | pnmtopng \
-		> $*.png
-
-docs-pics: doc/hostapd.png doc/hostapd.eps
-
-docs: docs-pics
-	(cd ..; doxygen hostapd/doc/doxygen.full; cd hostapd)
-	$(MAKE) -C doc/latex
-	cp doc/latex/refman.pdf hostapd-devel.pdf
-
-docs-fast: docs-pics
-	(cd ..; doxygen hostapd/doc/doxygen.fast; cd hostapd)
-
-clean-docs:
-	rm -rf doc/latex doc/html
-	rm -f doc/hostapd.{eps,png} hostapd-devel.pdf
-
-TEST_SRC_MILENAGE = ../src/hlr_auc_gw/milenage.c ../src/crypto/aes_wrap.c ../src/crypto/aes.c ../src/utils/common.c ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).c
-test-milenage: $(TEST_SRC_MILENAGE)
-	$(CC) -o test-milenage -Wall -Werror $(TEST_SRC_MILENAGE) \
-		-DTEST_MAIN_MILENAGE -I. -DINTERNAL_AES \
-		-I../src/crypto -I../src/utils
-	./test-milenage
-	rm test-milenage
-
 -include $(OBJS:%.o=%.d)
diff --git a/contrib/wpa/hostapd/README b/contrib/wpa/hostapd/README
index eb9aa4815b4f..1af487d76593 100644
--- a/contrib/wpa/hostapd/README
+++ b/contrib/wpa/hostapd/README
@@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
 	  Authenticator and RADIUS authentication server
 ================================================================
 
-Copyright (c) 2002-2009, Jouni Malinen  and contributors
+Copyright (c) 2002-2010, Jouni Malinen  and contributors
 All Rights Reserved.
 
 This program is dual-licensed under both the GPL version 2 and BSD
@@ -95,9 +95,6 @@ Current hardware/software requirements:
 	madwifi driver root directory in .config (see defconfig file for
 	an example: CFLAGS += -I)
 
-	Prism54 driver for Intersil/Conexant Prism GT/Duette/Indigo
-	(http://www.prism54.org/)
-
 	mac80211-based drivers that support AP mode (with driver=nl80211).
 	This includes drivers for Atheros (ath9k) and Broadcom (b43)
 	chipsets.
diff --git a/contrib/wpa/hostapd/README-WPS b/contrib/wpa/hostapd/README-WPS
index e0e370b5bc8f..74f211348ede 100644
--- a/contrib/wpa/hostapd/README-WPS
+++ b/contrib/wpa/hostapd/README-WPS
@@ -62,7 +62,6 @@ includes WPS support and uses madwifi driver interface:
 
 CONFIG_DRIVER_MADWIFI=y
 CFLAGS += -I/usr/src/madwifi-0.9.3
-CONFIG_EAP=y
 CONFIG_WPS=y
 CONFIG_WPS_UPNP=y
 
@@ -196,6 +195,33 @@ 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  [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
 -----------------------------------------------
 
diff --git a/contrib/wpa/hostapd/config.c b/contrib/wpa/hostapd/config_file.c
similarity index 78%
rename from contrib/wpa/hostapd/config.c
rename to contrib/wpa/hostapd/config_file.c
index 692b1a412e02..8916b03db826 100644
--- a/contrib/wpa/hostapd/config.c
+++ b/contrib/wpa/hostapd/config_file.c
@@ -1,7 +1,6 @@
 /*
- * hostapd / Configuration file
- * Copyright (c) 2003-2008, Jouni Malinen 
- * Copyright (c) 2007-2008, Intel Corporation
+ * hostapd / Configuration file parser
+ * Copyright (c) 2003-2009, Jouni Malinen 
  *
  * 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
@@ -13,27 +12,26 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 #ifndef CONFIG_NATIVE_WINDOWS
 #include 
 #endif /* CONFIG_NATIVE_WINDOWS */
 
-#include "hostapd.h"
-#include "driver.h"
-#include "sha1.h"
+#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 "wpa_common.h"
-#include "wpa.h"
-#include "uuid.h"
-#include "eap_common/eap_wsc_common.h"
+#include "ap/wpa_auth.h"
+#include "ap/ap_config.h"
+#include "config_file.h"
 
 
-#define MAX_STA_COUNT 2007
-
-extern struct wpa_driver_ops *hostapd_drivers[];
+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)
 {
@@ -113,168 +111,7 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
 
 	return 0;
 }
-
-
-static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
-{
-	struct hostapd_vlan *vlan, *prev;
-
-	vlan = bss->vlan;
-	prev = NULL;
-	while (vlan) {
-		prev = vlan;
-		vlan = vlan->next;
-		os_free(prev);
-	}
-
-	bss->vlan = NULL;
-}
-
-
-/* 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 void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
-{
-	bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
-	bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
-	bss->logger_syslog = (unsigned int) -1;
-	bss->logger_stdout = (unsigned int) -1;
-
-	bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
-
-	bss->wep_rekeying_period = 300;
-	/* use key0 in individual key and key1 in broadcast key */
-	bss->broadcast_key_idx_min = 1;
-	bss->broadcast_key_idx_max = 2;
-	bss->eap_reauth_period = 3600;
-
-	bss->wpa_group_rekey = 600;
-	bss->wpa_gmk_rekey = 86400;
-	bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
-	bss->wpa_pairwise = WPA_CIPHER_TKIP;
-	bss->wpa_group = WPA_CIPHER_TKIP;
-	bss->rsn_pairwise = 0;
-
-	bss->max_num_sta = MAX_STA_COUNT;
-
-	bss->dtim_period = 2;
-
-	bss->radius_server_auth_port = 1812;
-	bss->ap_max_inactivity = AP_MAX_INACTIVITY;
-	bss->eapol_version = EAPOL_VERSION;
-
-	bss->max_listen_interval = 65535;
-
-#ifdef CONFIG_IEEE80211W
-	bss->assoc_sa_query_max_timeout = 1000;
-	bss->assoc_sa_query_retry_timeout = 201;
-#endif /* CONFIG_IEEE80211W */
-#ifdef EAP_FAST
-	 /* both anonymous and authenticated provisioning */
-	bss->eap_fast_prov = 3;
-	bss->pac_key_lifetime = 7 * 24 * 60 * 60;
-	bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
-#endif /* EAP_FAST */
-}
-
-
-static struct hostapd_config * hostapd_config_defaults(void)
-{
-	struct hostapd_config *conf;
-	struct hostapd_bss_config *bss;
-	int i;
-	const int aCWmin = 4, aCWmax = 10;
-	const struct hostapd_wmm_ac_params ac_bk =
-		{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
-	const struct hostapd_wmm_ac_params ac_be =
-		{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
-	const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
-		{ aCWmin - 1, aCWmin, 2, 3000 / 32, 1 };
-	const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
-		{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 };
-
-	conf = os_zalloc(sizeof(*conf));
-	bss = os_zalloc(sizeof(*bss));
-	if (conf == NULL || bss == NULL) {
-		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
-			   "configuration data.");
-		os_free(conf);
-		os_free(bss);
-		return NULL;
-	}
-
-	/* set default driver based on configuration */
-	conf->driver = hostapd_drivers[0];
-	if (conf->driver == NULL) {
-		wpa_printf(MSG_ERROR, "No driver wrappers registered!");
-		os_free(conf);
-		os_free(bss);
-		return NULL;
-	}
-
-	bss->radius = os_zalloc(sizeof(*bss->radius));
-	if (bss->radius == NULL) {
-		os_free(conf);
-		os_free(bss);
-		return NULL;
-	}
-
-	hostapd_config_defaults_bss(bss);
-
-	conf->num_bss = 1;
-	conf->bss = bss;
-
-	conf->beacon_int = 100;
-	conf->rts_threshold = -1; /* use driver default: 2347 */
-	conf->fragm_threshold = -1; /* user driver default: 2346 */
-	conf->send_probe_response = 1;
-	conf->bridge_packets = INTERNAL_BRIDGE_DO_NOT_CONTROL;
-
-	for (i = 0; i < NUM_TX_QUEUES; i++)
-		conf->tx_queue[i].aifs = -1; /* use hw default */
-
-	conf->wmm_ac_params[0] = ac_be;
-	conf->wmm_ac_params[1] = ac_bk;
-	conf->wmm_ac_params[2] = ac_vi;
-	conf->wmm_ac_params[3] = ac_vo;
-
-#ifdef CONFIG_IEEE80211N
-	conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
-#endif /* CONFIG_IEEE80211N */
-
-	return conf;
-}
-
-
-int hostapd_mac_comp(const void *a, const void *b)
-{
-	return os_memcmp(a, b, sizeof(macaddr));
-}
-
-
-int hostapd_mac_comp_empty(const void *a)
-{
-	macaddr empty = { 0 };
-	return os_memcmp(a, empty, sizeof(macaddr));
-}
+#endif /* CONFIG_NO_VLAN */
 
 
 static int hostapd_acl_comp(const void *a, const void *b)
@@ -357,133 +194,6 @@ static int hostapd_config_read_maclist(const char *fname,
 }
 
 
-static int hostapd_config_read_wpa_psk(const char *fname,
-				       struct hostapd_ssid *ssid)
-{
-	FILE *f;
-	char buf[128], *pos;
-	int line = 0, ret = 0, len, ok;
-	u8 addr[ETH_ALEN];
-	struct hostapd_wpa_psk *psk;
-
-	if (!fname)
-		return 0;
-
-	f = fopen(fname, "r");
-	if (!f) {
-		wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname);
-		return -1;
-	}
-
-	while (fgets(buf, sizeof(buf), f)) {
-		line++;
-
-		if (buf[0] == '#')
-			continue;
-		pos = buf;
-		while (*pos != '\0') {
-			if (*pos == '\n') {
-				*pos = '\0';
-				break;
-			}
-			pos++;
-		}
-		if (buf[0] == '\0')
-			continue;
-
-		if (hwaddr_aton(buf, addr)) {
-			wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
-				   "line %d in '%s'", buf, line, fname);
-			ret = -1;
-			break;
-		}
-
-		psk = os_zalloc(sizeof(*psk));
-		if (psk == NULL) {
-			wpa_printf(MSG_ERROR, "WPA PSK allocation failed");
-			ret = -1;
-			break;
-		}
-		if (is_zero_ether_addr(addr))
-			psk->group = 1;
-		else
-			os_memcpy(psk->addr, addr, ETH_ALEN);
-
-		pos = buf + 17;
-		if (*pos == '\0') {
-			wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
-				   line, fname);
-			os_free(psk);
-			ret = -1;
-			break;
-		}
-		pos++;
-
-		ok = 0;
-		len = os_strlen(pos);
-		if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
-			ok = 1;
-		else if (len >= 8 && len < 64) {
-			pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
-				    4096, psk->psk, PMK_LEN);
-			ok = 1;
-		}
-		if (!ok) {
-			wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
-				   "'%s'", pos, line, fname);
-			os_free(psk);
-			ret = -1;
-			break;
-		}
-
-		psk->next = ssid->wpa_psk;
-		ssid->wpa_psk = psk;
-	}
-
-	fclose(f);
-
-	return ret;
-}
-
-
-int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
-{
-	struct hostapd_ssid *ssid = &conf->ssid;
-
-	if (ssid->wpa_passphrase != NULL) {
-		if (ssid->wpa_psk != NULL) {
-			wpa_printf(MSG_ERROR, "Warning: both WPA PSK and "
-				   "passphrase set. Using passphrase.");
-			os_free(ssid->wpa_psk);
-		}
-		ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
-		if (ssid->wpa_psk == NULL) {
-			wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
-			return -1;
-		}
-		wpa_hexdump_ascii(MSG_DEBUG, "SSID",
-				  (u8 *) ssid->ssid, ssid->ssid_len);
-		wpa_hexdump_ascii(MSG_DEBUG, "PSK (ASCII passphrase)",
-				  (u8 *) ssid->wpa_passphrase,
-				  os_strlen(ssid->wpa_passphrase));
-		pbkdf2_sha1(ssid->wpa_passphrase,
-			    ssid->ssid, ssid->ssid_len,
-			    4096, ssid->wpa_psk->psk, PMK_LEN);
-		wpa_hexdump(MSG_DEBUG, "PSK (from passphrase)",
-			    ssid->wpa_psk->psk, PMK_LEN);
-		ssid->wpa_psk->group = 1;
-	}
-
-	if (ssid->wpa_psk_file) {
-		if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file,
-						&conf->ssid))
-			return -1;
-	}
-
-	return 0;
-}
-
-
 #ifdef EAP_SERVER
 static int hostapd_config_read_eap_user(const char *fname,
 					struct hostapd_bss_config *conf)
@@ -761,6 +471,7 @@ static int hostapd_config_read_eap_user(const char *fname,
 #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,
@@ -786,6 +497,7 @@ hostapd_config_read_radius_addr(struct hostapd_radius_server **server,
 
 	return ret;
 }
+#endif /* CONFIG_NO_RADIUS */
 
 
 static int hostapd_config_parse_key_mgmt(int line, const char *value)
@@ -899,86 +611,6 @@ static int hostapd_config_parse_cipher(int line, const char *value)
 }
 
 
-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;
-}
-
-
 static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
 				   char *val)
 {
@@ -1089,6 +721,26 @@ static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
 }
 
 
+/* 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 ||
@@ -1389,6 +1041,86 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
 #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)
@@ -1417,6 +1149,16 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 		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)) {
@@ -1455,10 +1197,10 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 			int j;
 			/* clear to get error below if setting is invalid */
 			conf->driver = NULL;
-			for (j = 0; hostapd_drivers[j]; j++) {
-				if (os_strcmp(pos, hostapd_drivers[j]->name) ==
-				    0) {
-					conf->driver = hostapd_drivers[j];
+			for (j = 0; wpa_drivers[j]; j++) {
+				if (os_strcmp(pos, wpa_drivers[j]->name) == 0)
+				{
+					conf->driver = wpa_drivers[j];
 					break;
 				}
 			}
@@ -1520,6 +1262,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 					   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) {
@@ -1569,7 +1313,7 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 		} else if (os_strcmp(buf, "dh_file") == 0) {
 			os_free(bss->dh_file);
 			bss->dh_file = os_strdup(pos);
-#ifdef EAP_FAST
+#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);
@@ -1611,18 +1355,18 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 			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_FAST */
-#ifdef EAP_SIM
+#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_SIM */
-#ifdef EAP_TNC
+#endif /* EAP_SERVER_SIM */
+#ifdef EAP_SERVER_TNC
 		} else if (os_strcmp(buf, "tnc") == 0) {
 			bss->tnc = atoi(pos);
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 #endif /* EAP_SERVER */
 		} else if (os_strcmp(buf, "eap_message") == 0) {
 			char *term;
@@ -1697,6 +1441,7 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 			}
 		} 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,
@@ -1750,7 +1495,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 			bss->radius->retry_primary_interval = atoi(pos);
 		} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0)
 		{
-			bss->radius->acct_interim_interval = atoi(pos);
+			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) {
@@ -1896,6 +1642,7 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 		} 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);
@@ -1927,6 +1674,7 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 			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);
@@ -2022,8 +1770,6 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 				conf->preamble = LONG_PREAMBLE;
 		} else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
 			bss->ignore_broadcast_ssid = atoi(pos);
-		} else if (os_strcmp(buf, "bridge_packets") == 0) {
-			conf->bridge_packets = atoi(pos);
 		} else if (os_strcmp(buf, "wep_default_key") == 0) {
 			bss->ssid.wep.idx = atoi(pos);
 			if (bss->ssid.wep.idx > 3) {
@@ -2042,6 +1788,7 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 					   "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) {
@@ -2054,12 +1801,7 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 		} else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
 			bss->ssid.vlan_tagged_interface = os_strdup(pos);
 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
-		} else if (os_strcmp(buf, "passive_scan_interval") == 0) {
-			conf->passive_scan_interval = atoi(pos);
-		} else if (os_strcmp(buf, "passive_scan_listen") == 0) {
-			conf->passive_scan_listen = atoi(pos);
-		} else if (os_strcmp(buf, "passive_scan_mode") == 0) {
-			conf->passive_scan_mode = atoi(pos);
+#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) {
@@ -2073,6 +1815,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 		} 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)) {
@@ -2087,13 +1831,7 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 				errors++;
 			}
 		} else if (os_strcmp(buf, "bssid") == 0) {
-			if (bss == conf->bss &&
-			    (!conf->driver || !conf->driver->init_bssid)) {
-				wpa_printf(MSG_ERROR, "Line %d: bssid item "
-					   "not allowed for the default "
-					   "interface and this driver", line);
-				errors++;
-			} else if (hwaddr_aton(pos, bss->bssid)) {
+			if (hwaddr_aton(pos, bss->bssid)) {
 				wpa_printf(MSG_ERROR, "Line %d: invalid bssid "
 					   "item", line);
 				errors++;
@@ -2309,314 +2047,3 @@ struct hostapd_config * hostapd_config_read(const char *fname)
 
 	return conf;
 }
-
-
-int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b)
-{
-	int i;
-
-	if (a->idx != b->idx || a->default_len != b->default_len)
-		return 1;
-	for (i = 0; i < NUM_WEP_KEYS; i++)
-		if (a->len[i] != b->len[i] ||
-		    os_memcmp(a->key[i], b->key[i], a->len[i]) != 0)
-			return 1;
-	return 0;
-}
-
-
-static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
-				       int num_servers)
-{
-	int i;
-
-	for (i = 0; i < num_servers; i++) {
-		os_free(servers[i].shared_secret);
-	}
-	os_free(servers);
-}
-
-
-static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
-{
-	os_free(user->identity);
-	os_free(user->password);
-	os_free(user);
-}
-
-
-static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
-{
-	int i;
-	for (i = 0; i < NUM_WEP_KEYS; i++) {
-		os_free(keys->key[i]);
-		keys->key[i] = NULL;
-	}
-}
-
-
-static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
-{
-	struct hostapd_wpa_psk *psk, *prev;
-	struct hostapd_eap_user *user, *prev_user;
-
-	if (conf == NULL)
-		return;
-
-	psk = conf->ssid.wpa_psk;
-	while (psk) {
-		prev = psk;
-		psk = psk->next;
-		os_free(prev);
-	}
-
-	os_free(conf->ssid.wpa_passphrase);
-	os_free(conf->ssid.wpa_psk_file);
-#ifdef CONFIG_FULL_DYNAMIC_VLAN
-	os_free(conf->ssid.vlan_tagged_interface);
-#endif /* CONFIG_FULL_DYNAMIC_VLAN */
-
-	user = conf->eap_user;
-	while (user) {
-		prev_user = user;
-		user = user->next;
-		hostapd_config_free_eap_user(prev_user);
-	}
-
-	os_free(conf->dump_log_name);
-	os_free(conf->eap_req_id_text);
-	os_free(conf->accept_mac);
-	os_free(conf->deny_mac);
-	os_free(conf->nas_identifier);
-	hostapd_config_free_radius(conf->radius->auth_servers,
-				   conf->radius->num_auth_servers);
-	hostapd_config_free_radius(conf->radius->acct_servers,
-				   conf->radius->num_acct_servers);
-	os_free(conf->rsn_preauth_interfaces);
-	os_free(conf->ctrl_interface);
-	os_free(conf->ca_cert);
-	os_free(conf->server_cert);
-	os_free(conf->private_key);
-	os_free(conf->private_key_passwd);
-	os_free(conf->dh_file);
-	os_free(conf->pac_opaque_encr_key);
-	os_free(conf->eap_fast_a_id);
-	os_free(conf->eap_fast_a_id_info);
-	os_free(conf->eap_sim_db);
-	os_free(conf->radius_server_clients);
-	os_free(conf->test_socket);
-	os_free(conf->radius);
-	hostapd_config_free_vlan(conf);
-	if (conf->ssid.dyn_vlan_keys) {
-		struct hostapd_ssid *ssid = &conf->ssid;
-		size_t i;
-		for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
-			if (ssid->dyn_vlan_keys[i] == NULL)
-				continue;
-			hostapd_config_free_wep(ssid->dyn_vlan_keys[i]);
-			os_free(ssid->dyn_vlan_keys[i]);
-		}
-		os_free(ssid->dyn_vlan_keys);
-		ssid->dyn_vlan_keys = NULL;
-	}
-
-#ifdef CONFIG_IEEE80211R
-	{
-		struct ft_remote_r0kh *r0kh, *r0kh_prev;
-		struct ft_remote_r1kh *r1kh, *r1kh_prev;
-
-		r0kh = conf->r0kh_list;
-		conf->r0kh_list = NULL;
-		while (r0kh) {
-			r0kh_prev = r0kh;
-			r0kh = r0kh->next;
-			os_free(r0kh_prev);
-		}
-
-		r1kh = conf->r1kh_list;
-		conf->r1kh_list = NULL;
-		while (r1kh) {
-			r1kh_prev = r1kh;
-			r1kh = r1kh->next;
-			os_free(r1kh_prev);
-		}
-	}
-#endif /* CONFIG_IEEE80211R */
-
-#ifdef CONFIG_WPS
-	os_free(conf->wps_pin_requests);
-	os_free(conf->device_name);
-	os_free(conf->manufacturer);
-	os_free(conf->model_name);
-	os_free(conf->model_number);
-	os_free(conf->serial_number);
-	os_free(conf->device_type);
-	os_free(conf->config_methods);
-	os_free(conf->ap_pin);
-	os_free(conf->extra_cred);
-	os_free(conf->ap_settings);
-	os_free(conf->upnp_iface);
-	os_free(conf->friendly_name);
-	os_free(conf->manufacturer_url);
-	os_free(conf->model_description);
-	os_free(conf->model_url);
-	os_free(conf->upc);
-#endif /* CONFIG_WPS */
-}
-
-
-/**
- * hostapd_config_free - Free hostapd configuration
- * @conf: Configuration data from hostapd_config_read().
- */
-void hostapd_config_free(struct hostapd_config *conf)
-{
-	size_t i;
-
-	if (conf == NULL)
-		return;
-
-	for (i = 0; i < conf->num_bss; i++)
-		hostapd_config_free_bss(&conf->bss[i]);
-	os_free(conf->bss);
-	os_free(conf->supported_rates);
-	os_free(conf->basic_rates);
-
-	os_free(conf);
-}
-
-
-/**
- * hostapd_maclist_found - Find a MAC address from a list
- * @list: MAC address list
- * @num_entries: Number of addresses in the list
- * @addr: Address to search for
- * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed
- * Returns: 1 if address is in the list or 0 if not.
- *
- * Perform a binary search for given MAC address from a pre-sorted list.
- */
-int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
-			  const u8 *addr, int *vlan_id)
-{
-	int start, end, middle, res;
-
-	start = 0;
-	end = num_entries - 1;
-
-	while (start <= end) {
-		middle = (start + end) / 2;
-		res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
-		if (res == 0) {
-			if (vlan_id)
-				*vlan_id = list[middle].vlan_id;
-			return 1;
-		}
-		if (res < 0)
-			start = middle + 1;
-		else
-			end = middle - 1;
-	}
-
-	return 0;
-}
-
-
-int hostapd_rate_found(int *list, int rate)
-{
-	int i;
-
-	if (list == NULL)
-		return 0;
-
-	for (i = 0; list[i] >= 0; i++)
-		if (list[i] == rate)
-			return 1;
-
-	return 0;
-}
-
-
-const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
-{
-	struct hostapd_vlan *v = vlan;
-	while (v) {
-		if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD)
-			return v->ifname;
-		v = v->next;
-	}
-	return NULL;
-}
-
-
-const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
-			   const u8 *addr, const u8 *prev_psk)
-{
-	struct hostapd_wpa_psk *psk;
-	int next_ok = prev_psk == NULL;
-
-	for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
-		if (next_ok &&
-		    (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0))
-			return psk->psk;
-
-		if (psk->psk == prev_psk)
-			next_ok = 1;
-	}
-
-	return NULL;
-}
-
-
-const struct hostapd_eap_user *
-hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
-		     size_t identity_len, int phase2)
-{
-	struct hostapd_eap_user *user = conf->eap_user;
-
-#ifdef CONFIG_WPS
-	if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
-	    os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
-		static struct hostapd_eap_user wsc_enrollee;
-		os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
-		wsc_enrollee.methods[0].method = eap_server_get_type(
-			"WSC", &wsc_enrollee.methods[0].vendor);
-		return &wsc_enrollee;
-	}
-
-	if (conf->wps_state && conf->ap_pin &&
-	    identity_len == WSC_ID_REGISTRAR_LEN &&
-	    os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
-		static struct hostapd_eap_user wsc_registrar;
-		os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
-		wsc_registrar.methods[0].method = eap_server_get_type(
-			"WSC", &wsc_registrar.methods[0].vendor);
-		wsc_registrar.password = (u8 *) conf->ap_pin;
-		wsc_registrar.password_len = os_strlen(conf->ap_pin);
-		return &wsc_registrar;
-	}
-#endif /* CONFIG_WPS */
-
-	while (user) {
-		if (!phase2 && user->identity == NULL) {
-			/* Wildcard match */
-			break;
-		}
-
-		if (user->phase2 == !!phase2 && user->wildcard_prefix &&
-		    identity_len >= user->identity_len &&
-		    os_memcmp(user->identity, identity, user->identity_len) ==
-		    0) {
-			/* Wildcard prefix match */
-			break;
-		}
-
-		if (user->phase2 == !!phase2 &&
-		    user->identity_len == identity_len &&
-		    os_memcmp(user->identity, identity, identity_len) == 0)
-			break;
-		user = user->next;
-	}
-
-	return user;
-}
diff --git a/contrib/wpa/hostapd/config_file.h b/contrib/wpa/hostapd/config_file.h
new file mode 100644
index 000000000000..7111a9a3167f
--- /dev/null
+++ b/contrib/wpa/hostapd/config_file.h
@@ -0,0 +1,20 @@
+/*
+ * hostapd / Configuration file parser
+ * Copyright (c) 2003-2009, Jouni Malinen 
+ *
+ * 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/contrib/wpa/hostapd/ctrl_iface.c b/contrib/wpa/hostapd/ctrl_iface.c
index 9dec7247cdd7..9c47ba8bb76d 100644
--- a/contrib/wpa/hostapd/ctrl_iface.c
+++ b/contrib/wpa/hostapd/ctrl_iface.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / UNIX domain socket -based control interface
- * Copyright (c) 2004-2008, Jouni Malinen 
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -12,7 +12,7 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
 #ifndef CONFIG_NATIVE_WINDOWS
 
@@ -20,17 +20,21 @@
 #include 
 #include 
 
-#include "hostapd.h"
-#include "eloop.h"
-#include "config.h"
-#include "ieee802_1x.h"
-#include "wpa.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 "ieee802_11.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"
-#include "sta_info.h"
-#include "accounting.h"
-#include "wps_hostapd.h"
 
 
 struct wpa_ctrl_dst {
@@ -125,84 +129,6 @@ static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
 }
 
 
-static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
-				      struct sta_info *sta,
-				      char *buf, size_t buflen)
-{
-	int len, res, ret;
-
-	if (sta == NULL) {
-		ret = os_snprintf(buf, buflen, "FAIL\n");
-		if (ret < 0 || (size_t) ret >= buflen)
-			return 0;
-		return ret;
-	}
-
-	len = 0;
-	ret = os_snprintf(buf + len, buflen - len, MACSTR "\n",
-			  MAC2STR(sta->addr));
-	if (ret < 0 || (size_t) ret >= buflen - len)
-		return len;
-	len += ret;
-
-	res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
-	if (res >= 0)
-		len += res;
-	res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len);
-	if (res >= 0)
-		len += res;
-	res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
-	if (res >= 0)
-		len += res;
-
-	return len;
-}
-
-
-static int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
-					char *buf, size_t buflen)
-{
-	return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen);
-}
-
-
-static int hostapd_ctrl_iface_sta(struct hostapd_data *hapd,
-				  const char *txtaddr,
-				  char *buf, size_t buflen)
-{
-	u8 addr[ETH_ALEN];
-	int ret;
-
-	if (hwaddr_aton(txtaddr, addr)) {
-		ret = os_snprintf(buf, buflen, "FAIL\n");
-		if (ret < 0 || (size_t) ret >= buflen)
-			return 0;
-		return ret;
-	}
-	return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr),
-					  buf, buflen);
-}
-
-
-static int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd,
-				       const char *txtaddr,
-				       char *buf, size_t buflen)
-{
-	u8 addr[ETH_ALEN];
-	struct sta_info *sta;
-	int ret;
-
-	if (hwaddr_aton(txtaddr, addr) ||
-	    (sta = ap_get_sta(hapd, addr)) == NULL) {
-		ret = os_snprintf(buf, buflen, "FAIL\n");
-		if (ret < 0 || (size_t) ret >= buflen)
-			return 0;
-		return ret;
-	}		
-	return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
-}
-
-
 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
 				      const char *txtaddr)
 {
@@ -229,7 +155,100 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
 }
 
 
+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)
 {
@@ -238,14 +257,15 @@ static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
 
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
 
-	if (hwaddr_aton(txtaddr, addr))
+	if (hwaddr_aton(txtaddr, addr) ||
+	    os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
 		return -1;
 
-	os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
 	ieee802_11_send_sa_query_req(hapd, addr, trans_id);
 
 	return 0;
 }
+#endif /* NEED_AP_MLME */
 #endif /* CONFIG_IEEE80211W */
 
 
@@ -269,6 +289,83 @@ static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
 
 	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 */
 
 
@@ -324,6 +421,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
 			else
 				reply_len += res;
 		}
+#ifndef CONFIG_NO_RADIUS
 		if (reply_len >= 0) {
 			res = radius_client_get_mib(hapd->radius,
 						    reply + reply_len,
@@ -333,6 +431,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
 			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);
@@ -355,10 +454,18 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
 	} 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) {
@@ -367,6 +474,14 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
 	} 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);
@@ -507,6 +622,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
 	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;
diff --git a/contrib/wpa/hostapd/ctrl_iface.h b/contrib/wpa/hostapd/ctrl_iface.h
index d86de8c94066..c997141a1510 100644
--- a/contrib/wpa/hostapd/ctrl_iface.h
+++ b/contrib/wpa/hostapd/ctrl_iface.h
@@ -15,7 +15,18 @@
 #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/contrib/wpa/hostapd/defconfig b/contrib/wpa/hostapd/defconfig
index 96a023d2e65d..1d28c022fa46 100644
--- a/contrib/wpa/hostapd/defconfig
+++ b/contrib/wpa/hostapd/defconfig
@@ -19,9 +19,6 @@ CONFIG_DRIVER_HOSTAP=y
 #CONFIG_DRIVER_MADWIFI=y
 #CFLAGS += -I../../madwifi # change to the madwifi source directory
 
-# Driver interface for Prism54 driver
-#CONFIG_DRIVER_PRISM54=y
-
 # Driver interface for drivers using the nl80211 kernel interface
 #CONFIG_DRIVER_NL80211=y
 # driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
@@ -35,6 +32,8 @@ CONFIG_DRIVER_HOSTAP=y
 #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
@@ -142,3 +141,35 @@ CONFIG_IPV6=y
 # 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/contrib/wpa/hostapd/doc/code_structure.doxygen b/contrib/wpa/hostapd/doc/code_structure.doxygen
deleted file mode 100644
index fdcf725b5d7f..000000000000
--- a/contrib/wpa/hostapd/doc/code_structure.doxygen
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
-\page code_structure Structure of the source code
-
-
-*/
diff --git a/contrib/wpa/hostapd/doc/ctrl_iface.doxygen b/contrib/wpa/hostapd/doc/ctrl_iface.doxygen
deleted file mode 100644
index 76cfc6a6b79c..000000000000
--- a/contrib/wpa/hostapd/doc/ctrl_iface.doxygen
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
-\page ctrl_iface_page Control interface
-
-hostapd implements a control interface that can be used by
-external programs to control the operations of the hostapd
-daemon and to get status information and event notifications. There is
-a small C library, in a form of a single C file, wpa_ctrl.c, that
-provides helper functions to facilitate the use of the control
-interface. External programs can link this file into them and then use
-the library functions documented in wpa_ctrl.h to interact with
-%wpa_supplicant. This library can also be used with C++. hostapd_cli.c
-is an example program using this library.
-
-There are multiple mechanisms for inter-process communication. For
-example, Linux version of hostapd is using UNIX domain sockets for the
-control interface. The use of the functions defined in wpa_ctrl.h can
-be used to hide the details of the used IPC from external programs.
-
-
-\section using_ctrl_iface Using the control interface
-
-External programs, e.g., a GUI or a configuration utility, that need to
-communicate with hostapd should link in wpa_ctrl.c. This
-allows them to use helper functions to open connection to the control
-interface with wpa_ctrl_open() and to send commands with
-wpa_ctrl_request().
-
-hostapd uses the control interface for two types of communication:
-commands and unsolicited event messages. Commands are a pair of
-messages, a request from the external program and a response from
-hostapd. These can be executed using wpa_ctrl_request().
-Unsolicited event messages are sent by hostapd to the control
-interface connection without specific request from the external program
-for receiving each message. However, the external program needs to
-attach to the control interface with wpa_ctrl_attach() to receive these
-unsolicited messages.
-
-If the control interface connection is used both for commands and
-unsolicited event messages, there is potential for receiving an
-unsolicited message between the command request and response.
-wpa_ctrl_request() caller will need to supply a callback, msg_cb,
-for processing these messages. Often it is easier to open two
-control interface connections by calling wpa_ctrl_open() twice and
-then use one of the connections for commands and the other one for
-unsolicited messages. This way command request/response pairs will
-not be broken by unsolicited messages. wpa_cli is an example of how
-to use only one connection for both purposes and wpa_gui demonstrates
-how to use two separate connections.
-
-Once the control interface connection is not needed anymore, it should
-be closed by calling wpa_ctrl_close(). If the connection was used for
-unsolicited event messages, it should be first detached by calling
-wpa_ctrl_detach().
-
-
-\section ctrl_iface_cmds Control interface commands
-
-Following commands can be used with wpa_ctrl_request():
-
-\subsection ctrl_iface_PING PING
-
-This command can be used to test whether hostapd is replying
-to the control interface commands. The expected reply is \c PONG if the
-connection is open and hostapd is processing commands.
-
-*/
diff --git a/contrib/wpa/hostapd/doc/doxygen.fast b/contrib/wpa/hostapd/doc/doxygen.fast
deleted file mode 100644
index 650c73d817f4..000000000000
--- a/contrib/wpa/hostapd/doc/doxygen.fast
+++ /dev/null
@@ -1,238 +0,0 @@
-# Doxyfile 1.4.4
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-PROJECT_NAME           = hostapd
-PROJECT_NUMBER         = 0.6.x
-OUTPUT_DIRECTORY       = hostapd/doc
-CREATE_SUBDIRS         = NO
-OUTPUT_LANGUAGE        = English
-BRIEF_MEMBER_DESC      = YES
-REPEAT_BRIEF           = YES
-ABBREVIATE_BRIEF       = "The $name class" \
-                         "The $name widget" \
-                         "The $name file" \
-                         is \
-                         provides \
-                         specifies \
-                         contains \
-                         represents \
-                         a \
-                         an \
-                         the
-ALWAYS_DETAILED_SEC    = NO
-INLINE_INHERITED_MEMB  = NO
-FULL_PATH_NAMES        = YES
-STRIP_FROM_PATH        =
-STRIP_FROM_INC_PATH    = 
-SHORT_NAMES            = NO
-JAVADOC_AUTOBRIEF      = NO
-MULTILINE_CPP_IS_BRIEF = NO
-DETAILS_AT_TOP         = NO
-INHERIT_DOCS           = YES
-DISTRIBUTE_GROUP_DOC   = NO
-SEPARATE_MEMBER_PAGES  = NO
-TAB_SIZE               = 8
-ALIASES                = 
-OPTIMIZE_OUTPUT_FOR_C  = YES
-OPTIMIZE_OUTPUT_JAVA   = NO
-SUBGROUPING            = YES
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-EXTRACT_ALL            = NO
-EXTRACT_PRIVATE        = NO
-EXTRACT_STATIC         = NO
-EXTRACT_LOCAL_CLASSES  = YES
-EXTRACT_LOCAL_METHODS  = NO
-HIDE_UNDOC_MEMBERS     = NO
-HIDE_UNDOC_CLASSES     = NO
-HIDE_FRIEND_COMPOUNDS  = NO
-HIDE_IN_BODY_DOCS      = NO
-INTERNAL_DOCS          = NO
-CASE_SENSE_NAMES       = YES
-HIDE_SCOPE_NAMES       = NO
-SHOW_INCLUDE_FILES     = YES
-INLINE_INFO            = YES
-SORT_MEMBER_DOCS       = YES
-SORT_BRIEF_DOCS        = NO
-SORT_BY_SCOPE_NAME     = NO
-GENERATE_TODOLIST      = YES
-GENERATE_TESTLIST      = YES
-GENERATE_BUGLIST       = YES
-GENERATE_DEPRECATEDLIST= YES
-ENABLED_SECTIONS       = 
-MAX_INITIALIZER_LINES  = 30
-SHOW_USED_FILES        = YES
-SHOW_DIRECTORIES       = YES
-FILE_VERSION_FILTER    = 
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-QUIET                  = NO
-WARNINGS               = YES
-WARN_IF_UNDOCUMENTED   = NO
-WARN_IF_DOC_ERROR      = YES
-WARN_NO_PARAMDOC       = YES
-WARN_FORMAT            = "$file:$line: $text"
-WARN_LOGFILE           = 
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-INPUT                  = hostapd \
-	src/common \
-	src/crypto \
-	src/eap_common \
-	src/eap_server \
-	src/l2_packet \
-	src/radius \
-	src/rsn_supp \
-	src/tls \
-	src/utils \
-	src/wps
-FILE_PATTERNS          = *.c *.h *.doxygen
-RECURSIVE              = YES
-EXCLUDE                = 
-EXCLUDE_SYMLINKS       = NO
-EXCLUDE_PATTERNS       = 
-EXAMPLE_PATH           = 
-EXAMPLE_PATTERNS       = *
-EXAMPLE_RECURSIVE      = NO
-IMAGE_PATH             = hostapd/doc
-INPUT_FILTER           = kerneldoc2doxygen.pl
-FILTER_PATTERNS        = 
-FILTER_SOURCE_FILES    = YES
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-SOURCE_BROWSER         = YES
-INLINE_SOURCES         = NO
-STRIP_CODE_COMMENTS    = YES
-REFERENCED_BY_RELATION = NO
-REFERENCES_RELATION    = NO
-VERBATIM_HEADERS       = NO
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-ALPHABETICAL_INDEX     = YES
-COLS_IN_ALPHA_INDEX    = 3
-IGNORE_PREFIX          = 
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-GENERATE_HTML          = YES
-HTML_OUTPUT            = html
-HTML_FILE_EXTENSION    = .html
-HTML_HEADER            = 
-HTML_FOOTER            = 
-HTML_STYLESHEET        = 
-HTML_ALIGN_MEMBERS     = YES
-GENERATE_HTMLHELP      = NO
-CHM_FILE               = 
-HHC_LOCATION           = 
-GENERATE_CHI           = NO
-BINARY_TOC             = NO
-TOC_EXPAND             = NO
-DISABLE_INDEX          = NO
-ENUM_VALUES_PER_LINE   = 4
-GENERATE_TREEVIEW      = NO
-TREEVIEW_WIDTH         = 250
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-GENERATE_LATEX         = NO
-LATEX_OUTPUT           = latex
-LATEX_CMD_NAME         = latex
-MAKEINDEX_CMD_NAME     = makeindex
-COMPACT_LATEX          = NO
-PAPER_TYPE             = a4wide
-EXTRA_PACKAGES         = 
-LATEX_HEADER           = 
-PDF_HYPERLINKS         = YES
-USE_PDFLATEX           = YES
-LATEX_BATCHMODE        = NO
-LATEX_HIDE_INDICES     = NO
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-GENERATE_RTF           = NO
-RTF_OUTPUT             = rtf
-COMPACT_RTF            = NO
-RTF_HYPERLINKS         = NO
-RTF_STYLESHEET_FILE    = 
-RTF_EXTENSIONS_FILE    = 
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-GENERATE_MAN           = NO
-MAN_OUTPUT             = man
-MAN_EXTENSION          = .3
-MAN_LINKS              = NO
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-GENERATE_XML           = NO
-XML_OUTPUT             = xml
-XML_SCHEMA             = 
-XML_DTD                = 
-XML_PROGRAMLISTING     = YES
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-GENERATE_AUTOGEN_DEF   = NO
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-GENERATE_PERLMOD       = NO
-PERLMOD_LATEX          = NO
-PERLMOD_PRETTY         = YES
-PERLMOD_MAKEVAR_PREFIX = 
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
-#---------------------------------------------------------------------------
-ENABLE_PREPROCESSING   = YES
-MACRO_EXPANSION        = NO
-EXPAND_ONLY_PREDEF     = NO
-SEARCH_INCLUDES        = YES
-INCLUDE_PATH           = 
-INCLUDE_FILE_PATTERNS  = 
-PREDEFINED             = RADIUS_SERVER EAP_SERVER EAP_SIM
-EXPAND_AS_DEFINED      = 
-SKIP_FUNCTION_MACROS   = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references   
-#---------------------------------------------------------------------------
-TAGFILES               = 
-GENERATE_TAGFILE       = 
-ALLEXTERNALS           = NO
-EXTERNAL_GROUPS        = YES
-PERL_PATH              = /usr/bin/perl
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
-#---------------------------------------------------------------------------
-CLASS_DIAGRAMS         = NO
-HIDE_UNDOC_RELATIONS   = YES
-HAVE_DOT               = NO
-CLASS_GRAPH            = YES
-COLLABORATION_GRAPH    = YES
-GROUP_GRAPHS           = YES
-UML_LOOK               = NO
-TEMPLATE_RELATIONS     = NO
-INCLUDE_GRAPH          = YES
-INCLUDED_BY_GRAPH      = YES
-CALL_GRAPH             = YES
-GRAPHICAL_HIERARCHY    = YES
-DIRECTORY_GRAPH        = NO
-DOT_IMAGE_FORMAT       = png
-DOT_PATH               = 
-DOTFILE_DIRS           = 
-MAX_DOT_GRAPH_DEPTH    = 1000
-DOT_TRANSPARENT        = NO
-DOT_MULTI_TARGETS      = NO
-GENERATE_LEGEND        = YES
-DOT_CLEANUP            = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
-#---------------------------------------------------------------------------
-SEARCHENGINE           = NO
diff --git a/contrib/wpa/hostapd/doc/doxygen.full b/contrib/wpa/hostapd/doc/doxygen.full
deleted file mode 100644
index f8c49bff7074..000000000000
--- a/contrib/wpa/hostapd/doc/doxygen.full
+++ /dev/null
@@ -1,238 +0,0 @@
-# Doxyfile 1.4.4
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-PROJECT_NAME           = hostapd
-PROJECT_NUMBER         = 0.6.x
-OUTPUT_DIRECTORY       = hostapd/doc
-CREATE_SUBDIRS         = NO
-OUTPUT_LANGUAGE        = English
-BRIEF_MEMBER_DESC      = YES
-REPEAT_BRIEF           = YES
-ABBREVIATE_BRIEF       = "The $name class" \
-                         "The $name widget" \
-                         "The $name file" \
-                         is \
-                         provides \
-                         specifies \
-                         contains \
-                         represents \
-                         a \
-                         an \
-                         the
-ALWAYS_DETAILED_SEC    = NO
-INLINE_INHERITED_MEMB  = NO
-FULL_PATH_NAMES        = YES
-STRIP_FROM_PATH        =
-STRIP_FROM_INC_PATH    = 
-SHORT_NAMES            = NO
-JAVADOC_AUTOBRIEF      = NO
-MULTILINE_CPP_IS_BRIEF = NO
-DETAILS_AT_TOP         = NO
-INHERIT_DOCS           = YES
-DISTRIBUTE_GROUP_DOC   = NO
-SEPARATE_MEMBER_PAGES  = NO
-TAB_SIZE               = 8
-ALIASES                = 
-OPTIMIZE_OUTPUT_FOR_C  = YES
-OPTIMIZE_OUTPUT_JAVA   = NO
-SUBGROUPING            = YES
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-EXTRACT_ALL            = NO
-EXTRACT_PRIVATE        = NO
-EXTRACT_STATIC         = NO
-EXTRACT_LOCAL_CLASSES  = YES
-EXTRACT_LOCAL_METHODS  = NO
-HIDE_UNDOC_MEMBERS     = NO
-HIDE_UNDOC_CLASSES     = NO
-HIDE_FRIEND_COMPOUNDS  = NO
-HIDE_IN_BODY_DOCS      = NO
-INTERNAL_DOCS          = NO
-CASE_SENSE_NAMES       = YES
-HIDE_SCOPE_NAMES       = NO
-SHOW_INCLUDE_FILES     = YES
-INLINE_INFO            = YES
-SORT_MEMBER_DOCS       = YES
-SORT_BRIEF_DOCS        = NO
-SORT_BY_SCOPE_NAME     = NO
-GENERATE_TODOLIST      = YES
-GENERATE_TESTLIST      = YES
-GENERATE_BUGLIST       = YES
-GENERATE_DEPRECATEDLIST= YES
-ENABLED_SECTIONS       = 
-MAX_INITIALIZER_LINES  = 30
-SHOW_USED_FILES        = YES
-SHOW_DIRECTORIES       = YES
-FILE_VERSION_FILTER    = 
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-QUIET                  = NO
-WARNINGS               = YES
-WARN_IF_UNDOCUMENTED   = NO
-WARN_IF_DOC_ERROR      = YES
-WARN_NO_PARAMDOC       = YES
-WARN_FORMAT            = "$file:$line: $text"
-WARN_LOGFILE           = 
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-INPUT                  = hostapd \
-	src/common \
-	src/crypto \
-	src/eap_common \
-	src/eap_server \
-	src/l2_packet \
-	src/radius \
-	src/rsn_supp \
-	src/tls \
-	src/utils \
-	src/wps
-FILE_PATTERNS          = *.c *.h *.doxygen
-RECURSIVE              = YES
-EXCLUDE                = 
-EXCLUDE_SYMLINKS       = NO
-EXCLUDE_PATTERNS       = 
-EXAMPLE_PATH           = 
-EXAMPLE_PATTERNS       = *
-EXAMPLE_RECURSIVE      = NO
-IMAGE_PATH             = hostapd/doc
-INPUT_FILTER           = kerneldoc2doxygen.pl
-FILTER_PATTERNS        = 
-FILTER_SOURCE_FILES    = YES
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-SOURCE_BROWSER         = YES
-INLINE_SOURCES         = NO
-STRIP_CODE_COMMENTS    = YES
-REFERENCED_BY_RELATION = NO
-REFERENCES_RELATION    = NO
-VERBATIM_HEADERS       = NO
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-ALPHABETICAL_INDEX     = YES
-COLS_IN_ALPHA_INDEX    = 3
-IGNORE_PREFIX          = 
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-GENERATE_HTML          = YES
-HTML_OUTPUT            = html
-HTML_FILE_EXTENSION    = .html
-HTML_HEADER            = 
-HTML_FOOTER            = 
-HTML_STYLESHEET        = 
-HTML_ALIGN_MEMBERS     = YES
-GENERATE_HTMLHELP      = NO
-CHM_FILE               = 
-HHC_LOCATION           = 
-GENERATE_CHI           = NO
-BINARY_TOC             = NO
-TOC_EXPAND             = NO
-DISABLE_INDEX          = NO
-ENUM_VALUES_PER_LINE   = 4
-GENERATE_TREEVIEW      = NO
-TREEVIEW_WIDTH         = 250
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-GENERATE_LATEX         = YES
-LATEX_OUTPUT           = latex
-LATEX_CMD_NAME         = latex
-MAKEINDEX_CMD_NAME     = makeindex
-COMPACT_LATEX          = NO
-PAPER_TYPE             = a4wide
-EXTRA_PACKAGES         = 
-LATEX_HEADER           = 
-PDF_HYPERLINKS         = YES
-USE_PDFLATEX           = YES
-LATEX_BATCHMODE        = NO
-LATEX_HIDE_INDICES     = NO
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-GENERATE_RTF           = NO
-RTF_OUTPUT             = rtf
-COMPACT_RTF            = NO
-RTF_HYPERLINKS         = NO
-RTF_STYLESHEET_FILE    = 
-RTF_EXTENSIONS_FILE    = 
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-GENERATE_MAN           = NO
-MAN_OUTPUT             = man
-MAN_EXTENSION          = .3
-MAN_LINKS              = NO
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-GENERATE_XML           = NO
-XML_OUTPUT             = xml
-XML_SCHEMA             = 
-XML_DTD                = 
-XML_PROGRAMLISTING     = YES
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-GENERATE_AUTOGEN_DEF   = NO
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-GENERATE_PERLMOD       = NO
-PERLMOD_LATEX          = NO
-PERLMOD_PRETTY         = YES
-PERLMOD_MAKEVAR_PREFIX = 
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
-#---------------------------------------------------------------------------
-ENABLE_PREPROCESSING   = YES
-MACRO_EXPANSION        = NO
-EXPAND_ONLY_PREDEF     = NO
-SEARCH_INCLUDES        = YES
-INCLUDE_PATH           = 
-INCLUDE_FILE_PATTERNS  = 
-PREDEFINED             = RADIUS_SERVER EAP_SERVER EAP_SIM
-EXPAND_AS_DEFINED      = 
-SKIP_FUNCTION_MACROS   = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references   
-#---------------------------------------------------------------------------
-TAGFILES               = 
-GENERATE_TAGFILE       = 
-ALLEXTERNALS           = NO
-EXTERNAL_GROUPS        = YES
-PERL_PATH              = /usr/bin/perl
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
-#---------------------------------------------------------------------------
-CLASS_DIAGRAMS         = NO
-HIDE_UNDOC_RELATIONS   = YES
-HAVE_DOT               = YES
-CLASS_GRAPH            = YES
-COLLABORATION_GRAPH    = YES
-GROUP_GRAPHS           = YES
-UML_LOOK               = NO
-TEMPLATE_RELATIONS     = NO
-INCLUDE_GRAPH          = YES
-INCLUDED_BY_GRAPH      = YES
-CALL_GRAPH             = YES
-GRAPHICAL_HIERARCHY    = YES
-DIRECTORY_GRAPH        = NO
-DOT_IMAGE_FORMAT       = png
-DOT_PATH               = 
-DOTFILE_DIRS           = 
-MAX_DOT_GRAPH_DEPTH    = 1000
-DOT_TRANSPARENT        = NO
-DOT_MULTI_TARGETS      = NO
-GENERATE_LEGEND        = YES
-DOT_CLEANUP            = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
-#---------------------------------------------------------------------------
-SEARCHENGINE           = YES
diff --git a/contrib/wpa/hostapd/doc/driver_wrapper.doxygen b/contrib/wpa/hostapd/doc/driver_wrapper.doxygen
deleted file mode 100644
index 0ad196f2d6b6..000000000000
--- a/contrib/wpa/hostapd/doc/driver_wrapper.doxygen
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
-\page driver_wrapper Driver wrapper implementation (driver.h, drivers.c)
-
-All hardware and driver dependent functionality is in separate C files
-that implement defined wrapper functions. Other parts
-of the hostapd are designed to be hardware, driver, and operating
-system independent.
-
-Driver wrappers need to implement whatever calls are used in the
-target operating system/driver for controlling wireless LAN
-devices. As an example, in case of Linux, these are mostly some glue
-code and ioctl() calls and netlink message parsing for Linux Wireless
-Extensions (WE). Since features required for WPA were added only recently to
-Linux Wireless Extensions (in version 18), some driver specific code is used
-in number of driver interface implementations. These driver dependent parts
-can be replaced with generic code in driver_wext.c once the target driver
-includes full support for WE-18. After that, all Linux drivers, at
-least in theory, could use the same driver wrapper code.
-
-*/
diff --git a/contrib/wpa/hostapd/doc/eap.doxygen b/contrib/wpa/hostapd/doc/eap.doxygen
deleted file mode 100644
index f0f135aa9598..000000000000
--- a/contrib/wpa/hostapd/doc/eap.doxygen
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
-\page eap_module EAP server implementation
-
-Extensible Authentication Protocol (EAP) is an authentication framework
-defined in RFC 3748. hostapd uses a separate code module for EAP server
-implementation. This module was designed to use only a minimal set of
-direct function calls (mainly, to debug/event functions) in order for
-it to be usable in other programs. The design of the EAP
-implementation is based loosely on RFC 4137. The state machine is
-defined in this RFC and so is the interface between the server state
-machine and methods. As such, this RFC provides useful information for
-understanding the EAP server implementation in hostapd.
-
-Some of the terminology used in EAP state machine is referring to
-EAPOL (IEEE 802.1X), but there is no strict requirement on the lower
-layer being IEEE 802.1X if EAP module is built for other programs than
-%wpa_supplicant. These terms should be understood to refer to the
-lower layer as defined in RFC 4137.
-
-
-\section adding_eap_methods Adding EAP methods
-
-Each EAP method is implemented as a separate module, usually as one C
-file named eap_.c, e.g., eap_md5.c. All EAP
-methods use the same interface between the server state machine and
-method specific functions. This allows new EAP methods to be added
-without modifying the core EAP state machine implementation.
-
-New EAP methods need to be registered by adding them into the build
-(Makefile) and the EAP method registration list in the
-eap_server_register_methods() function of eap_methods.c. Each EAP
-method should use a build-time configuration option, e.g., EAP_TLS, in
-order to make it possible to select which of the methods are included
-in the build.
-
-EAP methods must implement the interface defined in eap_i.h. struct
-eap_method defines the needed function pointers that each EAP method
-must provide. In addition, the EAP type and name are registered using
-this structure. This interface is based on section 4.4 of RFC 4137.
-
-It is recommended that the EAP methods would use generic helper
-functions, eap_msg_alloc() and eap_hdr_validate() when processing
-messages. This allows code sharing and can avoid missing some of the
-needed validation steps for received packets. In addition, these
-functions make it easier to change between expanded and legacy EAP
-header, if needed.
-
-When adding an EAP method that uses a vendor specific EAP type
-(Expanded Type as defined in RFC 3748, Chapter 5.7), the new method
-must be registered by passing vendor id instead of EAP_VENDOR_IETF to
-eap_server_method_alloc(). These methods must not try to emulate
-expanded types by registering a legacy EAP method for type 254. See
-eap_vendor_test.c for an example of an EAP method implementation that
-is implemented as an expanded type.
-
-*/
diff --git a/contrib/wpa/hostapd/doc/hostapd.fig b/contrib/wpa/hostapd/doc/hostapd.fig
deleted file mode 100644
index af3f0be19a9b..000000000000
--- a/contrib/wpa/hostapd/doc/hostapd.fig
+++ /dev/null
@@ -1,264 +0,0 @@
-#FIG 3.2
-Landscape
-Center
-Inches
-Letter  
-100.00
-Single
--2
-1200 2
-6 1875 4050 2925 4350
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 1875 4050 2925 4050 2925 4350 1875 4350 1875 4050
-4 0 0 50 -1 0 12 0.0000 4 180 735 2025 4275 l2_packet\001
--6
-6 4725 1200 5925 1500
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 4725 1200 5925 1200 5925 1500 4725 1500 4725 1200
-4 0 0 50 -1 0 12 0.0000 4 135 1005 4800 1425 GUI frontend\001
--6
-6 6000 2700 7200 3225
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 6000 2700 7200 2700 7200 3225 6000 3225 6000 2700
-4 0 0 50 -1 0 12 0.0000 4 135 975 6075 2925 WPA/WPA2\001
-4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 3150 state machine\001
--6
-6 6000 4950 7200 5475
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 6000 4950 7200 4950 7200 5475 6000 5475 6000 4950
-4 0 0 50 -1 0 12 0.0000 4 135 360 6075 5175 EAP\001
-4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 5400 state machine\001
--6
-6 4350 3900 5025 4425
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 4350 3900 5025 3900 5025 4425 4350 4425 4350 3900
-4 0 0 50 -1 0 12 0.0000 4 105 420 4500 4125 event\001
-4 0 0 50 -1 0 12 0.0000 4 180 315 4500 4350 loop\001
--6
-6 4275 2550 5100 2850
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 4275 2550 5100 2550 5100 2850 4275 2850 4275 2550
-4 0 0 50 -1 0 12 0.0000 4 135 450 4425 2775 ctrl i/f\001
--6
-6 6000 3900 7200 4425
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 6000 3900 7200 3900 7200 4425 6000 4425 6000 3900
-4 0 0 50 -1 0 12 0.0000 4 135 600 6075 4125 EAPOL\001
-4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 4350 state machine\001
--6
-6 2775 3150 4050 3450
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 2775 3150 4050 3150 4050 3450 2775 3450 2775 3150
-4 0 0 50 -1 0 12 0.0000 4 180 990 2925 3375 configuration\001
--6
-6 3450 1200 4575 1500
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 3450 1200 4575 1200 4575 1500 3450 1500 3450 1200
-4 0 0 50 -1 0 12 0.0000 4 180 870 3600 1425 hostapd_cli\001
--6
-6 3525 7800 5775 8100
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 3525 7800 5775 7800 5775 8100 3525 8100 3525 7800
-4 0 0 50 -1 0 12 0.0000 4 135 2145 3600 8025 kernel network device driver\001
--6
-6 4275 6000 5100 6300
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 4275 6000 5100 6000 5100 6300 4275 6300 4275 6000
-4 0 0 50 -1 0 12 0.0000 4 135 630 4350 6225 driver i/f\001
--6
-6 8175 4725 9225 5025
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 8175 4725 9225 4725 9225 5025 8175 5025 8175 4725
-4 0 0 50 -1 0 12 0.0000 4 135 735 8250 4950 EAP-TLS\001
--6
-6 9300 4725 10350 5025
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 9300 4725 10350 4725 10350 5025 9300 5025 9300 4725
-4 0 0 50 -1 0 12 0.0000 4 135 810 9375 4950 EAP-MD5\001
--6
-6 8175 5100 9225 5400
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 8175 5100 9225 5100 9225 5400 8175 5400 8175 5100
-4 0 0 50 -1 0 12 0.0000 4 135 885 8250 5325 EAP-PEAP\001
--6
-6 9300 5100 10350 5400
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 9300 5100 10350 5100 10350 5400 9300 5400 9300 5100
-4 0 0 50 -1 0 12 0.0000 4 135 840 9375 5325 EAP-TTLS\001
--6
-6 8175 5475 9225 5775
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 8175 5475 9225 5475 9225 5775 8175 5775 8175 5475
-4 0 0 50 -1 0 12 0.0000 4 135 780 8250 5700 EAP-GTC\001
--6
-6 8175 5850 9225 6150
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 8175 5850 9225 5850 9225 6150 8175 6150 8175 5850
-4 0 0 50 -1 0 12 0.0000 4 135 750 8250 6075 EAP-SIM\001
--6
-6 8175 6225 9225 6525
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 8175 6225 9225 6225 9225 6525 8175 6525 8175 6225
-4 0 0 50 -1 0 12 0.0000 4 135 765 8250 6450 EAP-PSK\001
--6
-6 9300 5850 10350 6150
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 9300 5850 10350 5850 10350 6150 9300 6150 9300 5850
-4 0 0 50 -1 0 12 0.0000 4 135 825 9375 6075 EAP-AKA\001
--6
-6 9300 5475 10350 5775
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 9300 5475 10350 5475 10350 5775 9300 5775 9300 5475
-4 0 0 50 -1 0 12 0.0000 4 135 795 9375 5700 EAP-PAX\001
--6
-6 8175 6600 9675 6900
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 8175 6600 9675 6600 9675 6900 8175 6900 8175 6600
-4 0 0 50 -1 0 12 0.0000 4 135 1365 8250 6825 EAP-MSCHAPv2\001
--6
-6 8700 3450 9375 3750
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 8700 3450 9375 3450 9375 3750 8700 3750 8700 3450
-4 0 0 50 -1 0 12 0.0000 4 150 480 8775 3675 crypto\001
--6
-6 9600 3450 10275 3750
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 9600 3450 10275 3450 10275 3750 9600 3750 9600 3450
-4 0 0 50 -1 0 12 0.0000 4 135 315 9750 3675 TLS\001
--6
-6 6000 5775 7200 6300
-6 6000 5775 7200 6300
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 6000 5775 7200 5775 7200 6300 6000 6300 6000 5775
-4 0 0 50 -1 0 12 0.0000 4 135 690 6075 6000 RADIUS\001
--6
-4 0 0 50 -1 0 12 0.0000 4 90 480 6075 6225 server\001
--6
-6 8100 2250 8925 2775
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 8100 2250 8925 2250 8925 2775 8100 2775 8100 2250
-4 0 0 50 -1 0 12 0.0000 4 135 690 8175 2475 RADIUS\001
-4 0 0 50 -1 0 12 0.0000 4 135 420 8175 2700 client\001
--6
-6 3150 5475 4425 5775
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 3150 5475 4425 5475 4425 5775 3150 5775 3150 5475
-4 0 0 50 -1 0 12 0.0000 4 135 990 3300 5700 driver events\001
--6
-6 1950 5550 2625 6075
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 1950 5550 2625 5550 2625 6075 1950 6075 1950 5550
-4 0 0 50 -1 0 12 0.0000 4 135 540 2025 5775 Station\001
-4 0 0 50 -1 0 12 0.0000 4 135 375 2025 6000 table\001
--6
-6 1875 4725 2925 5250
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 1875 4725 2925 4725 2925 5250 1875 5250 1875 4725
-4 0 0 50 -1 0 12 0.0000 4 135 960 1950 4950 IEEE 802.11\001
-4 0 0 50 -1 0 12 0.0000 4 135 555 1950 5175 MLME\001
--6
-2 1 1 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2
-	 1275 4200 1875 4200
-2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
-	 4500 2550 3900 1500
-2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
-	 4800 2550 5400 1500
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 2925 4200 4350 4200
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 5025 3900 6000 3000
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 5025 4200 6000 4200
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 4650 6000 4650 4425
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 6600 4425 6600 4950
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 6600 3225 6600 3900
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 7200 5250 8100 5250
-2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 9075 4425 9075 3750
-2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 7200 3000 8700 3525
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 4650 3900 4650 2850
-2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 7200 4125 8700 3675
-2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 6000 4350 5025 6000
-2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 6000 3150 4875 6000
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 1500 2100 10800 2100 10800 7500 1500 7500 1500 2100
-2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 9900 4425 9900 3750
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 1
-	 4350 3900
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 4350 3900 4050 3450
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 4350 4425 4050 5475
-2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
-	 2250 7200 4200 7800
-2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
-	 7200 7200 5100 7800
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 2775 6900 3675 6900 3675 7200 2775 7200 2775 6900
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 3750 6900 4650 6900 4650 7200 3750 7200 3750 6900
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4
-	 2250 6900 2250 6600 7200 6600 7200 6900
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 3225 6900 3225 6600
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 4200 6900 4200 6600
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 5175 6900 5175 6600
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 6150 6900 6150 6600
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 4650 6600 4650 6300
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 1800 6900 2700 6900 2700 7200 1800 7200 1800 6900
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 4725 6900 5625 6900 5625 7200 4725 7200 4725 6900
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 5700 6900 6600 6900 6600 7200 5700 7200 5700 6900
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 6675 6900 7800 6900 7800 7200 6675 7200 6675 6900
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 8100 6975 10425 6975 10425 4425 8100 4425 8100 6975
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 6600 5475 6600 5775
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 5025 4425 6000 5775
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
-	 4800 3900 5925 2550 8100 2550
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 7200 3900 8475 2775
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-	 9450 2250 10425 2250 10425 2775 9450 2775 9450 2250
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 8925 2475 9450 2475
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 2325 5550 2325 5250
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-	 2925 4950 4350 4275
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
-	 2850 4725 5775 2400 8100 2400
-4 0 0 50 -1 0 12 0.0000 4 135 915 375 3975 EAPOL and\001
-4 0 0 50 -1 0 12 0.0000 4 180 630 375 4200 pre-auth\001
-4 0 0 50 -1 0 12 0.0000 4 180 810 375 4425 ethertypes\001
-4 0 0 50 -1 0 12 0.0000 4 135 1050 375 4650 from/to kernel\001
-4 0 0 50 -1 0 12 0.0000 4 135 1920 3675 1875 frontend control interface\001
-4 0 0 50 -1 2 14 0.0000 4 195 720 1637 2371 hostapd\001
-4 0 0 50 -1 0 12 0.0000 4 180 600 3825 7125 prism54\001
-4 0 0 50 -1 0 12 0.0000 4 180 510 1875 7125 hostap\001
-4 0 0 50 -1 0 12 0.0000 4 135 600 2850 7125 madwifi\001
-4 0 0 50 -1 0 12 0.0000 4 135 270 4800 7125 bsd\001
-4 0 0 50 -1 0 12 0.0000 4 105 300 6750 7125 test\001
-4 0 0 50 -1 0 12 0.0000 4 135 420 5775 7125 wired\001
-4 0 0 50 -1 0 12 0.0000 4 135 1050 8700 4650 EAP methods\001
-4 0 0 50 -1 0 12 0.0000 4 135 690 9525 2475 RADIUS\001
-4 0 0 50 -1 0 12 0.0000 4 180 825 9525 2700 accounting\001
diff --git a/contrib/wpa/hostapd/doc/kerneldoc2doxygen.pl b/contrib/wpa/hostapd/doc/kerneldoc2doxygen.pl
deleted file mode 100755
index 68835a1ddd31..000000000000
--- a/contrib/wpa/hostapd/doc/kerneldoc2doxygen.pl
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/usr/bin/perl -w
-#
-##########################################################################
-# Convert kernel-doc style comments to Doxygen comments.
-##########################################################################
-#
-# This script reads a C source file from stdin, and writes
-# to stdout.  Normal usage:
-#
-# $ mv file.c file.c.gtkdoc
-# $ kerneldoc2doxygen.pl file.c
-#
-# Or to do the same thing with multiple files:
-# $ perl -i.gtkdoc kerneldoc2doxygen.pl *.c *.h
-#
-# This script may also be suitable for use as a Doxygen input filter,
-# but that has not been tested.
-#
-# Back up your source files before using this script!!
-#
-##########################################################################
-# Copyright (C) 2003 Jonathan Foster 
-# Copyright (C) 2005 Jouni Malinen 
-# (modified for kerneldoc format used in wpa_supplicant)
-#
-# 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
-# or look at http://www.gnu.org/licenses/gpl.html
-##########################################################################
-
-
-##########################################################################
-#
-# This function converts a single comment from gtk-doc to Doxygen format.
-# The parameter does not include the opening or closing lines
-# (i.e. given a comment like this:
-#    "/**\n"
-#    " * FunctionName:\n"
-#    " * @foo: This describes the foo parameter\n"
-#    " * @bar: This describes the bar parameter\n"
-#    " * @Returns: This describes the return value\n"
-#    " *\n"
-#    " * This describes the function.\n"
-#    " */\n"
-# This function gets:
-#    " * FunctionName:\n"
-#    " * @foo: This describes the foo parameter\n"
-#    " * @bar: This describes the bar parameter\n"
-#    " * @Returns: This describes the return value\n"
-#    " *\n"
-#    " * This describes the function.\n"
-# And it returns:
-#    " * This describes the function.\n"
-#    " *\n"
-#    " * @param foo This describes the foo parameter\n"
-#    " * @param bar This describes the bar parameter\n"
-#    " * @return This describes the return value\n"
-# )
-#
-sub fixcomment {
-    $t = $_[0];
-
-    # " * func: foo" --> "\brief foo\n"
-    # " * struct bar: foo" --> "\brief foo\n"
-    # If this fails, not a kernel-doc comment ==> return unmodified.
-    ($t =~ s/^[\t ]*\*[\t ]*(struct )?([^ \t\n]*) - ([^\n]*)/\\brief $3\n/s)
-      or return $t;
-
-    # " * Returns: foo" --> "\return foo"
-    $t =~ s/\n[\t ]*\*[\t ]*Returns:/\n\\return/sig;
-
-    # " * @foo: bar" --> "\param foo bar"
-    # Handle two common typos: No ":", or "," instead of ":".
-    $t =~ s/\n[\t ]*\*[\t ]*\@([^ :,]*)[:,]?[\t ]*/\n\\param $1 /sg;
-
-    return $t;
-}
-
-##########################################################################
-# Start of main code
-
-# Read entire stdin into memory - one multi-line string.
-$_ = do { local $/; <> };
-
-s{^/\*\n \*}{/\*\* \\file\n\\brief};
-s{ \* Copyright}{\\par Copyright\nCopyright};
-
-# Fix any comments like "/*************" so they don't match.
-# "/***" ===> "/* *"
-s{/\*\*\*}{/\* \*}gs;
-
-# The main comment-detection code.
-s{
-    (               # $1 = Open comment
-        /\*\*       # Open comment
-        (?!\*)      # Do not match /*** (redundant due to fixup above).
-        [\t ]*\n?   # If 1st line is whitespace, match the lot (including the newline).
-    )
-    (.*?)           # $2 = Body of comment (multi-line)
-    (               # $3 = Close comment
-        (           # If possible, match the whitespace before the close-comment
-            (?<=\n) # This part only matches after a newline
-            [\t ]*  # Eat whitespace
-        )?
-        \*/         # Close comment
-    )
- }
- {
-    $1 . fixcomment($2) . $3
- }gesx;
-# ^^^^ Modes: g - Global, match all occurances.
-#             e - Evaluate the replacement as an expression.
-#             s - Single-line - allows the pattern to match across newlines.
-#             x - eXtended pattern, ignore embedded whitespace
-#                 and allow comments.
-
-# Write results to stdout
-print $_;
-
diff --git a/contrib/wpa/hostapd/doc/mainpage.doxygen b/contrib/wpa/hostapd/doc/mainpage.doxygen
deleted file mode 100644
index 7cf95de584af..000000000000
--- a/contrib/wpa/hostapd/doc/mainpage.doxygen
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
-\mainpage Developers' documentation for hostapd
-
-hostapd includes IEEE 802.11 access point management (authentication /
-association), IEEE 802.1X/WPA/WPA2 Authenticator, EAP server, and
-RADIUS authentication server functionality. It can be build with
-various configuration option, e.g., a standalone AP management
-solution or a RADIUS authentication server with support for number of
-EAP methods.
-
-The goal of this documentation and comments in the source code is to
-give enough information for other developers to understand how hostapd
-has been implemented, how it can be modified, how new drivers can be
-supported, and how hostapd can be ported to other operating
-systems. If any information is missing, feel free to contact Jouni
-Malinen  for more information. Contributions as
-patch files are also very welcome at the same address. Please note
-that hostapd is licensed under dual license, GPLv2 or BSD at user's
-choice. All contributions to hostapd are expected to use compatible
-licensing terms.
-
-The source code and read-only access to hostapd CVS repository
-is available from the project home page at
-http://hostap.epitest.fi/hostapd/. This developers' documentation
-is also available as a PDF file from
-http://hostap.epitest.fi/hostapd/hostapd-devel.pdf .
-
-The design goal for hostapd was to use hardware, driver, and
-OS independent, portable C code for all WPA functionality. The source
-code is divided into separate C files as shown on the \ref
-code_structure "code structure page". All hardware/driver specific
-functionality is in separate files that implement a \ref
-driver_wrapper "well-defined driver API". Information about porting
-to different target boards and operating systems is available on
-the \ref porting "porting page".
-
-EAPOL (IEEE 802.1X) state machines are implemented as a separate
-module that interacts with \ref eap_module "EAP server implementation".
-Similarly, RADIUS authentication server is in its own separate module.
-Both IEEE 802.1X and RADIUS authentication server can use EAP server
-functionality.
-
-hostapd implements a \ref ctrl_iface_page "control interface" that can
-be used by external programs to control the operations of the hostapdt
-daemon and to get status information and event notifications. There is
-a small C library that provides helper functions to facilitate the use
-of the control interface. This library can also be used with C++.
-
-\image html hostapd.png "hostapd modules"
-\image latex hostapd.eps "hostapd modules" width=15cm
-
-*/
diff --git a/contrib/wpa/hostapd/doc/porting.doxygen b/contrib/wpa/hostapd/doc/porting.doxygen
deleted file mode 100644
index 0621791c0be0..000000000000
--- a/contrib/wpa/hostapd/doc/porting.doxygen
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
-\page porting Porting to different target boards and operating systems
-
-
-*/
diff --git a/contrib/wpa/hostapd/driver.h b/contrib/wpa/hostapd/driver.h
deleted file mode 100644
index 45f546087302..000000000000
--- a/contrib/wpa/hostapd/driver.h
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * hostapd - driver interface definition
- * Copyright (c) 2002-2007, Jouni Malinen 
- * Copyright (c) 2007-2008, Intel Corporation
- *
- * 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 DRIVER_H
-#define DRIVER_H
-
-struct hostapd_sta_add_params {
-	const u8 *addr;
-	u16 aid;
-	u16 capability;
-	const u8 *supp_rates;
-	size_t supp_rates_len;
-	int flags;
-	u16 listen_interval;
-	const struct ht_cap_ie *ht_capabilities;
-};
-
-struct hostapd_freq_params {
-	int mode;
-	int freq;
-	int ht_enabled;
-	int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled,
-				 * secondary channel below primary, 1 = HT40
-				 * enabled, secondary channel above primary */
-};
-
-enum hostapd_driver_if_type {
-	HOSTAPD_IF_VLAN, HOSTAPD_IF_WDS
-};
-
-struct wpa_driver_ops {
-	const char *name;		/* as appears in the config file */
-
-	void * (*init)(struct hostapd_data *hapd);
-	void * (*init_bssid)(struct hostapd_data *hapd, const u8 *bssid);
-	void (*deinit)(void *priv);
-
-	int (*wireless_event_init)(void *priv);
-	void (*wireless_event_deinit)(void *priv);
-
-	/**
-	 * set_8021x - enable/disable IEEE 802.1X support
-	 * @ifname: Interface name (for multi-SSID/VLAN support)
-	 * @priv: driver private data
-	 * @enabled: 1 = enable, 0 = disable
-	 *
-	 * Returns: 0 on success, -1 on failure
-	 *
-	 * Configure the kernel driver to enable/disable 802.1X support.
-	 * This may be an empty function if 802.1X support is always enabled.
-	 */
-	int (*set_ieee8021x)(const char *ifname, void *priv, int enabled);
-
-	/**
-	 * set_privacy - enable/disable privacy
-	 * @priv: driver private data
-	 * @enabled: 1 = privacy enabled, 0 = disabled
-	 *
-	 * Return: 0 on success, -1 on failure
-	 *
-	 * Configure privacy.
-	 */
-	int (*set_privacy)(const char *ifname, void *priv, int enabled);
-
-	int (*set_encryption)(const char *ifname, void *priv, const char *alg,
-			      const u8 *addr, int idx,
-			      const u8 *key, size_t key_len, int txkey);
-	int (*get_seqnum)(const char *ifname, void *priv, const u8 *addr,
-			  int idx, u8 *seq);
-	int (*get_seqnum_igtk)(const char *ifname, void *priv, const u8 *addr,
-			       int idx, u8 *seq);
-	int (*flush)(void *priv);
-	int (*set_generic_elem)(const char *ifname, void *priv, const u8 *elem,
-				size_t elem_len);
-
-	int (*read_sta_data)(void *priv, struct hostap_sta_driver_data *data,
-			     const u8 *addr);
-	int (*send_eapol)(void *priv, const u8 *addr, const u8 *data,
-			  size_t data_len, int encrypt, const u8 *own_addr);
-	int (*sta_deauth)(void *priv, const u8 *addr, int reason);
-	int (*sta_disassoc)(void *priv, const u8 *addr, int reason);
-	int (*sta_remove)(void *priv, const u8 *addr);
-	int (*get_ssid)(const char *ifname, void *priv, u8 *buf, int len);
-	int (*set_ssid)(const char *ifname, void *priv, const u8 *buf,
-			int len);
-	int (*set_countermeasures)(void *priv, int enabled);
-	int (*send_mgmt_frame)(void *priv, const void *msg, size_t len,
-			       int flags);
-	int (*set_assoc_ap)(void *priv, const u8 *addr);
-	/* note: sta_add() is deprecated; use sta_add2() instead */
-	int (*sta_add)(const char *ifname, void *priv, const u8 *addr, u16 aid,
-		       u16 capability, u8 *supp_rates, size_t supp_rates_len,
-		       int flags, u16 listen_interval);
-	int (*sta_add2)(const char *ifname, void *priv,
-			struct hostapd_sta_add_params *params);
-	int (*get_inact_sec)(void *priv, const u8 *addr);
-	int (*sta_clear_stats)(void *priv, const u8 *addr);
-
-	/* note: set_freq() is deprecated; use set_freq2() instead */
-	int (*set_freq)(void *priv, int mode, int freq);
-	int (*set_freq2)(void *priv, struct hostapd_freq_params *freq);
-	int (*set_rts)(void *priv, int rts);
-	int (*get_rts)(void *priv, int *rts);
-	int (*set_frag)(void *priv, int frag);
-	int (*get_frag)(void *priv, int *frag);
-	int (*set_retry)(void *priv, int short_retry, int long_retry);
-	int (*get_retry)(void *priv, int *short_retry, int *long_retry);
-
-	int (*sta_set_flags)(void *priv, const u8 *addr,
-			     int total_flags, int flags_or, int flags_and);
-	int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates,
-			     int mode);
-	int (*set_regulatory_domain)(void *priv, unsigned int rd);
-	int (*set_country)(void *priv, const char *country);
-	int (*set_ieee80211d)(void *priv, int enabled);
-	int (*set_beacon)(const char *ifname, void *priv,
-			  u8 *head, size_t head_len,
-			  u8 *tail, size_t tail_len);
-
-	/* Configure internal bridge:
-	 * 0 = disabled, i.e., client separation is enabled (no bridging of
-	 *     packets between associated STAs
-	 * 1 = enabled, i.e., bridge packets between associated STAs (default)
-	 */
-	int (*set_internal_bridge)(void *priv, int value);
-	int (*set_beacon_int)(void *priv, int value);
-	int (*set_dtim_period)(const char *ifname, void *priv, int value);
-	/* Configure broadcast SSID mode:
-	 * 0 = include SSID in Beacon frames and reply to Probe Request frames
-	 *     that use broadcast SSID
-	 * 1 = hide SSID from Beacon frames and ignore Probe Request frames for
-	 *     broadcast SSID
-	 */
-	int (*set_broadcast_ssid)(void *priv, int value);
-	int (*set_cts_protect)(void *priv, int value);
-	int (*set_key_tx_rx_threshold)(void *priv, int value);
-	int (*set_preamble)(void *priv, int value);
-	int (*set_short_slot_time)(void *priv, int value);
-	int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min,
-				   int cw_max, int burst_time);
-	int (*bss_add)(void *priv, const char *ifname, const u8 *bssid);
-	int (*bss_remove)(void *priv, const char *ifname);
-	int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask);
-	int (*passive_scan)(void *priv, int now, int our_mode_only,
-			    int interval, int _listen, int *channel,
-			    int *last_rx);
-	struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv,
-							 u16 *num_modes,
-							 u16 *flags);
-	int (*if_add)(const char *iface, void *priv,
-		      enum hostapd_driver_if_type type, char *ifname,
-		      const u8 *addr);
-	int (*if_update)(void *priv, enum hostapd_driver_if_type type,
-			 char *ifname, const u8 *addr);
-	int (*if_remove)(void *priv, enum hostapd_driver_if_type type,
-			 const char *ifname, const u8 *addr);
-	int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname,
-			    int vlan_id);
-	/**
-	 * commit - Optional commit changes handler
-	 * @priv: driver private data
-	 * Returns: 0 on success, -1 on failure
-	 *
-	 * This optional handler function can be registered if the driver
-	 * interface implementation needs to commit changes (e.g., by setting
-	 * network interface up) at the end of initial configuration. If set,
-	 * this handler will be called after initial setup has been completed.
-	 */
-	int (*commit)(void *priv);
-
-	int (*send_ether)(void *priv, const u8 *dst, const u8 *src, u16 proto,
-			  const u8 *data, size_t data_len);
-
-	int (*set_radius_acl_auth)(void *priv, const u8 *mac, int accepted, 
-				   u32 session_timeout);
-	int (*set_radius_acl_expire)(void *priv, const u8 *mac);
-
-	int (*set_ht_params)(const char *ifname, void *priv,
-			     const u8 *ht_capab, size_t ht_capab_len,
-			     const u8 *ht_oper, size_t ht_oper_len);
-
-	int (*set_wps_beacon_ie)(const char *ifname, void *priv,
-				 const u8 *ie, size_t len);
-	int (*set_wps_probe_resp_ie)(const char *ifname, void *priv,
-				     const u8 *ie, size_t len);
-};
-
-static inline void *
-hostapd_driver_init(struct hostapd_data *hapd)
-{
-	if (hapd->driver == NULL || hapd->driver->init == NULL)
-		return NULL;
-	return hapd->driver->init(hapd);
-}
-
-static inline void *
-hostapd_driver_init_bssid(struct hostapd_data *hapd, const u8 *bssid)
-{
-	if (hapd->driver == NULL || hapd->driver->init_bssid == NULL)
-		return NULL;
-	return hapd->driver->init_bssid(hapd, bssid);
-}
-
-static inline void
-hostapd_driver_deinit(struct hostapd_data *hapd)
-{
-	if (hapd->driver == NULL || hapd->driver->deinit == NULL)
-		return;
-	hapd->driver->deinit(hapd->drv_priv);
-}
-
-static inline int
-hostapd_wireless_event_init(struct hostapd_data *hapd)
-{
-	if (hapd->driver == NULL ||
-	    hapd->driver->wireless_event_init == NULL)
-		return 0;
-	return hapd->driver->wireless_event_init(hapd->drv_priv);
-}
-
-static inline void
-hostapd_wireless_event_deinit(struct hostapd_data *hapd)
-{
-	if (hapd->driver == NULL ||
-	    hapd->driver->wireless_event_deinit == NULL)
-		return;
-	hapd->driver->wireless_event_deinit(hapd->drv_priv);
-}
-
-static inline int
-hostapd_set_ieee8021x(const char *ifname, struct hostapd_data *hapd,
-		      int enabled)
-{
-	if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL)
-		return 0;
-	return hapd->driver->set_ieee8021x(ifname, hapd->drv_priv, enabled);
-}
-
-static inline int
-hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
-{
-	if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
-		return 0;
-	return hapd->driver->set_privacy(hapd->conf->iface, hapd->drv_priv,
-					 enabled);
-}
-
-static inline int
-hostapd_set_encryption(const char *ifname, struct hostapd_data *hapd,
-		       const char *alg, const u8 *addr, int idx,
-		       u8 *key, size_t key_len, int txkey)
-{
-	if (hapd->driver == NULL || hapd->driver->set_encryption == NULL)
-		return 0;
-	return hapd->driver->set_encryption(ifname, hapd->drv_priv, alg, addr,
-					    idx, key, key_len, txkey);
-}
-
-static inline int
-hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
-		   const u8 *addr, int idx, u8 *seq)
-{
-	if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL)
-		return 0;
-	return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx,
-					seq);
-}
-
-static inline int
-hostapd_get_seqnum_igtk(const char *ifname, struct hostapd_data *hapd,
-			const u8 *addr, int idx, u8 *seq)
-{
-	if (hapd->driver == NULL || hapd->driver->get_seqnum_igtk == NULL)
-		return -1;
-	return hapd->driver->get_seqnum_igtk(ifname, hapd->drv_priv, addr, idx,
-					     seq);
-}
-
-static inline int
-hostapd_flush(struct hostapd_data *hapd)
-{
-	if (hapd->driver == NULL || hapd->driver->flush == NULL)
-		return 0;
-	return hapd->driver->flush(hapd->drv_priv);
-}
-
-static inline int
-hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
-			 size_t elem_len)
-{
-	if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
-		return 0;
-	return hapd->driver->set_generic_elem(hapd->conf->iface,
-					      hapd->drv_priv, elem, elem_len);
-}
-
-static inline int
-hostapd_read_sta_data(struct hostapd_data *hapd,
-		      struct hostap_sta_driver_data *data, const u8 *addr)
-{
-	if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
-		return -1;
-	return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
-}
-
-static inline int
-hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr, const u8 *data,
-		   size_t data_len, int encrypt)
-{
-	if (hapd->driver == NULL || hapd->driver->send_eapol == NULL)
-		return 0;
-	return hapd->driver->send_eapol(hapd->drv_priv, addr, data, data_len,
-					encrypt, hapd->own_addr);
-}
-
-static inline int
-hostapd_sta_deauth(struct hostapd_data *hapd, const u8 *addr, int reason)
-{
-	if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
-		return 0;
-	return hapd->driver->sta_deauth(hapd->drv_priv, addr, reason);
-}
-
-static inline int
-hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr, int reason)
-{
-	if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
-		return 0;
-	return hapd->driver->sta_disassoc(hapd->drv_priv, addr, reason);
-}
-
-static inline int
-hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr)
-{
-	if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
-		return 0;
-	return hapd->driver->sta_remove(hapd->drv_priv, addr);
-}
-
-static inline int
-hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
-{
-	if (hapd->driver == NULL || hapd->driver->get_ssid == NULL)
-		return 0;
-	return hapd->driver->get_ssid(hapd->conf->iface, hapd->drv_priv, buf,
-				      len);
-}
-
-static inline int
-hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
-{
-	if (hapd->driver == NULL || hapd->driver->set_ssid == NULL)
-		return 0;
-	return hapd->driver->set_ssid(hapd->conf->iface, hapd->drv_priv, buf,
-				      len);
-}
-
-static inline int
-hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg, size_t len,
-			int flags)
-{
-	if (hapd->driver == NULL || hapd->driver->send_mgmt_frame == NULL)
-		return 0;
-	return hapd->driver->send_mgmt_frame(hapd->drv_priv, msg, len, flags);
-}
-
-static inline int
-hostapd_set_assoc_ap(struct hostapd_data *hapd, const u8 *addr)
-{
-	if (hapd->driver == NULL || hapd->driver->set_assoc_ap == NULL)
-		return 0;
-	return hapd->driver->set_assoc_ap(hapd->drv_priv, addr);
-}
-
-static inline int
-hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled)
-{
-	if (hapd->driver == NULL || hapd->driver->set_countermeasures == NULL)
-		return 0;
-	return hapd->driver->set_countermeasures(hapd->drv_priv, enabled);
-}
-
-static inline int
-hostapd_sta_add(const char *ifname, struct hostapd_data *hapd, const u8 *addr,
-		u16 aid, u16 capability, const u8 *supp_rates,
-		size_t supp_rates_len, int flags, u16 listen_interval,
-		const struct ht_cap_ie *ht_capabilities)
-{
-	if (hapd->driver == NULL)
-		return 0;
-
-	if (hapd->driver->sta_add2) {
-		struct hostapd_sta_add_params params;
-		os_memset(¶ms, 0, sizeof(params));
-		params.addr = addr;
-		params.aid = aid;
-		params.capability = capability;
-		params.supp_rates = supp_rates;
-		params.supp_rates_len = supp_rates_len;
-		params.flags = flags;
-		params.listen_interval = listen_interval;
-		params.ht_capabilities = ht_capabilities;
-		return hapd->driver->sta_add2(ifname, hapd->drv_priv, ¶ms);
-	}
-
-	if (hapd->driver->sta_add == NULL)
-		return 0;
-	return hapd->driver->sta_add(ifname, hapd->drv_priv, addr, aid,
-				     capability, (u8 *) supp_rates,
-				     supp_rates_len,
-				     flags, listen_interval);
-}
-
-static inline int
-hostapd_get_inact_sec(struct hostapd_data *hapd, const u8 *addr)
-{
-	if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
-		return 0;
-	return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
-}
-
-static inline int
-hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq, int ht_enabled,
-		 int sec_channel_offset)
-{
-	if (hapd->driver == NULL)
-		return 0;
-	if (hapd->driver->set_freq2) {
-		struct hostapd_freq_params data;
-		os_memset(&data, 0, sizeof(data));
-		data.mode = mode;
-		data.freq = freq;
-		data.ht_enabled = ht_enabled;
-		data.sec_channel_offset = sec_channel_offset;
-		return hapd->driver->set_freq2(hapd->drv_priv, &data);
-	}
-
-	if (hapd->driver->set_freq == NULL)
-		return 0;
-	return hapd->driver->set_freq(hapd->drv_priv, mode, freq);
-}
-
-static inline int
-hostapd_set_rts(struct hostapd_data *hapd, int rts)
-{
-	if (hapd->driver == NULL || hapd->driver->set_rts == NULL)
-		return 0;
-	return hapd->driver->set_rts(hapd->drv_priv, rts);
-}
-
-static inline int
-hostapd_get_rts(struct hostapd_data *hapd, int *rts)
-{
-	if (hapd->driver == NULL || hapd->driver->get_rts == NULL)
-		return 0;
-	return hapd->driver->get_rts(hapd->drv_priv, rts);
-}
-
-static inline int
-hostapd_set_frag(struct hostapd_data *hapd, int frag)
-{
-	if (hapd->driver == NULL || hapd->driver->set_frag == NULL)
-		return 0;
-	return hapd->driver->set_frag(hapd->drv_priv, frag);
-}
-
-static inline int
-hostapd_get_frag(struct hostapd_data *hapd, int *frag)
-{
-	if (hapd->driver == NULL || hapd->driver->get_frag == NULL)
-		return 0;
-	return hapd->driver->get_frag(hapd->drv_priv, frag);
-}
-
-static inline int
-hostapd_set_retry(struct hostapd_data *hapd, int short_retry, int long_retry)
-{
-	if (hapd->driver == NULL || hapd->driver->set_retry == NULL)
-		return 0;
-	return hapd->driver->set_retry(hapd->drv_priv, short_retry,
-				       long_retry);
-}
-
-static inline int
-hostapd_get_retry(struct hostapd_data *hapd, int *short_retry, int *long_retry)
-{
-	if (hapd->driver == NULL || hapd->driver->get_retry == NULL)
-		return 0;
-	return hapd->driver->get_retry(hapd->drv_priv, short_retry,
-				       long_retry);
-}
-
-static inline int
-hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
-		      int total_flags, int flags_or, int flags_and)
-{
-	if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
-		return 0;
-	return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
-					   flags_or, flags_and);
-}
-
-static inline int
-hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
-		      int *basic_rates, int mode)
-{
-	if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL)
-		return 0;
-	return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates,
-					   basic_rates, mode);
-}
-
-static inline int
-hostapd_set_regulatory_domain(struct hostapd_data *hapd, unsigned int rd)
-{
-	if (hapd->driver == NULL ||
-	    hapd->driver->set_regulatory_domain == NULL)
-		return 0;
-	return hapd->driver->set_regulatory_domain(hapd->drv_priv, rd);
-}
-
-static inline int
-hostapd_set_country(struct hostapd_data *hapd, const char *country)
-{
-	if (hapd->driver == NULL ||
-	    hapd->driver->set_country == NULL)
-		return 0;
-	return hapd->driver->set_country(hapd->drv_priv, country);
-}
-
-static inline int
-hostapd_set_ieee80211d(struct hostapd_data *hapd, int enabled)
-{
-	if (hapd->driver == NULL ||
-	    hapd->driver->set_ieee80211d == NULL)
-		return 0;
-	return hapd->driver->set_ieee80211d(hapd->drv_priv, enabled);
-}
-
-static inline int
-hostapd_sta_clear_stats(struct hostapd_data *hapd, const u8 *addr)
-{
-	if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
-		return 0;
-	return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
-}
-
-static inline int
-hostapd_set_beacon(const char *ifname, struct hostapd_data *hapd,
-		   u8 *head, size_t head_len,
-		   u8 *tail, size_t tail_len)
-{
-	if (hapd->driver == NULL || hapd->driver->set_beacon == NULL)
-		return 0;
-	return hapd->driver->set_beacon(ifname, hapd->drv_priv, head, head_len,
-					tail, tail_len);
-}
-
-static inline int
-hostapd_set_internal_bridge(struct hostapd_data *hapd, int value)
-{
-	if (hapd->driver == NULL || hapd->driver->set_internal_bridge == NULL)
-		return 0;
-	return hapd->driver->set_internal_bridge(hapd->drv_priv, value);
-}
-
-static inline int
-hostapd_set_beacon_int(struct hostapd_data *hapd, int value)
-{
-	if (hapd->driver == NULL || hapd->driver->set_beacon_int == NULL)
-		return 0;
-	return hapd->driver->set_beacon_int(hapd->drv_priv, value);
-}
-
-static inline int
-hostapd_set_dtim_period(struct hostapd_data *hapd, int value)
-{
-	if (hapd->driver == NULL || hapd->driver->set_dtim_period == NULL)
-		return 0;
-	return hapd->driver->set_dtim_period(hapd->conf->iface, hapd->drv_priv,
-					     value);
-}
-
-static inline int
-hostapd_set_broadcast_ssid(struct hostapd_data *hapd, int value)
-{
-	if (hapd->driver == NULL || hapd->driver->set_broadcast_ssid == NULL)
-		return 0;
-	return hapd->driver->set_broadcast_ssid(hapd->drv_priv, value);
-}
-
-static inline int
-hostapd_set_cts_protect(struct hostapd_data *hapd, int value)
-{
-	if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL)
-		return 0;
-	return hapd->driver->set_cts_protect(hapd->drv_priv, value);
-}
-
-static inline int
-hostapd_set_key_tx_rx_threshold(struct hostapd_data *hapd, int value)
-{
-	if (hapd->driver == NULL ||
-	    hapd->driver->set_key_tx_rx_threshold == NULL)
-		return 0;
-	return hapd->driver->set_key_tx_rx_threshold(hapd->drv_priv, value);
-}
-
-static inline int
-hostapd_set_preamble(struct hostapd_data *hapd, int value)
-{
-	if (hapd->driver == NULL || hapd->driver->set_preamble == NULL)
-		return 0;
-	return hapd->driver->set_preamble(hapd->drv_priv, value);
-}
-
-static inline int
-hostapd_set_short_slot_time(struct hostapd_data *hapd, int value)
-{
-	if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL)
-		return 0;
-	return hapd->driver->set_short_slot_time(hapd->drv_priv, value);
-}
-
-static inline int
-hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
-			    int cw_min, int cw_max, int burst_time)
-{
-	if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL)
-		return 0;
-	return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs,
-						 cw_min, cw_max, burst_time);
-}
-
-static inline int
-hostapd_bss_add(struct hostapd_data *hapd, const char *ifname, const u8 *bssid)
-{
-	if (hapd->driver == NULL || hapd->driver->bss_add == NULL)
-		return 0;
-	return hapd->driver->bss_add(hapd->drv_priv, ifname, bssid);
-}
-
-static inline int
-hostapd_bss_remove(struct hostapd_data *hapd, const char *ifname)
-{
-	if (hapd->driver == NULL || hapd->driver->bss_remove == NULL)
-		return 0;
-	return hapd->driver->bss_remove(hapd->drv_priv, ifname);
-}
-
-static inline int
-hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
-		       const u8 *mask)
-{
-	if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL)
-		return 1;
-	return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask);
-}
-
-static inline int
-hostapd_if_add(struct hostapd_data *hapd, enum hostapd_driver_if_type type,
-	       char *ifname, const u8 *addr)
-{
-	if (hapd->driver == NULL || hapd->driver->if_add == NULL)
-		return -1;
-	return hapd->driver->if_add(hapd->conf->iface, hapd->drv_priv, type,
-				    ifname, addr);
-}
-
-static inline int
-hostapd_if_update(struct hostapd_data *hapd, enum hostapd_driver_if_type type,
-		  char *ifname, const u8 *addr)
-{
-	if (hapd->driver == NULL || hapd->driver->if_update == NULL)
-		return -1;
-	return hapd->driver->if_update(hapd->drv_priv, type, ifname, addr);
-}
-
-static inline int
-hostapd_if_remove(struct hostapd_data *hapd, enum hostapd_driver_if_type type,
-		  char *ifname, const u8 *addr)
-{
-	if (hapd->driver == NULL || hapd->driver->if_remove == NULL)
-		return -1;
-	return hapd->driver->if_remove(hapd->drv_priv, type, ifname, addr);
-}
-
-static inline int
-hostapd_passive_scan(struct hostapd_data *hapd, int now, int our_mode_only,
-		     int interval, int _listen, int *channel,
-		     int *last_rx)
-{
-	if (hapd->driver == NULL || hapd->driver->passive_scan == NULL)
-		return -1;
-	return hapd->driver->passive_scan(hapd->drv_priv, now, our_mode_only,
-					  interval, _listen, channel, last_rx);
-}
-
-static inline struct hostapd_hw_modes *
-hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
-			    u16 *flags)
-{
-	if (hapd->driver == NULL || hapd->driver->get_hw_feature_data == NULL)
-		return NULL;
-	return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
-						 flags);
-}
-
-static inline int
-hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd,
-		     const u8 *addr, int vlan_id)
-{
-	if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
-		return 0;
-	return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname, vlan_id);
-}
-
-static inline int
-hostapd_driver_commit(struct hostapd_data *hapd)
-{
-	if (hapd->driver == NULL || hapd->driver->commit == NULL)
-		return 0;
-	return hapd->driver->commit(hapd->drv_priv);
-}
-
-static inline int
-hostapd_set_radius_acl_auth(struct hostapd_data *hapd, const u8 *mac,
-			    int accepted, u32 session_timeout)
-{
-	if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
-		return 0;
-	return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
-						 session_timeout);
-}
-
-static inline int
-hostapd_set_radius_acl_expire(struct hostapd_data *hapd, const u8 *mac)
-{
-	if (hapd->driver == NULL ||
-	    hapd->driver->set_radius_acl_expire == NULL)
-		return 0;
-	return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
-}
-
-#ifdef CONFIG_IEEE80211N
-static inline int
-hostapd_set_ht_params(const char *ifname, struct hostapd_data *hapd,
-		      const u8 *ht_capab, size_t ht_capab_len,
-		      const u8 *ht_oper, size_t ht_oper_len)
-{
-	if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL ||
-	    ht_capab == NULL || ht_oper == NULL)
-		return 0;
-	return hapd->driver->set_ht_params(
-		ifname, hapd->drv_priv, ht_capab, ht_capab_len,
-		ht_oper, ht_oper_len);
-}
-#endif /* CONFIG_IEEE80211N */
-
-static inline int
-hostapd_drv_none(struct hostapd_data *hapd)
-{
-	return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
-}
-
-static inline int
-hostapd_set_wps_beacon_ie(struct hostapd_data *hapd, const u8 *ie, size_t len)
-{
-	if (hapd->driver == NULL || hapd->driver->set_wps_beacon_ie == NULL)
-		return 0;
-	return hapd->driver->set_wps_beacon_ie(hapd->conf->iface,
-					       hapd->drv_priv, ie, len);
-}
-
-static inline int
-hostapd_set_wps_probe_resp_ie(struct hostapd_data *hapd, const u8 *ie,
-			      size_t len)
-{
-	if (hapd->driver == NULL ||
-	    hapd->driver->set_wps_probe_resp_ie == NULL)
-		return 0;
-	return hapd->driver->set_wps_probe_resp_ie(hapd->conf->iface,
-						   hapd->drv_priv, ie, len);
-}
-
-#endif /* DRIVER_H */
diff --git a/contrib/wpa/hostapd/driver_bsd.c b/contrib/wpa/hostapd/driver_bsd.c
deleted file mode 100644
index 43d57d9091d3..000000000000
--- a/contrib/wpa/hostapd/driver_bsd.c
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * hostapd / Driver interaction with BSD net80211 layer
- * Copyright (c) 2004, Sam Leffler 
- * Copyright (c) 2004, 2Wire, Inc
- *
- * 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 
-
-#include 
-
-#include 
-#include 
-#include 
-
-/*
- * Avoid conflicts with hostapd definitions by undefining couple of defines
- * from net80211 header files.
- */
-#undef RSN_VERSION
-#undef WPA_VERSION
-#undef WPA_OUI_TYPE
-#undef WME_OUI_TYPE
-
-#include "hostapd.h"
-#include "driver.h"
-#include "ieee802_1x.h"
-#include "eloop.h"
-#include "sta_info.h"
-#include "l2_packet/l2_packet.h"
-
-#include "eapol_sm.h"
-#include "wpa.h"
-#include "radius/radius.h"
-#include "ieee802_11.h"
-#include "common.h"
-
-struct bsd_driver_data {
-	struct hostapd_data *hapd;		/* back pointer */
-
-	char	iface[IFNAMSIZ + 1];
-	struct l2_packet_data *sock_xmit;	/* raw packet xmit socket */
-	int	ioctl_sock;			/* socket for ioctl() use */
-	int	wext_sock;			/* socket for wireless events */
-};
-
-static int bsd_sta_deauth(void *priv, const u8 *addr, int reason_code);
-
-static int
-set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len)
-{
-	struct ieee80211req ireq;
-
-	memset(&ireq, 0, sizeof(ireq));
-	os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
-	ireq.i_type = op;
-	ireq.i_len = arg_len;
-	ireq.i_data = (void *) arg;
-
-	if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) {
-		perror("ioctl[SIOCS80211]");
-		return -1;
-	}
-	return 0;
-}
-
-static int
-get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len)
-{
-	struct ieee80211req ireq;
-
-	memset(&ireq, 0, sizeof(ireq));
-	os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
-	ireq.i_type = op;
-	ireq.i_len = arg_len;
-	ireq.i_data = arg;
-
-	if (ioctl(drv->ioctl_sock, SIOCG80211, &ireq) < 0) {
-		perror("ioctl[SIOCG80211]");
-		return -1;
-	}
-	return ireq.i_len;
-}
-
-static int
-set80211param(struct bsd_driver_data *drv, int op, int arg)
-{
-	struct ieee80211req ireq;
-
-	memset(&ireq, 0, sizeof(ireq));
-	os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ);
-	ireq.i_type = op;
-	ireq.i_val = arg;
-
-	if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) {
-		perror("ioctl[SIOCS80211]");
-		return -1;
-	}
-	return 0;
-}
-
-static const char *
-ether_sprintf(const u8 *addr)
-{
-	static char buf[sizeof(MACSTR)];
-
-	if (addr != NULL)
-		snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
-	else
-		snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
-	return buf;
-}
-
-/*
- * Configure WPA parameters.
- */
-static int
-bsd_configure_wpa(struct bsd_driver_data *drv)
-{
-	static const char *ciphernames[] =
-		{ "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" };
-	struct hostapd_data *hapd = drv->hapd;
-	struct hostapd_bss_config *conf = hapd->conf;
-	int v;
-
-	switch (conf->wpa_group) {
-	case WPA_CIPHER_CCMP:
-		v = IEEE80211_CIPHER_AES_CCM;
-		break;
-	case WPA_CIPHER_TKIP:
-		v = IEEE80211_CIPHER_TKIP;
-		break;
-	case WPA_CIPHER_WEP104:
-		v = IEEE80211_CIPHER_WEP;
-		break;
-	case WPA_CIPHER_WEP40:
-		v = IEEE80211_CIPHER_WEP;
-		break;
-	case WPA_CIPHER_NONE:
-		v = IEEE80211_CIPHER_NONE;
-		break;
-	default:
-		printf("Unknown group key cipher %u\n",
-			conf->wpa_group);
-		return -1;
-	}
-	wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)",
-		   __func__, ciphernames[v], v);
-	if (set80211param(drv, IEEE80211_IOC_MCASTCIPHER, v)) {
-		printf("Unable to set group key cipher to %u (%s)\n",
-			v, ciphernames[v]);
-		return -1;
-	}
-	if (v == IEEE80211_CIPHER_WEP) {
-		/* key length is done only for specific ciphers */
-		v = (conf->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5);
-		if (set80211param(drv, IEEE80211_IOC_MCASTKEYLEN, v)) {
-			printf("Unable to set group key length to %u\n", v);
-			return -1;
-		}
-	}
-
-	v = 0;
-	if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
-		v |= 1<wpa_pairwise & WPA_CIPHER_TKIP)
-		v |= 1<wpa_pairwise & WPA_CIPHER_NONE)
-		v |= 1<wpa_key_mgmt);
-	if (set80211param(drv, IEEE80211_IOC_KEYMGTALGS, conf->wpa_key_mgmt)) {
-		printf("Unable to set key management algorithms to 0x%x\n",
-			conf->wpa_key_mgmt);
-		return -1;
-	}
-
-	v = 0;
-	if (conf->rsn_preauth)
-		v |= BIT(0);
-	wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x",
-		   __func__, conf->rsn_preauth);
-	if (set80211param(drv, IEEE80211_IOC_RSNCAPS, v)) {
-		printf("Unable to set RSN capabilities to 0x%x\n", v);
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, conf->wpa);
-	if (set80211param(drv, IEEE80211_IOC_WPA, conf->wpa)) {
-		printf("Unable to set WPA to %u\n", conf->wpa);
-		return -1;
-	}
-	return 0;
-}
-
-
-static int
-bsd_set_iface_flags(void *priv, int dev_up)
-{
-	struct bsd_driver_data *drv = priv;
-	struct ifreq ifr;
-
-	wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up);
-
-	if (drv->ioctl_sock < 0)
-		return -1;
-
-	memset(&ifr, 0, sizeof(ifr));
-	os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
-
-	if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
-		perror("ioctl[SIOCGIFFLAGS]");
-		return -1;
-	}
-
-	if (dev_up)
-		ifr.ifr_flags |= IFF_UP;
-	else
-		ifr.ifr_flags &= ~IFF_UP;
-
-	if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
-		perror("ioctl[SIOCSIFFLAGS]");
-		return -1;
-	}
-
-	if (dev_up) {
-		memset(&ifr, 0, sizeof(ifr));
-		os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
-		ifr.ifr_mtu = HOSTAPD_MTU;
-		if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
-			perror("ioctl[SIOCSIFMTU]");
-			printf("Setting MTU failed - trying to survive with "
-			       "current value\n");
-		}
-	}
-
-	return 0;
-}
-
-static int
-bsd_set_ieee8021x(const char *ifname, void *priv, int enabled)
-{
-	struct bsd_driver_data *drv = priv;
-	struct hostapd_data *hapd = drv->hapd;
-	struct hostapd_bss_config *conf = hapd->conf;
-
-	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
-
-	if (!enabled) {
-		/* XXX restore state */
-		return set80211param(priv, IEEE80211_IOC_AUTHMODE,
-			IEEE80211_AUTH_AUTO);
-	}
-	if (!conf->wpa && !conf->ieee802_1x) {
-		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
-			HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
-		return -1;
-	}
-	if (conf->wpa && bsd_configure_wpa(drv) != 0) {
-		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
-			HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
-		return -1;
-	}
-	if (set80211param(priv, IEEE80211_IOC_AUTHMODE,
-		(conf->wpa ?  IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
-		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER,
-			HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!");
-		return -1;
-	}
-	return bsd_set_iface_flags(priv, 1);
-}
-
-static int
-bsd_set_privacy(const char *ifname, void *priv, int enabled)
-{
-	struct bsd_driver_data *drv = priv;
-
-	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
-
-	return set80211param(drv, IEEE80211_IOC_PRIVACY, enabled);
-}
-
-static int
-bsd_set_sta_authorized(void *priv, const u8 *addr, int authorized)
-{
-	struct bsd_driver_data *drv = priv;
-	struct ieee80211req_mlme mlme;
-
-	wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d",
-		   __func__, ether_sprintf(addr), authorized);
-
-	if (authorized)
-		mlme.im_op = IEEE80211_MLME_AUTHORIZE;
-	else
-		mlme.im_op = IEEE80211_MLME_UNAUTHORIZE;
-	mlme.im_reason = 0;
-	memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
-	return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
-}
-
-static int
-bsd_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or,
-		  int flags_and)
-{
-	/* For now, only support setting Authorized flag */
-	if (flags_or & WLAN_STA_AUTHORIZED)
-		return bsd_set_sta_authorized(priv, addr, 1);
-	if (!(flags_and & WLAN_STA_AUTHORIZED))
-		return bsd_set_sta_authorized(priv, addr, 0);
-	return 0;
-}
-
-static int
-bsd_del_key(void *priv, const u8 *addr, int key_idx)
-{
-	struct bsd_driver_data *drv = priv;
-	struct ieee80211req_del_key wk;
-
-	wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d",
-		   __func__, ether_sprintf(addr), key_idx);
-
-	memset(&wk, 0, sizeof(wk));
-	if (addr != NULL) {
-		memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
-		wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE;	/* XXX */
-	} else {
-		wk.idk_keyix = key_idx;
-	}
-
-	return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk));
-}
-
-static int
-bsd_set_key(const char *ifname, void *priv, const char *alg,
-	    const u8 *addr, int key_idx,
-	    const u8 *key, size_t key_len, int txkey)
-{
-	struct bsd_driver_data *drv = priv;
-	struct ieee80211req_key wk;
-	u_int8_t cipher;
-
-	if (strcmp(alg, "none") == 0)
-		return bsd_del_key(drv, addr, key_idx);
-
-	wpa_printf(MSG_DEBUG, "%s: alg=%s addr=%s key_idx=%d",
-		   __func__, alg, ether_sprintf(addr), key_idx);
-
-	if (strcmp(alg, "WEP") == 0)
-		cipher = IEEE80211_CIPHER_WEP;
-	else if (strcmp(alg, "TKIP") == 0)
-		cipher = IEEE80211_CIPHER_TKIP;
-	else if (strcmp(alg, "CCMP") == 0)
-		cipher = IEEE80211_CIPHER_AES_CCM;
-	else {
-		printf("%s: unknown/unsupported algorithm %s\n",
-			__func__, alg);
-		return -1;
-	}
-
-	if (key_len > sizeof(wk.ik_keydata)) {
-		printf("%s: key length %d too big\n", __func__, key_len);
-		return -3;
-	}
-
-	memset(&wk, 0, sizeof(wk));
-	wk.ik_type = cipher;
-	wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
-	if (addr == NULL) {
-		memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
-		wk.ik_keyix = key_idx;
-		wk.ik_flags |= IEEE80211_KEY_DEFAULT;
-	} else {
-		memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
-		wk.ik_keyix = IEEE80211_KEYIX_NONE;
-	}
-	wk.ik_keylen = key_len;
-	memcpy(wk.ik_keydata, key, key_len);
-
-	return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
-}
-
-
-static int
-bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
-	       u8 *seq)
-{
-	struct bsd_driver_data *drv = priv;
-	struct ieee80211req_key wk;
-
-	wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
-		   __func__, ether_sprintf(addr), idx);
-
-	memset(&wk, 0, sizeof(wk));
-	if (addr == NULL)
-		memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
-	else
-		memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
-	wk.ik_keyix = idx;
-
-	if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) {
-		printf("Failed to get encryption.\n");
-		return -1;
-	}
-
-#ifdef WORDS_BIGENDIAN
-	{
-		/*
-		 * wk.ik_keytsc is in host byte order (big endian), need to
-		 * swap it to match with the byte order used in WPA.
-		 */
-		int i;
-		u8 tmp[WPA_KEY_RSC_LEN];
-		memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
-		for (i = 0; i < WPA_KEY_RSC_LEN; i++) {
-			seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1];
-		}
-	}
-#else /* WORDS_BIGENDIAN */
-	memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
-#endif /* WORDS_BIGENDIAN */
-	return 0;
-}
-
-
-static int 
-bsd_flush(void *priv)
-{
-	u8 allsta[IEEE80211_ADDR_LEN];
-
-	memset(allsta, 0xff, IEEE80211_ADDR_LEN);
-	return bsd_sta_deauth(priv, allsta, IEEE80211_REASON_AUTH_LEAVE);
-}
-
-
-static int
-bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data,
-			 const u8 *addr)
-{
-	struct bsd_driver_data *drv = priv;
-	struct ieee80211req_sta_stats stats;
-
-	memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
-	if (get80211var(drv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) > 0) {
-		/* XXX? do packets counts include non-data frames? */
-		data->rx_packets = stats.is_stats.ns_rx_data;
-		data->rx_bytes = stats.is_stats.ns_rx_bytes;
-		data->tx_packets = stats.is_stats.ns_tx_data;
-		data->tx_bytes = stats.is_stats.ns_tx_bytes;
-	}
-	return 0;
-}
-
-static int
-bsd_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len)
-{
-	/*
-	 * Do nothing; we setup parameters at startup that define the
-	 * contents of the beacon information element.
-	 */
-	return 0;
-}
-
-static int
-bsd_sta_deauth(void *priv, const u8 *addr, int reason_code)
-{
-	struct bsd_driver_data *drv = priv;
-	struct ieee80211req_mlme mlme;
-
-	wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d",
-		   __func__, ether_sprintf(addr), reason_code);
-
-	mlme.im_op = IEEE80211_MLME_DEAUTH;
-	mlme.im_reason = reason_code;
-	memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
-	return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
-}
-
-static int
-bsd_sta_disassoc(void *priv, const u8 *addr, int reason_code)
-{
-	struct bsd_driver_data *drv = priv;
-	struct ieee80211req_mlme mlme;
-
-	wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d",
-		   __func__, ether_sprintf(addr), reason_code);
-
-	mlme.im_op = IEEE80211_MLME_DISASSOC;
-	mlme.im_reason = reason_code;
-	memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
-	return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme));
-}
-
-static int
-bsd_del_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
-{
-	struct hostapd_data *hapd = drv->hapd;
-	struct hostapd_bss_config *conf = hapd->conf;
-	struct sta_info *sta;
-
-	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
-		HOSTAPD_LEVEL_INFO, "deassociated");
-
-	sta = ap_get_sta(hapd, addr);
-	if (sta != NULL) {
-		sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
-		if (conf->wpa)
-			wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
-		sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
-		ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
-		ap_free_sta(hapd, sta);
-	}
-	return 0;
-}
-
-static int
-bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
-{
-	struct hostapd_data *hapd = drv->hapd;
-	struct hostapd_bss_config *conf = hapd->conf;
-	struct sta_info *sta;
-	struct ieee80211req_wpaie ie;
-	int new_assoc, ielen, res;
-
-	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
-		HOSTAPD_LEVEL_INFO, "associated");
-
-	sta = ap_sta_add(hapd, addr);
-	if (sta == NULL)
-		return -1;
-	/*
-	 * Fetch and validate any negotiated WPA/RSN parameters.
-	 */
-	if (conf->wpa) {
-		memset(&ie, 0, sizeof(ie));
-		memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
-		if (get80211var(drv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) {
-			printf("Failed to get WPA/RSN information element.\n");
-			return -1;		/* XXX not right */
-		}
-		ielen = ie.wpa_ie[1];
-		if (ielen == 0) {
-			printf("No WPA/RSN information element for station!\n");
-			return -1;		/* XXX not right */
-		}
-		ielen += 2;
-		if (sta->wpa_sm == NULL)
-			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
-							sta->addr);
-		if (sta->wpa_sm == NULL) {
-			printf("Failed to initialize WPA state machine\n");
-			return -1;
-		}
-		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
-					  ie.wpa_ie, ielen, NULL, 0);
-		if (res != WPA_IE_OK) {
-			printf("WPA/RSN information element rejected? "
-				"(res %u)\n", res);
-			return -1;
-		}
-	}
-
-	/*
-	 * Now that the internal station state is setup
-	 * kick the authenticator into action.
-	 */
-	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
-	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
-	wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
-	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
-	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
-	return 0;
-}
-
-#include 
-#include 
-
-static void
-bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
-{
-	struct bsd_driver_data *drv = ctx;
-	struct hostapd_data *hapd = drv->hapd;
-	char buf[2048];
-	struct if_announcemsghdr *ifan;
-	struct rt_msghdr *rtm;
-	struct ieee80211_michael_event *mic;
-	struct ieee80211_join_event *join;
-	struct ieee80211_leave_event *leave;
-	int n;
-
-	n = read(sock, buf, sizeof(buf));
-	if (n < 0) {
-		if (errno != EINTR && errno != EAGAIN)
-			perror("read(PF_ROUTE)");
-		return;
-	}
-
-	rtm = (struct rt_msghdr *) buf;
-	if (rtm->rtm_version != RTM_VERSION) {
-		wpa_printf(MSG_DEBUG, "Routing message version %d not "
-			"understood\n", rtm->rtm_version);
-		return;
-	}
-	ifan = (struct if_announcemsghdr *) rtm;
-	switch (rtm->rtm_type) {
-	case RTM_IEEE80211:
-		switch (ifan->ifan_what) {
-		case RTM_IEEE80211_ASSOC:
-		case RTM_IEEE80211_REASSOC:
-		case RTM_IEEE80211_DISASSOC:
-		case RTM_IEEE80211_SCAN:
-			break;
-		case RTM_IEEE80211_LEAVE:
-			leave = (struct ieee80211_leave_event *) &ifan[1];
-			bsd_del_sta(drv, leave->iev_addr);
-			break;
-		case RTM_IEEE80211_JOIN:
-#ifdef RTM_IEEE80211_REJOIN
-		case RTM_IEEE80211_REJOIN:
-#endif
-			join = (struct ieee80211_join_event *) &ifan[1];
-			bsd_new_sta(drv, join->iev_addr);
-			break;
-		case RTM_IEEE80211_REPLAY:
-			/* ignore */
-			break;
-		case RTM_IEEE80211_MICHAEL:
-			mic = (struct ieee80211_michael_event *) &ifan[1];
-			wpa_printf(MSG_DEBUG,
-				"Michael MIC failure wireless event: "
-				"keyix=%u src_addr=" MACSTR, mic->iev_keyix,
-				MAC2STR(mic->iev_src));
-			ieee80211_michael_mic_failure(hapd, mic->iev_src, 1);
-			break;
-		}
-		break;
-	}
-}
-
-static int
-bsd_wireless_event_init(void *priv)
-{
-	struct bsd_driver_data *drv = priv;
-	int s;
-
-	drv->wext_sock = -1;
-
-	s = socket(PF_ROUTE, SOCK_RAW, 0);
-	if (s < 0) {
-		perror("socket(PF_ROUTE,SOCK_RAW)");
-		return -1;
-	}
-	eloop_register_read_sock(s, bsd_wireless_event_receive, drv, NULL);
-	drv->wext_sock = s;
-
-	return 0;
-}
-
-static void
-bsd_wireless_event_deinit(void *priv)
-{
-	struct bsd_driver_data *drv = priv;
-
-	if (drv != NULL) {
-		if (drv->wext_sock < 0)
-			return;
-		eloop_unregister_read_sock(drv->wext_sock);
-		close(drv->wext_sock);
-	}
-}
-
-
-static int
-bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
-	       int encrypt, const u8 *own_addr)
-{
-	struct bsd_driver_data *drv = priv;
-	unsigned char buf[3000];
-	unsigned char *bp = buf;
-	struct l2_ethhdr *eth;
-	size_t len;
-	int status;
-
-	/*
-	 * Prepend the Etherent header.  If the caller left us
-	 * space at the front we could just insert it but since
-	 * we don't know we copy to a local buffer.  Given the frequency
-	 * and size of frames this probably doesn't matter.
-	 */
-	len = data_len + sizeof(struct l2_ethhdr);
-	if (len > sizeof(buf)) {
-		bp = malloc(len);
-		if (bp == NULL) {
-			printf("EAPOL frame discarded, cannot malloc temp "
-				"buffer of size %u!\n", len);
-			return -1;
-		}
-	}
-	eth = (struct l2_ethhdr *) bp;
-	memcpy(eth->h_dest, addr, ETH_ALEN);
-	memcpy(eth->h_source, own_addr, ETH_ALEN);
-	eth->h_proto = htons(ETH_P_EAPOL);
-	memcpy(eth+1, data, data_len);
-
-	wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
-
-	status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len);
-
-	if (bp != buf)
-		free(bp);
-	return status;
-}
-
-static void
-handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
-{
-	struct bsd_driver_data *drv = ctx;
-	struct hostapd_data *hapd = drv->hapd;
-	struct sta_info *sta;
-
-	sta = ap_get_sta(hapd, src_addr);
-	if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
-		printf("Data frame from not associated STA %s\n",
-		       ether_sprintf(src_addr));
-		/* XXX cannot happen */
-		return;
-	}
-	ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr),
-			   len - sizeof(struct l2_ethhdr));
-}
-
-static int
-bsd_get_ssid(const char *ifname, void *priv, u8 *buf, int len)
-{
-	struct bsd_driver_data *drv = priv;
-	int ssid_len = get80211var(drv, IEEE80211_IOC_SSID, buf, len);
-
-	wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, ssid_len, buf);
-
-	return ssid_len;
-}
-
-static int
-bsd_set_ssid(const char *ifname, void *priv, const u8 *buf, int len)
-{
-	struct bsd_driver_data *drv = priv;
-
-	wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, len, buf);
-
-	return set80211var(drv, IEEE80211_IOC_SSID, buf, len);
-}
-
-static void *
-bsd_init(struct hostapd_data *hapd)
-{
-	struct bsd_driver_data *drv;
-
-	drv = os_zalloc(sizeof(struct bsd_driver_data));
-	if (drv == NULL) {
-		printf("Could not allocate memory for bsd driver data\n");
-		goto bad;
-	}
-
-	drv->hapd = hapd;
-	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
-	if (drv->ioctl_sock < 0) {
-		perror("socket[PF_INET,SOCK_DGRAM]");
-		goto bad;
-	}
-	memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
-
-	drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL,
-					handle_read, drv, 1);
-	if (drv->sock_xmit == NULL)
-		goto bad;
-	if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr))
-		goto bad;
-
-	bsd_set_iface_flags(drv, 0);	/* mark down during setup */
-
-	return drv;
-bad:
-	if (drv->sock_xmit != NULL)
-		l2_packet_deinit(drv->sock_xmit);
-	if (drv->ioctl_sock >= 0)
-		close(drv->ioctl_sock);
-	if (drv != NULL)
-		free(drv);
-	return NULL;
-}
-
-
-static void
-bsd_deinit(void *priv)
-{
-	struct bsd_driver_data *drv = priv;
-
-	(void) bsd_set_iface_flags(drv, 0);
-	if (drv->ioctl_sock >= 0)
-		close(drv->ioctl_sock);
-	if (drv->sock_xmit != NULL)
-		l2_packet_deinit(drv->sock_xmit);
-	free(drv);
-}
-
-const struct wpa_driver_ops wpa_driver_bsd_ops = {
-	.name			= "bsd",
-	.init			= bsd_init,
-	.deinit			= bsd_deinit,
-	.set_ieee8021x		= bsd_set_ieee8021x,
-	.set_privacy		= bsd_set_privacy,
-	.set_encryption		= bsd_set_key,
-	.get_seqnum		= bsd_get_seqnum,
-	.flush			= bsd_flush,
-	.set_generic_elem	= bsd_set_opt_ie,
-	.wireless_event_init	= bsd_wireless_event_init,
-	.wireless_event_deinit	= bsd_wireless_event_deinit,
-	.sta_set_flags		= bsd_sta_set_flags,
-	.read_sta_data		= bsd_read_sta_driver_data,
-	.send_eapol		= bsd_send_eapol,
-	.sta_disassoc		= bsd_sta_disassoc,
-	.sta_deauth		= bsd_sta_deauth,
-	.set_ssid		= bsd_set_ssid,
-	.get_ssid		= bsd_get_ssid,
-};
diff --git a/contrib/wpa/hostapd/driver_hostap.c b/contrib/wpa/hostapd/driver_hostap.c
deleted file mode 100644
index ceff0998919c..000000000000
--- a/contrib/wpa/hostapd/driver_hostap.c
+++ /dev/null
@@ -1,1279 +0,0 @@
-/*
- * hostapd / Kernel driver communication with Linux Host AP driver
- * Copyright (c) 2002-2007, Jouni Malinen 
- *
- * 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 
-
-#ifdef USE_KERNEL_HEADERS
-/* compat-wireless does not include linux/compiler.h to define __user, so
- * define it here */
-#ifndef __user
-#define __user
-#endif /* __user */
-#include 
-#include 
-#include    /* The L2 protocols */
-#include 
-#include 
-#else /* USE_KERNEL_HEADERS */
-#include 
-#include 
-#include "wireless_copy.h"
-#endif /* USE_KERNEL_HEADERS */
-
-#include "hostapd.h"
-#include "driver.h"
-#include "ieee802_1x.h"
-#include "eloop.h"
-#include "priv_netlink.h"
-#include "ieee802_11.h"
-#include "sta_info.h"
-#include "hostap_common.h"
-#include "hw_features.h"
-
-
-struct hostap_driver_data {
-	struct hostapd_data *hapd;
-
-	char iface[IFNAMSIZ + 1];
-	int sock; /* raw packet socket for driver access */
-	int ioctl_sock; /* socket for ioctl() use */
-	int wext_sock; /* socket for wireless events */
-
-	int we_version;
-
-	u8 *generic_ie;
-	size_t generic_ie_len;
-	u8 *wps_ie;
-	size_t wps_ie_len;
-};
-
-
-static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
-			 int len);
-static int hostap_set_iface_flags(void *priv, int dev_up);
-
-static void handle_data(struct hostapd_data *hapd, u8 *buf, size_t len,
-			u16 stype)
-{
-	struct ieee80211_hdr *hdr;
-	u16 fc, ethertype;
-	u8 *pos, *sa;
-	size_t left;
-	struct sta_info *sta;
-
-	if (len < sizeof(struct ieee80211_hdr))
-		return;
-
-	hdr = (struct ieee80211_hdr *) buf;
-	fc = le_to_host16(hdr->frame_control);
-
-	if ((fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) != WLAN_FC_TODS) {
-		printf("Not ToDS data frame (fc=0x%04x)\n", fc);
-		return;
-	}
-
-	sa = hdr->addr2;
-	sta = ap_get_sta(hapd, sa);
-	if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
-		printf("Data frame from not associated STA " MACSTR "\n",
-		       MAC2STR(sa));
-		if (sta && (sta->flags & WLAN_STA_AUTH))
-			hostapd_sta_disassoc(
-				hapd, sa,
-				WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
-		else
-			hostapd_sta_deauth(
-				hapd, sa,
-				WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
-		return;
-	}
-
-	pos = (u8 *) (hdr + 1);
-	left = len - sizeof(*hdr);
-
-	if (left < sizeof(rfc1042_header)) {
-		printf("Too short data frame\n");
-		return;
-	}
-
-	if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) {
-		printf("Data frame with no RFC1042 header\n");
-		return;
-	}
-	pos += sizeof(rfc1042_header);
-	left -= sizeof(rfc1042_header);
-
-	if (left < 2) {
-		printf("No ethertype in data frame\n");
-		return;
-	}
-
-	ethertype = WPA_GET_BE16(pos);
-	pos += 2;
-	left -= 2;
-	switch (ethertype) {
-	case ETH_P_PAE:
-		ieee802_1x_receive(hapd, sa, pos, left);
-		break;
-
-	default:
-		printf("Unknown ethertype 0x%04x in data frame\n", ethertype);
-		break;
-	}
-}
-
-
-static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
-			       int ok)
-{
-	struct ieee80211_hdr *hdr;
-	u16 fc, type, stype;
-	struct sta_info *sta;
-
-	hdr = (struct ieee80211_hdr *) buf;
-	fc = le_to_host16(hdr->frame_control);
-
-	type = WLAN_FC_GET_TYPE(fc);
-	stype = WLAN_FC_GET_STYPE(fc);
-
-	switch (type) {
-	case WLAN_FC_TYPE_MGMT:
-		wpa_printf(MSG_DEBUG, "MGMT (TX callback) %s",
-			   ok ? "ACK" : "fail");
-		ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
-		break;
-	case WLAN_FC_TYPE_CTRL:
-		wpa_printf(MSG_DEBUG, "CTRL (TX callback) %s",
-			   ok ? "ACK" : "fail");
-		break;
-	case WLAN_FC_TYPE_DATA:
-		wpa_printf(MSG_DEBUG, "DATA (TX callback) %s",
-			   ok ? "ACK" : "fail");
-		sta = ap_get_sta(hapd, hdr->addr1);
-		if (sta && sta->flags & WLAN_STA_PENDING_POLL) {
-			wpa_printf(MSG_DEBUG, "STA " MACSTR
-				   " %s pending activity poll",
-				   MAC2STR(sta->addr),
-				   ok ? "ACKed" : "did not ACK");
-			if (ok)
-				sta->flags &= ~WLAN_STA_PENDING_POLL;
-		}
-		if (sta)
-			ieee802_1x_tx_status(hapd, sta, buf, len, ok);
-		break;
-	default:
-		printf("unknown TX callback frame type %d\n", type);
-		break;
-	}
-}
-
-
-static void handle_frame(struct hostapd_data *hapd, u8 *buf, size_t len)
-{
-	struct ieee80211_hdr *hdr;
-	u16 fc, extra_len, type, stype;
-	unsigned char *extra = NULL;
-	size_t data_len = len;
-	int ver;
-
-	/* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
-	 * these to user space */
-	if (len < 24) {
-		wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)",
-			   (unsigned long) len);
-		return;
-	}
-
-	hdr = (struct ieee80211_hdr *) buf;
-	fc = le_to_host16(hdr->frame_control);
-	type = WLAN_FC_GET_TYPE(fc);
-	stype = WLAN_FC_GET_STYPE(fc);
-
-	if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) {
-		wpa_hexdump(MSG_MSGDUMP, "Received management frame",
-			    buf, len);
-	}
-
-	ver = fc & WLAN_FC_PVER;
-
-	/* protocol version 3 is reserved for indicating extra data after the
-	 * payload, version 2 for indicating ACKed frame (TX callbacks), and
-	 * version 1 for indicating failed frame (no ACK, TX callbacks) */
-	if (ver == 3) {
-		u8 *pos = buf + len - 2;
-		extra_len = WPA_GET_LE16(pos);
-		printf("extra data in frame (elen=%d)\n", extra_len);
-		if ((size_t) extra_len + 2 > len) {
-			printf("  extra data overflow\n");
-			return;
-		}
-		len -= extra_len + 2;
-		extra = buf + len;
-	} else if (ver == 1 || ver == 2) {
-		handle_tx_callback(hapd, buf, data_len, ver == 2 ? 1 : 0);
-		return;
-	} else if (ver != 0) {
-		printf("unknown protocol version %d\n", ver);
-		return;
-	}
-
-	switch (type) {
-	case WLAN_FC_TYPE_MGMT:
-		if (stype != WLAN_FC_STYPE_BEACON)
-			wpa_printf(MSG_MSGDUMP, "MGMT");
-		ieee802_11_mgmt(hapd, buf, data_len, stype, NULL);
-		break;
-	case WLAN_FC_TYPE_CTRL:
-		wpa_printf(MSG_DEBUG, "CTRL");
-		break;
-	case WLAN_FC_TYPE_DATA:
-		wpa_printf(MSG_DEBUG, "DATA");
-		handle_data(hapd, buf, data_len, stype);
-		break;
-	default:
-		wpa_printf(MSG_DEBUG, "unknown frame type %d", type);
-		break;
-	}
-}
-
-
-static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
-{
-	struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
-	int len;
-	unsigned char buf[3000];
-
-	len = recv(sock, buf, sizeof(buf), 0);
-	if (len < 0) {
-		perror("recv");
-		return;
-	}
-
-	handle_frame(hapd, buf, len);
-}
-
-
-static int hostap_init_sockets(struct hostap_driver_data *drv)
-{
-	struct ifreq ifr;
-	struct sockaddr_ll addr;
-
-	drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
-	if (drv->sock < 0) {
-		perror("socket[PF_PACKET,SOCK_RAW]");
-		return -1;
-	}
-
-	if (eloop_register_read_sock(drv->sock, handle_read, drv->hapd, NULL))
-	{
-		printf("Could not register read socket\n");
-		return -1;
-	}
-
-        memset(&ifr, 0, sizeof(ifr));
-        snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
-        if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
-		perror("ioctl(SIOCGIFINDEX)");
-		return -1;
-        }
-
-	if (hostap_set_iface_flags(drv, 1)) {
-		return -1;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sll_family = AF_PACKET;
-	addr.sll_ifindex = ifr.ifr_ifindex;
-	wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
-		   addr.sll_ifindex);
-
-	if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("bind");
-		return -1;
-	}
-
-        memset(&ifr, 0, sizeof(ifr));
-        os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
-        if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
-		perror("ioctl(SIOCGIFHWADDR)");
-		return -1;
-        }
-
-	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
-		printf("Invalid HW-addr family 0x%04x\n",
-		       ifr.ifr_hwaddr.sa_family);
-		return -1;
-	}
-	memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
-
-	return 0;
-}
-
-
-static int hostap_send_mgmt_frame(void *priv, const void *msg, size_t len,
-				  int flags)
-{
-	struct hostap_driver_data *drv = priv;
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg;
-	int res;
-
-	/* Request TX callback */
-	hdr->frame_control |= host_to_le16(BIT(1));
-	res = send(drv->sock, msg, len, flags);
-	hdr->frame_control &= ~host_to_le16(BIT(1));
-
-	return res;
-}
-
-
-static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data,
-			     size_t data_len, int encrypt, const u8 *own_addr)
-{
-	struct hostap_driver_data *drv = priv;
-	struct ieee80211_hdr *hdr;
-	size_t len;
-	u8 *pos;
-	int res;
-
-	len = sizeof(*hdr) + sizeof(rfc1042_header) + 2 + data_len;
-	hdr = os_zalloc(len);
-	if (hdr == NULL) {
-		printf("malloc() failed for hostapd_send_data(len=%lu)\n",
-		       (unsigned long) len);
-		return -1;
-	}
-
-	hdr->frame_control =
-		IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
-	hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
-	if (encrypt)
-		hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
-	memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
-	memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
-	memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
-
-	pos = (u8 *) (hdr + 1);
-	memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
-	pos += sizeof(rfc1042_header);
-	*((u16 *) pos) = htons(ETH_P_PAE);
-	pos += 2;
-	memcpy(pos, data, data_len);
-
-	res = hostap_send_mgmt_frame(drv, (u8 *) hdr, len, 0);
-	free(hdr);
-
-	if (res < 0) {
-		perror("hostapd_send_eapol: send");
-		printf("hostapd_send_eapol - packet len: %lu - failed\n",
-		       (unsigned long) len);
-	}
-
-	return res;
-}
-
-
-static int hostap_sta_set_flags(void *priv, const u8 *addr,
-				int total_flags, int flags_or, int flags_and)
-{
-	struct hostap_driver_data *drv = priv;
-	struct prism2_hostapd_param param;
-
-	memset(¶m, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA;
-	memcpy(param.sta_addr, addr, ETH_ALEN);
-	param.u.set_flags_sta.flags_or = flags_or;
-	param.u.set_flags_sta.flags_and = flags_and;
-	return hostapd_ioctl(drv, ¶m, sizeof(param));
-}
-
-
-static int hostap_set_iface_flags(void *priv, int dev_up)
-{
-	struct hostap_driver_data *drv = priv;
-	struct ifreq ifr;
-
-	if (drv->ioctl_sock < 0)
-		return -1;
-
-	memset(&ifr, 0, sizeof(ifr));
-	snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", drv->iface);
-
-	if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
-		perror("ioctl[SIOCGIFFLAGS]");
-		return -1;
-	}
-
-	if (dev_up)
-		ifr.ifr_flags |= IFF_UP;
-	else
-		ifr.ifr_flags &= ~IFF_UP;
-
-	if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
-		perror("ioctl[SIOCSIFFLAGS]");
-		return -1;
-	}
-
-	if (dev_up) {
-		memset(&ifr, 0, sizeof(ifr));
-		snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", drv->iface);
-		ifr.ifr_mtu = HOSTAPD_MTU;
-		if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
-			perror("ioctl[SIOCSIFMTU]");
-			printf("Setting MTU failed - trying to survive with "
-			       "current value\n");
-		}
-	}
-
-	return 0;
-}
-
-
-static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
-			 int len)
-{
-	struct hostap_driver_data *drv = priv;
-	struct iwreq iwr;
-
-	memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
-	iwr.u.data.pointer = (caddr_t) param;
-	iwr.u.data.length = len;
-
-	if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
-		perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static int hostap_set_encryption(const char *ifname, void *priv,
-				 const char *alg, const u8 *addr,
-				 int idx, const u8 *key, size_t key_len,
-				 int txkey)
-{
-	struct hostap_driver_data *drv = priv;
-	struct prism2_hostapd_param *param;
-	u8 *buf;
-	size_t blen;
-	int ret = 0;
-
-	blen = sizeof(*param) + key_len;
-	buf = os_zalloc(blen);
-	if (buf == NULL)
-		return -1;
-
-	param = (struct prism2_hostapd_param *) buf;
-	param->cmd = PRISM2_SET_ENCRYPTION;
-	if (addr == NULL)
-		memset(param->sta_addr, 0xff, ETH_ALEN);
-	else
-		memcpy(param->sta_addr, addr, ETH_ALEN);
-	os_strlcpy((char *) param->u.crypt.alg, alg,
-		   HOSTAP_CRYPT_ALG_NAME_LEN);
-	param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
-	param->u.crypt.idx = idx;
-	param->u.crypt.key_len = key_len;
-	memcpy((u8 *) (param + 1), key, key_len);
-
-	if (hostapd_ioctl(drv, param, blen)) {
-		printf("Failed to set encryption.\n");
-		ret = -1;
-	}
-	free(buf);
-
-	return ret;
-}
-
-
-static int hostap_get_seqnum(const char *ifname, void *priv, const u8 *addr,
-			     int idx, u8 *seq)
-{
-	struct hostap_driver_data *drv = priv;
-	struct prism2_hostapd_param *param;
-	u8 *buf;
-	size_t blen;
-	int ret = 0;
-
-	blen = sizeof(*param) + 32;
-	buf = os_zalloc(blen);
-	if (buf == NULL)
-		return -1;
-
-	param = (struct prism2_hostapd_param *) buf;
-	param->cmd = PRISM2_GET_ENCRYPTION;
-	if (addr == NULL)
-		memset(param->sta_addr, 0xff, ETH_ALEN);
-	else
-		memcpy(param->sta_addr, addr, ETH_ALEN);
-	param->u.crypt.idx = idx;
-
-	if (hostapd_ioctl(drv, param, blen)) {
-		printf("Failed to get encryption.\n");
-		ret = -1;
-	} else {
-		memcpy(seq, param->u.crypt.seq, 8);
-	}
-	free(buf);
-
-	return ret;
-}
-
-
-static int hostap_ioctl_prism2param(void *priv, int param, int value)
-{
-	struct hostap_driver_data *drv = priv;
-	struct iwreq iwr;
-	int *i;
-
-	memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
-	i = (int *) iwr.u.name;
-	*i++ = param;
-	*i++ = value;
-
-	if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) {
-		perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static int hostap_set_ieee8021x(const char *ifname, void *priv, int enabled)
-{
-	struct hostap_driver_data *drv = priv;
-
-	/* enable kernel driver support for IEEE 802.1X */
-	if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_IEEE_802_1X, enabled)) {
-		printf("Could not setup IEEE 802.1X support in kernel driver."
-		       "\n");
-		return -1;
-	}
-
-	if (!enabled)
-		return 0;
-
-	/* use host driver implementation of encryption to allow
-	 * individual keys and passing plaintext EAPOL frames */
-	if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_DECRYPT, 1) ||
-	    hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_ENCRYPT, 1)) {
-		printf("Could not setup host-based encryption in kernel "
-		       "driver.\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static int hostap_set_privacy(const char *ifname, void *priv, int enabled)
-{
-	struct hostap_drvier_data *drv = priv;
-
-	return hostap_ioctl_prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED,
-					enabled);
-}
-
- 
-static int hostap_set_ssid(const char *ifname, void *priv, const u8 *buf,
-			   int len)
-{
-	struct hostap_driver_data *drv = priv;
-	struct iwreq iwr;
-
-	memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
-	iwr.u.essid.flags = 1; /* SSID active */
-	iwr.u.essid.pointer = (caddr_t) buf;
-	iwr.u.essid.length = len + 1;
-
-	if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
-		perror("ioctl[SIOCSIWESSID]");
-		printf("len=%d\n", len);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static int hostap_flush(void *priv)
-{
-	struct hostap_driver_data *drv = priv;
-	struct prism2_hostapd_param param;
-
-	memset(¶m, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_FLUSH;
-	return hostapd_ioctl(drv, ¶m, sizeof(param));
-}
-
-
-static int hostap_read_sta_data(void *priv,
-				struct hostap_sta_driver_data *data,
-				const u8 *addr)
-{
-	struct hostap_driver_data *drv = priv;
-	char buf[1024], line[128], *pos;
-	FILE *f;
-	unsigned long val;
-
-	memset(data, 0, sizeof(*data));
-	snprintf(buf, sizeof(buf), "/proc/net/hostap/%s/" MACSTR,
-		 drv->iface, MAC2STR(addr));
-
-	f = fopen(buf, "r");
-	if (!f)
-		return -1;
-	/* Need to read proc file with in one piece, so use large enough
-	 * buffer. */
-	setbuffer(f, buf, sizeof(buf));
-
-	while (fgets(line, sizeof(line), f)) {
-		pos = strchr(line, '=');
-		if (!pos)
-			continue;
-		*pos++ = '\0';
-		val = strtoul(pos, NULL, 10);
-		if (strcmp(line, "rx_packets") == 0)
-			data->rx_packets = val;
-		else if (strcmp(line, "tx_packets") == 0)
-			data->tx_packets = val;
-		else if (strcmp(line, "rx_bytes") == 0)
-			data->rx_bytes = val;
-		else if (strcmp(line, "tx_bytes") == 0)
-			data->tx_bytes = val;
-	}
-
-	fclose(f);
-
-	return 0;
-}
-
-
-static int hostap_sta_add(const char *ifname, void *priv, const u8 *addr,
-			  u16 aid, u16 capability, u8 *supp_rates,
-			  size_t supp_rates_len, int flags,
-			  u16 listen_interval)
-{
-	struct hostap_driver_data *drv = priv;
-	struct prism2_hostapd_param param;
-	int tx_supp_rates = 0;
-	size_t i;
-
-#define WLAN_RATE_1M BIT(0)
-#define WLAN_RATE_2M BIT(1)
-#define WLAN_RATE_5M5 BIT(2)
-#define WLAN_RATE_11M BIT(3)
-
-	for (i = 0; i < supp_rates_len; i++) {
-		if ((supp_rates[i] & 0x7f) == 2)
-			tx_supp_rates |= WLAN_RATE_1M;
-		if ((supp_rates[i] & 0x7f) == 4)
-			tx_supp_rates |= WLAN_RATE_2M;
-		if ((supp_rates[i] & 0x7f) == 11)
-			tx_supp_rates |= WLAN_RATE_5M5;
-		if ((supp_rates[i] & 0x7f) == 22)
-			tx_supp_rates |= WLAN_RATE_11M;
-	}
-
-	memset(¶m, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_ADD_STA;
-	memcpy(param.sta_addr, addr, ETH_ALEN);
-	param.u.add_sta.aid = aid;
-	param.u.add_sta.capability = capability;
-	param.u.add_sta.tx_supp_rates = tx_supp_rates;
-	return hostapd_ioctl(drv, ¶m, sizeof(param));
-}
-
-
-static int hostap_sta_remove(void *priv, const u8 *addr)
-{
-	struct hostap_driver_data *drv = priv;
-	struct prism2_hostapd_param param;
-
-	hostap_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED);
-
-	memset(¶m, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
-	memcpy(param.sta_addr, addr, ETH_ALEN);
-	if (hostapd_ioctl(drv, ¶m, sizeof(param))) {
-		printf("Could not remove station from kernel driver.\n");
-		return -1;
-	}
-	return 0;
-}
-
-
-static int hostap_get_inact_sec(void *priv, const u8 *addr)
-{
-	struct hostap_driver_data *drv = priv;
-	struct prism2_hostapd_param param;
-
-	memset(¶m, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_GET_INFO_STA;
-	memcpy(param.sta_addr, addr, ETH_ALEN);
-	if (hostapd_ioctl(drv, ¶m, sizeof(param))) {
-		return -1;
-	}
-
-	return param.u.get_info_sta.inactive_sec;
-}
-
-
-static int hostap_sta_clear_stats(void *priv, const u8 *addr)
-{
-	struct hostap_driver_data *drv = priv;
-	struct prism2_hostapd_param param;
-
-	memset(¶m, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_STA_CLEAR_STATS;
-	memcpy(param.sta_addr, addr, ETH_ALEN);
-	if (hostapd_ioctl(drv, ¶m, sizeof(param))) {
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static int hostap_set_assoc_ap(void *priv, const u8 *addr)
-{
-	struct hostap_driver_data *drv = priv;
-	struct prism2_hostapd_param param;
-
-	memset(¶m, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR;
-	memcpy(param.sta_addr, addr, ETH_ALEN);
-	if (hostapd_ioctl(drv, ¶m, sizeof(param)))
-		return -1;
-
-	return 0;
-}
-
-
-static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv)
-{
-	struct prism2_hostapd_param *param;
-	int res;
-	size_t blen, elem_len;
-
-	elem_len = drv->generic_ie_len + drv->wps_ie_len;
-	blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len;
-	if (blen < sizeof(*param))
-		blen = sizeof(*param);
-
-	param = os_zalloc(blen);
-	if (param == NULL)
-		return -1;
-
-	param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
-	param->u.generic_elem.len = elem_len;
-	if (drv->generic_ie) {
-		os_memcpy(param->u.generic_elem.data, drv->generic_ie,
-			  drv->generic_ie_len);
-	}
-	if (drv->wps_ie) {
-		os_memcpy(¶m->u.generic_elem.data[drv->generic_ie_len],
-			  drv->wps_ie, drv->wps_ie_len);
-	}
-	wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE",
-		    param->u.generic_elem.data, elem_len);
-	res = hostapd_ioctl(drv, param, blen);
-
-	os_free(param);
-
-	return res;
-}
-
-
-static int hostap_set_generic_elem(const char *ifname, void *priv,
-				   const u8 *elem, size_t elem_len)
-{
-	struct hostap_driver_data *drv = priv;
-
-	os_free(drv->generic_ie);
-	drv->generic_ie = NULL;
-	drv->generic_ie_len = 0;
-	if (elem) {
-		drv->generic_ie = os_malloc(elem_len);
-		if (drv->generic_ie == NULL)
-			return -1;
-		os_memcpy(drv->generic_ie, elem, elem_len);
-		drv->generic_ie_len = elem_len;
-	}
-
-	return hostapd_ioctl_set_generic_elem(drv);
-}
-
-
-static int hostap_set_wps_beacon_ie(const char *ifname, void *priv,
-				    const u8 *ie, size_t len)
-{
-	/* Host AP driver supports only one set of extra IEs, so we need to
-	 * use the ProbeResp IEs also for Beacon frames since they include more
-	 * information. */
-	return 0;
-}
-
-
-static int hostap_set_wps_probe_resp_ie(const char *ifname, void *priv,
-					const u8 *ie, size_t len)
-{
-	struct hostap_driver_data *drv = priv;
-
-	os_free(drv->wps_ie);
-	drv->wps_ie = NULL;
-	drv->wps_ie_len = 0;
-	if (ie) {
-		drv->wps_ie = os_malloc(len);
-		if (drv->wps_ie == NULL)
-			return -1;
-		os_memcpy(drv->wps_ie, ie, len);
-		drv->wps_ie_len = len;
-	}
-
-	return hostapd_ioctl_set_generic_elem(drv);
-}
-
-
-static void
-hostapd_wireless_event_wireless_custom(struct hostap_driver_data *drv,
-				       char *custom)
-{
-	wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
-
-	if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
-		char *pos;
-		u8 addr[ETH_ALEN];
-		pos = strstr(custom, "addr=");
-		if (pos == NULL) {
-			wpa_printf(MSG_DEBUG,
-				   "MLME-MICHAELMICFAILURE.indication "
-				   "without sender address ignored");
-			return;
-		}
-		pos += 5;
-		if (hwaddr_aton(pos, addr) == 0) {
-			ieee80211_michael_mic_failure(drv->hapd, addr, 1);
-		} else {
-			wpa_printf(MSG_DEBUG,
-				   "MLME-MICHAELMICFAILURE.indication "
-				   "with invalid MAC address");
-		}
-	}
-}
-
-
-static void hostapd_wireless_event_wireless(struct hostap_driver_data *drv,
-					    char *data, int len)
-{
-	struct iw_event iwe_buf, *iwe = &iwe_buf;
-	char *pos, *end, *custom, *buf;
-
-	pos = data;
-	end = data + len;
-
-	while (pos + IW_EV_LCP_LEN <= end) {
-		/* Event data may be unaligned, so make a local, aligned copy
-		 * before processing. */
-		memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
-		wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
-			   iwe->cmd, iwe->len);
-		if (iwe->len <= IW_EV_LCP_LEN)
-			return;
-
-		custom = pos + IW_EV_POINT_LEN;
-		if (drv->we_version > 18 &&
-		    (iwe->cmd == IWEVMICHAELMICFAILURE ||
-		     iwe->cmd == IWEVCUSTOM)) {
-			/* WE-19 removed the pointer from struct iw_point */
-			char *dpos = (char *) &iwe_buf.u.data.length;
-			int dlen = dpos - (char *) &iwe_buf;
-			memcpy(dpos, pos + IW_EV_LCP_LEN,
-			       sizeof(struct iw_event) - dlen);
-		} else {
-			memcpy(&iwe_buf, pos, sizeof(struct iw_event));
-			custom += IW_EV_POINT_OFF;
-		}
-
-		switch (iwe->cmd) {
-		case IWEVCUSTOM:
-			if (custom + iwe->u.data.length > end)
-				return;
-			buf = malloc(iwe->u.data.length + 1);
-			if (buf == NULL)
-				return;
-			memcpy(buf, custom, iwe->u.data.length);
-			buf[iwe->u.data.length] = '\0';
-			hostapd_wireless_event_wireless_custom(drv, buf);
-			free(buf);
-			break;
-		}
-
-		pos += iwe->len;
-	}
-}
-
-
-static void hostapd_wireless_event_rtm_newlink(struct hostap_driver_data *drv,
-					       struct nlmsghdr *h, int len)
-{
-	struct ifinfomsg *ifi;
-	int attrlen, nlmsg_len, rta_len;
-	struct rtattr * attr;
-
-	if (len < (int) sizeof(*ifi))
-		return;
-
-	ifi = NLMSG_DATA(h);
-
-	/* TODO: use ifi->ifi_index to filter out wireless events from other
-	 * interfaces */
-
-	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
-	attrlen = h->nlmsg_len - nlmsg_len;
-	if (attrlen < 0)
-		return;
-
-	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
-
-	rta_len = RTA_ALIGN(sizeof(struct rtattr));
-	while (RTA_OK(attr, attrlen)) {
-		if (attr->rta_type == IFLA_WIRELESS) {
-			hostapd_wireless_event_wireless(
-				drv, ((char *) attr) + rta_len,
-				attr->rta_len - rta_len);
-		}
-		attr = RTA_NEXT(attr, attrlen);
-	}
-}
-
-
-static void hostapd_wireless_event_receive(int sock, void *eloop_ctx,
-					   void *sock_ctx)
-{
-	char buf[256];
-	int left;
-	struct sockaddr_nl from;
-	socklen_t fromlen;
-	struct nlmsghdr *h;
-	struct hostap_driver_data *drv = eloop_ctx;
-
-	fromlen = sizeof(from);
-	left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
-			(struct sockaddr *) &from, &fromlen);
-	if (left < 0) {
-		if (errno != EINTR && errno != EAGAIN)
-			perror("recvfrom(netlink)");
-		return;
-	}
-
-	h = (struct nlmsghdr *) buf;
-	while (left >= (int) sizeof(*h)) {
-		int len, plen;
-
-		len = h->nlmsg_len;
-		plen = len - sizeof(*h);
-		if (len > left || plen < 0) {
-			printf("Malformed netlink message: "
-			       "len=%d left=%d plen=%d\n",
-			       len, left, plen);
-			break;
-		}
-
-		switch (h->nlmsg_type) {
-		case RTM_NEWLINK:
-			hostapd_wireless_event_rtm_newlink(drv, h, plen);
-			break;
-		}
-
-		len = NLMSG_ALIGN(len);
-		left -= len;
-		h = (struct nlmsghdr *) ((char *) h + len);
-	}
-
-	if (left > 0) {
-		printf("%d extra bytes in the end of netlink message\n", left);
-	}
-}
-
-
-static int hostap_get_we_version(struct hostap_driver_data *drv)
-{
-	struct iw_range *range;
-	struct iwreq iwr;
-	int minlen;
-	size_t buflen;
-
-	drv->we_version = 0;
-
-	/*
-	 * Use larger buffer than struct iw_range in order to allow the
-	 * structure to grow in the future.
-	 */
-	buflen = sizeof(struct iw_range) + 500;
-	range = os_zalloc(buflen);
-	if (range == NULL)
-		return -1;
-
-	memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
-	iwr.u.data.pointer = (caddr_t) range;
-	iwr.u.data.length = buflen;
-
-	minlen = ((char *) &range->enc_capa) - (char *) range +
-		sizeof(range->enc_capa);
-
-	if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
-		perror("ioctl[SIOCGIWRANGE]");
-		free(range);
-		return -1;
-	} else if (iwr.u.data.length >= minlen &&
-		   range->we_version_compiled >= 18) {
-		wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
-			   "WE(source)=%d enc_capa=0x%x",
-			   range->we_version_compiled,
-			   range->we_version_source,
-			   range->enc_capa);
-		drv->we_version = range->we_version_compiled;
-	}
-
-	free(range);
-	return 0;
-}
-
-
-static int hostap_wireless_event_init(void *priv)
-{
-	struct hostap_driver_data *drv = priv;
-	int s;
-	struct sockaddr_nl local;
-
-	hostap_get_we_version(drv);
-
-	drv->wext_sock = -1;
-
-	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-	if (s < 0) {
-		perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
-		return -1;
-	}
-
-	memset(&local, 0, sizeof(local));
-	local.nl_family = AF_NETLINK;
-	local.nl_groups = RTMGRP_LINK;
-	if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
-		perror("bind(netlink)");
-		close(s);
-		return -1;
-	}
-
-	eloop_register_read_sock(s, hostapd_wireless_event_receive, drv,
-				 NULL);
-	drv->wext_sock = s;
-
-	return 0;
-}
-
-
-static void hostap_wireless_event_deinit(void *priv)
-{
-	struct hostap_driver_data *drv = priv;
-	if (drv->wext_sock < 0)
-		return;
-	eloop_unregister_read_sock(drv->wext_sock);
-	close(drv->wext_sock);
-}
-
-
-static void * hostap_init(struct hostapd_data *hapd)
-{
-	struct hostap_driver_data *drv;
-
-	drv = os_zalloc(sizeof(struct hostap_driver_data));
-	if (drv == NULL) {
-		printf("Could not allocate memory for hostapd driver data\n");
-		return NULL;
-	}
-
-	drv->hapd = hapd;
-	drv->ioctl_sock = drv->sock = -1;
-	memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
-
-	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
-	if (drv->ioctl_sock < 0) {
-		perror("socket[PF_INET,SOCK_DGRAM]");
-		free(drv);
-		return NULL;
-	}
-
-	if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 1)) {
-		printf("Could not enable hostapd mode for interface %s\n",
-		       drv->iface);
-		close(drv->ioctl_sock);
-		free(drv);
-		return NULL;
-	}
-
-	if (hostap_init_sockets(drv)) {
-		close(drv->ioctl_sock);
-		free(drv);
-		return NULL;
-	}
-
-	return drv;
-}
-
-
-static void hostap_driver_deinit(void *priv)
-{
-	struct hostap_driver_data *drv = priv;
-
-	(void) hostap_set_iface_flags(drv, 0);
-	(void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0);
-	(void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0);
-
-	if (drv->ioctl_sock >= 0)
-		close(drv->ioctl_sock);
-
-	if (drv->sock >= 0)
-		close(drv->sock);
-
-	os_free(drv->generic_ie);
-	os_free(drv->wps_ie);
-
-	free(drv);
-}
-
-
-static int hostap_sta_deauth(void *priv, const u8 *addr, int reason)
-{
-	struct hostap_driver_data *drv = priv;
-	struct ieee80211_mgmt mgmt;
-
-	memset(&mgmt, 0, sizeof(mgmt));
-	mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
-					  WLAN_FC_STYPE_DEAUTH);
-	memcpy(mgmt.da, addr, ETH_ALEN);
-	memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
-	memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
-	mgmt.u.deauth.reason_code = host_to_le16(reason);
-	return hostap_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN +
-				      sizeof(mgmt.u.deauth), 0);
-}
-
-
-static int hostap_sta_disassoc(void *priv, const u8 *addr, int reason)
-{
-	struct hostap_driver_data *drv = priv;
-	struct ieee80211_mgmt mgmt;
-
-	memset(&mgmt, 0, sizeof(mgmt));
-	mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
-					  WLAN_FC_STYPE_DISASSOC);
-	memcpy(mgmt.da, addr, ETH_ALEN);
-	memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
-	memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
-	mgmt.u.disassoc.reason_code = host_to_le16(reason);
-	return  hostap_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN +
-				       sizeof(mgmt.u.disassoc), 0);
-}
-
-
-static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv,
-							    u16 *num_modes,
-							    u16 *flags)
-{
-	struct hostapd_hw_modes *mode;
-	int i, clen, rlen;
-	const short chan2freq[14] = {
-		2412, 2417, 2422, 2427, 2432, 2437, 2442,
-		2447, 2452, 2457, 2462, 2467, 2472, 2484
-	};
-
-	mode = os_zalloc(sizeof(struct hostapd_hw_modes));
-	if (mode == NULL)
-		return NULL;
-
-	*num_modes = 1;
-	*flags = 0;
-
-	mode->mode = HOSTAPD_MODE_IEEE80211B;
-	mode->num_channels = 14;
-	mode->num_rates = 4;
-
-	clen = mode->num_channels * sizeof(struct hostapd_channel_data);
-	rlen = mode->num_rates * sizeof(struct hostapd_rate_data);
-
-	mode->channels = os_zalloc(clen);
-	mode->rates = os_zalloc(rlen);
-	if (mode->channels == NULL || mode->rates == NULL) {
-		hostapd_free_hw_features(mode, *num_modes);
-		return NULL;
-	}
-
-	for (i = 0; i < 14; i++) {
-		mode->channels[i].chan = i + 1;
-		mode->channels[i].freq = chan2freq[i];
-		/* TODO: Get allowed channel list from the driver */
-		if (i >= 11)
-			mode->channels[i].flag = HOSTAPD_CHAN_DISABLED;
-	}
-
-	mode->rates[0].rate = 10;
-	mode->rates[0].flags = HOSTAPD_RATE_CCK;
-	mode->rates[1].rate = 20;
-	mode->rates[1].flags = HOSTAPD_RATE_CCK;
-	mode->rates[2].rate = 55;
-	mode->rates[2].flags = HOSTAPD_RATE_CCK;
-	mode->rates[3].rate = 110;
-	mode->rates[3].flags = HOSTAPD_RATE_CCK;
-
-	return mode;
-}
-
-
-const struct wpa_driver_ops wpa_driver_hostap_ops = {
-	.name = "hostap",
-	.init = hostap_init,
-	.deinit = hostap_driver_deinit,
-	.wireless_event_init = hostap_wireless_event_init,
-	.wireless_event_deinit = hostap_wireless_event_deinit,
-	.set_ieee8021x = hostap_set_ieee8021x,
-	.set_privacy = hostap_set_privacy,
-	.set_encryption = hostap_set_encryption,
-	.get_seqnum = hostap_get_seqnum,
-	.flush = hostap_flush,
-	.set_generic_elem = hostap_set_generic_elem,
-	.read_sta_data = hostap_read_sta_data,
-	.send_eapol = hostap_send_eapol,
-	.sta_set_flags = hostap_sta_set_flags,
-	.sta_deauth = hostap_sta_deauth,
-	.sta_disassoc = hostap_sta_disassoc,
-	.sta_remove = hostap_sta_remove,
-	.set_ssid = hostap_set_ssid,
-	.send_mgmt_frame = hostap_send_mgmt_frame,
-	.set_assoc_ap = hostap_set_assoc_ap,
-	.sta_add = hostap_sta_add,
-	.get_inact_sec = hostap_get_inact_sec,
-	.sta_clear_stats = hostap_sta_clear_stats,
-	.get_hw_feature_data = hostap_get_hw_feature_data,
-	.set_wps_beacon_ie = hostap_set_wps_beacon_ie,
-	.set_wps_probe_resp_ie = hostap_set_wps_probe_resp_ie,
-};
diff --git a/contrib/wpa/hostapd/driver_wired.c b/contrib/wpa/hostapd/driver_wired.c
deleted file mode 100644
index 61cb667cca7f..000000000000
--- a/contrib/wpa/hostapd/driver_wired.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * hostapd / Kernel driver communication for wired (Ethernet) drivers
- * Copyright (c) 2002-2007, Jouni Malinen 
- * Copyright (c) 2004, Gunter Burchardt 
- *
- * 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 
-
-#ifdef USE_KERNEL_HEADERS
-#include 
-#include 
-#include    /* The L2 protocols */
-#include 
-#include 
-#else /* USE_KERNEL_HEADERS */
-#include 
-#include 
-#include 
-#endif /* USE_KERNEL_HEADERS */
-
-#include "hostapd.h"
-#include "ieee802_1x.h"
-#include "eloop.h"
-#include "sta_info.h"
-#include "driver.h"
-#include "accounting.h"
-
-
-struct wired_driver_data {
-	struct hostapd_data *hapd;
-
-	int sock; /* raw packet socket for driver access */
-	int dhcp_sock; /* socket for dhcp packets */
-	int use_pae_group_addr;
-};
-
-
-#define WIRED_EAPOL_MULTICAST_GROUP	{0x01,0x80,0xc2,0x00,0x00,0x03}
-
-
-/* TODO: detecting new devices should eventually be changed from using DHCP
- * snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
- * based on ebtables, etc. */
-
-struct dhcp_message {
-	u_int8_t op;
-	u_int8_t htype;
-	u_int8_t hlen;
-	u_int8_t hops;
-	u_int32_t xid;
-	u_int16_t secs;
-	u_int16_t flags;
-	u_int32_t ciaddr;
-	u_int32_t yiaddr;
-	u_int32_t siaddr;
-	u_int32_t giaddr;
-	u_int8_t chaddr[16];
-	u_int8_t sname[64];
-	u_int8_t file[128];
-	u_int32_t cookie;
-	u_int8_t options[308]; /* 312 - cookie */
-};
-
-
-static void wired_possible_new_sta(struct hostapd_data *hapd, u8 *addr)
-{
-	struct sta_info *sta;
-
-	sta = ap_get_sta(hapd, addr);
-	if (sta)
-		return;
-
-	wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
-		   " - adding a new STA", MAC2STR(addr));
-	sta = ap_sta_add(hapd, addr);
-	if (sta) {
-		hostapd_new_assoc_sta(hapd, sta, 0);
-	} else {
-		wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
-			   MAC2STR(addr));
-	}
-}
-
-
-static void handle_data(struct hostapd_data *hapd, unsigned char *buf,
-			size_t len)
-{
-	struct ieee8023_hdr *hdr;
-	u8 *pos, *sa;
-	size_t left;
-
-	/* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
-	 * 2 byte ethertype */
-	if (len < 14) {
-		wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)",
-			   (unsigned long) len);
-		return;
-	}
-
-	hdr = (struct ieee8023_hdr *) buf;
-
-	switch (ntohs(hdr->ethertype)) {
-		case ETH_P_PAE:
-			wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
-			sa = hdr->src;
-			wired_possible_new_sta(hapd, sa);
-
-			pos = (u8 *) (hdr + 1);
-			left = len - sizeof(*hdr);
-
-			ieee802_1x_receive(hapd, sa, pos, left);
-		break;
-
-	default:
-		wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
-			   ntohs(hdr->ethertype));
-		break;
-	}
-}
-
-
-static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
-{
-	struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
-	int len;
-	unsigned char buf[3000];
-
-	len = recv(sock, buf, sizeof(buf), 0);
-	if (len < 0) {
-		perror("recv");
-		return;
-	}
-	
-	handle_data(hapd, buf, len);
-}
-
-
-static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx)
-{
-	struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx;
-	int len;
-	unsigned char buf[3000];
-	struct dhcp_message *msg;
-	u8 *mac_address;
-
-	len = recv(sock, buf, sizeof(buf), 0);
-	if (len < 0) {
-		perror("recv"); 
-		return;
-	}
-
-	/* must contain at least dhcp_message->chaddr */
-	if (len < 44) {
-		wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len);
-		return;
-	}
-	
-	msg = (struct dhcp_message *) buf;
-	mac_address = (u8 *) &(msg->chaddr);
-	
-	wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR,
-		   MAC2STR(mac_address));
-
-	wired_possible_new_sta(hapd, mac_address);
-}
-
-
-static int wired_init_sockets(struct wired_driver_data *drv)
-{
-	struct hostapd_data *hapd = drv->hapd;
-	struct ifreq ifr;
-	struct sockaddr_ll addr;
-	struct sockaddr_in addr2;
-	struct packet_mreq mreq;
-	u8 multicastgroup_eapol[6] = WIRED_EAPOL_MULTICAST_GROUP;
-	int n = 1;
-
-	drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
-	if (drv->sock < 0) {
-		perror("socket[PF_PACKET,SOCK_RAW]");
-		return -1;
-	}
-
-	if (eloop_register_read_sock(drv->sock, handle_read, hapd, NULL)) {
-		printf("Could not register read socket\n");
-		return -1;
-	}
-
-	memset(&ifr, 0, sizeof(ifr));
-	os_strlcpy(ifr.ifr_name, hapd->conf->iface, sizeof(ifr.ifr_name));
-	if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
-		perror("ioctl(SIOCGIFINDEX)");
-		return -1;
-	}
-
-	
-	memset(&addr, 0, sizeof(addr));
-	addr.sll_family = AF_PACKET;
-	addr.sll_ifindex = ifr.ifr_ifindex;
-	wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
-		   addr.sll_ifindex);
-
-	if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-		perror("bind");
-		return -1;
-	}
-
-	/* filter multicast address */
-	memset(&mreq, 0, sizeof(mreq));
-	mreq.mr_ifindex = ifr.ifr_ifindex;
-	mreq.mr_type = PACKET_MR_MULTICAST;
-	mreq.mr_alen = 6;
-	memcpy(mreq.mr_address, multicastgroup_eapol, mreq.mr_alen);
-
-	if (setsockopt(drv->sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq,
-		       sizeof(mreq)) < 0) {
-		perror("setsockopt[SOL_SOCKET,PACKET_ADD_MEMBERSHIP]");
-		return -1;
-	}
-
-	memset(&ifr, 0, sizeof(ifr));
-	os_strlcpy(ifr.ifr_name, hapd->conf->iface, sizeof(ifr.ifr_name));
-	if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
-		perror("ioctl(SIOCGIFHWADDR)");
-		return -1;
-	}
-
-	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
-		printf("Invalid HW-addr family 0x%04x\n",
-		       ifr.ifr_hwaddr.sa_family);
-		return -1;
-	}
-	memcpy(hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
-
-	/* setup dhcp listen socket for sta detection */
-	if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
-		perror("socket call failed for dhcp");
-		return -1;
-	}
-
-	if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, hapd, NULL))
-	{
-		printf("Could not register read socket\n");
-		return -1;
-	}
-	
-	memset(&addr2, 0, sizeof(addr2));
-	addr2.sin_family = AF_INET;
-	addr2.sin_port = htons(67);
-	addr2.sin_addr.s_addr = INADDR_ANY;
-
-	if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n,
-		       sizeof(n)) == -1) {
-		perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]");
-		return -1;
-	}
-	if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n,
-		       sizeof(n)) == -1) {
-		perror("setsockopt[SOL_SOCKET,SO_BROADCAST]");
-		return -1;
-	}
-
-	memset(&ifr, 0, sizeof(ifr));
-	os_strlcpy(ifr.ifr_ifrn.ifrn_name, hapd->conf->iface, IFNAMSIZ);
-	if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE,
-		       (char *) &ifr, sizeof(ifr)) < 0) {
-		perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]");
-		return -1;
-	}
-
-	if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2,
-		 sizeof(struct sockaddr)) == -1) {
-		perror("bind");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static int wired_send_eapol(void *priv, const u8 *addr,
-			    const u8 *data, size_t data_len, int encrypt,
-			    const u8 *own_addr)
-{
-	struct wired_driver_data *drv = priv;
-	u8 pae_group_addr[ETH_ALEN] = WIRED_EAPOL_MULTICAST_GROUP;
-	struct ieee8023_hdr *hdr;
-	size_t len;
-	u8 *pos;
-	int res;
-
-	len = sizeof(*hdr) + data_len;
-	hdr = os_zalloc(len);
-	if (hdr == NULL) {
-		printf("malloc() failed for wired_send_eapol(len=%lu)\n",
-		       (unsigned long) len);
-		return -1;
-	}
-
-	memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
-	       ETH_ALEN);
-	memcpy(hdr->src, own_addr, ETH_ALEN);
-	hdr->ethertype = htons(ETH_P_PAE);
-
-	pos = (u8 *) (hdr + 1);
-	memcpy(pos, data, data_len);
-
-	res = send(drv->sock, (u8 *) hdr, len, 0);
-	free(hdr);
-
-	if (res < 0) {
-		perror("wired_send_eapol: send");
-		printf("wired_send_eapol - packet len: %lu - failed\n",
-		       (unsigned long) len);
-	}
-
-	return res;
-}
-
-
-static void * wired_driver_init(struct hostapd_data *hapd)
-{
-	struct wired_driver_data *drv;
-
-	drv = os_zalloc(sizeof(struct wired_driver_data));
-	if (drv == NULL) {
-		printf("Could not allocate memory for wired driver data\n");
-		return NULL;
-	}
-
-	drv->hapd = hapd;
-	drv->use_pae_group_addr = hapd->conf->use_pae_group_addr;
-
-	if (wired_init_sockets(drv)) {
-		free(drv);
-		return NULL;
-	}
-
-	return drv;
-}
-
-
-static void wired_driver_deinit(void *priv)
-{
-	struct wired_driver_data *drv = priv;
-
-	if (drv->sock >= 0)
-		close(drv->sock);
-	
-	if (drv->dhcp_sock >= 0)
-		close(drv->dhcp_sock);
-
-	free(drv);
-}
-
-
-const struct wpa_driver_ops wpa_driver_wired_ops = {
-	.name = "wired",
-	.init = wired_driver_init,
-	.deinit = wired_driver_deinit,
-	.send_eapol = wired_send_eapol,
-};
diff --git a/contrib/wpa/hostapd/drivers.c b/contrib/wpa/hostapd/drivers.c
deleted file mode 100644
index bde6e609f3d4..000000000000
--- a/contrib/wpa/hostapd/drivers.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * hostapd / driver interface list
- * Copyright (c) 2007, Jouni Malinen 
- *
- * 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"
-
-
-#ifdef CONFIG_DRIVER_HOSTAP
-extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
-#endif /* CONFIG_DRIVER_HOSTAP */
-#ifdef CONFIG_DRIVER_NL80211
-extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */
-#endif /* CONFIG_DRIVER_NL80211 */
-#ifdef CONFIG_DRIVER_PRISM54
-extern struct wpa_driver_ops wpa_driver_prism54_ops; /* driver_prism54.c */
-#endif /* CONFIG_DRIVER_PRISM54 */
-#ifdef CONFIG_DRIVER_MADWIFI
-extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */
-#endif /* CONFIG_DRIVER_MADWIFI */
-#ifdef CONFIG_DRIVER_ATHEROS
-extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */
-#endif /* CONFIG_DRIVER_ATHEROS */
-#ifdef CONFIG_DRIVER_BSD
-extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
-#endif /* CONFIG_DRIVER_BSD */
-#ifdef CONFIG_DRIVER_WIRED
-extern struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */
-#endif /* CONFIG_DRIVER_WIRED */
-#ifdef CONFIG_DRIVER_TEST
-extern struct wpa_driver_ops wpa_driver_test_ops; /* driver_test.c */
-#endif /* CONFIG_DRIVER_TEST */
-#ifdef CONFIG_DRIVER_NONE
-extern struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */
-#endif /* CONFIG_DRIVER_NONE */
-
-
-struct wpa_driver_ops *hostapd_drivers[] =
-{
-#ifdef CONFIG_DRIVER_HOSTAP
-	&wpa_driver_hostap_ops,
-#endif /* CONFIG_DRIVER_HOSTAP */
-#ifdef CONFIG_DRIVER_NL80211
-	&wpa_driver_nl80211_ops,
-#endif /* CONFIG_DRIVER_NL80211 */
-#ifdef CONFIG_DRIVER_PRISM54
-	&wpa_driver_prism54_ops,
-#endif /* CONFIG_DRIVER_PRISM54 */
-#ifdef CONFIG_DRIVER_MADWIFI
-	&wpa_driver_madwifi_ops,
-#endif /* CONFIG_DRIVER_MADWIFI */
-#ifdef CONFIG_DRIVER_ATHEROS
-	&wpa_driver_atheros_ops,
-#endif /* CONFIG_DRIVER_ATHEROS */
-#ifdef CONFIG_DRIVER_BSD
-	&wpa_driver_bsd_ops,
-#endif /* CONFIG_DRIVER_BSD */
-#ifdef CONFIG_DRIVER_WIRED
-	&wpa_driver_wired_ops,
-#endif /* CONFIG_DRIVER_WIRED */
-#ifdef CONFIG_DRIVER_TEST
-	&wpa_driver_test_ops,
-#endif /* CONFIG_DRIVER_TEST */
-#ifdef CONFIG_DRIVER_NONE
-	&wpa_driver_none_ops,
-#endif /* CONFIG_DRIVER_NONE */
-	NULL
-};
diff --git a/contrib/wpa/hostapd/dump_state.c b/contrib/wpa/hostapd/dump_state.c
new file mode 100644
index 000000000000..bba3068ccd81
--- /dev/null
+++ b/contrib/wpa/hostapd/dump_state.c
@@ -0,0 +1,184 @@
+/*
+ * hostapd / State dump
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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/contrib/wpa/hostapd/dump_state.h b/contrib/wpa/hostapd/dump_state.h
new file mode 100644
index 000000000000..e14f08a4f5e1
--- /dev/null
+++ b/contrib/wpa/hostapd/dump_state.h
@@ -0,0 +1,20 @@
+/*
+ * hostapd / State dump
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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/contrib/wpa/hostapd/eap_register.c b/contrib/wpa/hostapd/eap_register.c
new file mode 100644
index 000000000000..ae9bf9d38de9
--- /dev/null
+++ b/contrib/wpa/hostapd/eap_register.c
@@ -0,0 +1,134 @@
+/*
+ * EAP method registration
+ * Copyright (c) 2004-2009, Jouni Malinen 
+ *
+ * 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/contrib/wpa/src/crypto/rc4.h b/contrib/wpa/hostapd/eap_register.h
similarity index 61%
rename from contrib/wpa/src/crypto/rc4.h
rename to contrib/wpa/hostapd/eap_register.h
index 35c7e41fba06..82e7171d6fde 100644
--- a/contrib/wpa/src/crypto/rc4.h
+++ b/contrib/wpa/hostapd/eap_register.h
@@ -1,6 +1,6 @@
 /*
- * RC4 stream cipher
- * Copyright (c) 2002-2005, Jouni Malinen 
+ * EAP method registration
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -12,10 +12,9 @@
  * See README and COPYING for more details.
  */
 
-#ifndef RC4_H
-#define RC4_H
+#ifndef EAP_REGISTER_H
+#define EAP_REGISTER_H
 
-void rc4_skip(const u8 *key, size_t keylen, size_t skip,
-	      u8 *data, size_t data_len);
+int eap_server_register_methods(void);
 
-#endif /* RC4_H */
+#endif /* EAP_REGISTER_H */
diff --git a/contrib/wpa/src/hlr_auc_gw/hlr_auc_gw.c b/contrib/wpa/hostapd/hlr_auc_gw.c
similarity index 99%
rename from contrib/wpa/src/hlr_auc_gw/hlr_auc_gw.c
rename to contrib/wpa/hostapd/hlr_auc_gw.c
index e318903543ad..36934aa9728a 100644
--- a/contrib/wpa/src/hlr_auc_gw/hlr_auc_gw.c
+++ b/contrib/wpa/hostapd/hlr_auc_gw.c
@@ -47,7 +47,7 @@
 #include 
 
 #include "common.h"
-#include "milenage.h"
+#include "crypto/milenage.h"
 
 static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
 static const char *socket_path;
diff --git a/contrib/wpa/src/hlr_auc_gw/hlr_auc_gw.milenage_db b/contrib/wpa/hostapd/hlr_auc_gw.milenage_db
similarity index 100%
rename from contrib/wpa/src/hlr_auc_gw/hlr_auc_gw.milenage_db
rename to contrib/wpa/hostapd/hlr_auc_gw.milenage_db
diff --git a/contrib/wpa/hostapd/hostap_common.h b/contrib/wpa/hostapd/hostap_common.h
deleted file mode 100644
index 5a57dca46d3e..000000000000
--- a/contrib/wpa/hostapd/hostap_common.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * hostapd / Kernel driver communication with Linux Host AP driver
- * Copyright (c) 2002-2006, Jouni Malinen 
- *
- * 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 HOSTAP_COMMON_H
-#define HOSTAP_COMMON_H
-
-/* netdevice private ioctls (used, e.g., with iwpriv from user space) */
-
-/* New wireless extensions API - SET/GET convention (even ioctl numbers are
- * root only)
- */
-#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
-#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
-#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2)
-#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3)
-#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4)
-#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6)
-#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8)
-#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10)
-#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12)
-#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14)
-#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16)
-#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18)
-#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20)
-#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22)
-
-/* following are not in SIOCGIWPRIV list; check permission in the driver code
- */
-#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13)
-#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14)
-
-
-/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */
-enum {
-	/* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */
-	PRISM2_PARAM_TXRATECTRL = 2,
-	PRISM2_PARAM_BEACON_INT = 3,
-	PRISM2_PARAM_PSEUDO_IBSS = 4,
-	PRISM2_PARAM_ALC = 5,
-	/* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */
-	PRISM2_PARAM_DUMP = 7,
-	PRISM2_PARAM_OTHER_AP_POLICY = 8,
-	PRISM2_PARAM_AP_MAX_INACTIVITY = 9,
-	PRISM2_PARAM_AP_BRIDGE_PACKETS = 10,
-	PRISM2_PARAM_DTIM_PERIOD = 11,
-	PRISM2_PARAM_AP_NULLFUNC_ACK = 12,
-	PRISM2_PARAM_MAX_WDS = 13,
-	PRISM2_PARAM_AP_AUTOM_AP_WDS = 14,
-	PRISM2_PARAM_AP_AUTH_ALGS = 15,
-	PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16,
-	PRISM2_PARAM_HOST_ENCRYPT = 17,
-	PRISM2_PARAM_HOST_DECRYPT = 18,
-	PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19,
-	PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20,
-	PRISM2_PARAM_HOST_ROAMING = 21,
-	PRISM2_PARAM_BCRX_STA_KEY = 22,
-	PRISM2_PARAM_IEEE_802_1X = 23,
-	PRISM2_PARAM_ANTSEL_TX = 24,
-	PRISM2_PARAM_ANTSEL_RX = 25,
-	PRISM2_PARAM_MONITOR_TYPE = 26,
-	PRISM2_PARAM_WDS_TYPE = 27,
-	PRISM2_PARAM_HOSTSCAN = 28,
-	PRISM2_PARAM_AP_SCAN = 29,
-	PRISM2_PARAM_ENH_SEC = 30,
-	PRISM2_PARAM_IO_DEBUG = 31,
-	PRISM2_PARAM_BASIC_RATES = 32,
-	PRISM2_PARAM_OPER_RATES = 33,
-	PRISM2_PARAM_HOSTAPD = 34,
-	PRISM2_PARAM_HOSTAPD_STA = 35,
-	PRISM2_PARAM_WPA = 36,
-	PRISM2_PARAM_PRIVACY_INVOKED = 37,
-	PRISM2_PARAM_TKIP_COUNTERMEASURES = 38,
-	PRISM2_PARAM_DROP_UNENCRYPTED = 39,
-	PRISM2_PARAM_SCAN_CHANNEL_MASK = 40,
-};
-
-enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1,
-       HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 };
-
-
-/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */
-enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1,
-       AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3,
-       AP_MAC_CMD_KICKALL = 4 };
-
-
-/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */
-enum {
-	PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */,
-	/* Note! Old versions of prism2_srec have a fatal error in CRC-16
-	 * calculation, which will corrupt all non-volatile downloads.
-	 * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to
-	 * prevent use of old versions of prism2_srec for non-volatile
-	 * download. */
-	PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */,
-	PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */,
-	/* Persistent versions of volatile download commands (keep firmware
-	 * data in memory and automatically re-download after hw_reset */
-	PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5,
-	PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6,
-};
-
-struct prism2_download_param {
-	u32 dl_cmd;
-	u32 start_addr;
-	u32 num_areas;
-	struct prism2_download_area {
-		u32 addr; /* wlan card address */
-		u32 len;
-		caddr_t ptr; /* pointer to data in user space */
-	} data[0];
-};
-
-#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072
-#define PRISM2_MAX_DOWNLOAD_LEN 262144
-
-
-/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */
-enum {
-	PRISM2_HOSTAPD_FLUSH = 1,
-	PRISM2_HOSTAPD_ADD_STA = 2,
-	PRISM2_HOSTAPD_REMOVE_STA = 3,
-	PRISM2_HOSTAPD_GET_INFO_STA = 4,
-	/* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
-	PRISM2_SET_ENCRYPTION = 6,
-	PRISM2_GET_ENCRYPTION = 7,
-	PRISM2_HOSTAPD_SET_FLAGS_STA = 8,
-	PRISM2_HOSTAPD_GET_RID = 9,
-	PRISM2_HOSTAPD_SET_RID = 10,
-	PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
-	PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12,
-	PRISM2_HOSTAPD_MLME = 13,
-	PRISM2_HOSTAPD_SCAN_REQ = 14,
-	PRISM2_HOSTAPD_STA_CLEAR_STATS = 15,
-};
-
-#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
-#define PRISM2_HOSTAPD_RID_HDR_LEN \
-((size_t) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
-#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
-((size_t) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
-
-/* Maximum length for algorithm names (-1 for nul termination) used in ioctl()
- */
-#define HOSTAP_CRYPT_ALG_NAME_LEN 16
-
-
-struct prism2_hostapd_param {
-	u32 cmd;
-	u8 sta_addr[ETH_ALEN];
-	union {
-		struct {
-			u16 aid;
-			u16 capability;
-			u8 tx_supp_rates;
-		} add_sta;
-		struct {
-			u32 inactive_sec;
-		} get_info_sta;
-		struct {
-			u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];
-			u32 flags;
-			u32 err;
-			u8 idx;
-			u8 seq[8]; /* sequence counter (set: RX, get: TX) */
-			u16 key_len;
-			u8 key[0];
-		} crypt;
-		struct {
-			u32 flags_and;
-			u32 flags_or;
-		} set_flags_sta;
-		struct {
-			u16 rid;
-			u16 len;
-			u8 data[0];
-		} rid;
-		struct {
-			u8 len;
-			u8 data[0];
-		} generic_elem;
-		struct {
-#define MLME_STA_DEAUTH 0
-#define MLME_STA_DISASSOC 1
-			u16 cmd;
-			u16 reason_code;
-		} mlme;
-		struct {
-			u8 ssid_len;
-			u8 ssid[32];
-		} scan_req;
-	} u;
-};
-
-#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0)
-#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1)
-
-#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2
-#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3
-#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4
-#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5
-#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6
-#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7
-
-#endif /* HOSTAP_COMMON_H */
diff --git a/contrib/wpa/hostapd/hostapd.8 b/contrib/wpa/hostapd/hostapd.8
index a67a1bcca6c7..b4456bbcf3e6 100644
--- a/contrib/wpa/hostapd/hostapd.8
+++ b/contrib/wpa/hostapd/hostapd.8
@@ -12,7 +12,7 @@ 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.
-The current version supports Linux (Host AP, madwifi, Prism54 drivers) and FreeBSD (net80211).
+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.
diff --git a/contrib/wpa/hostapd/hostapd.c b/contrib/wpa/hostapd/hostapd.c
deleted file mode 100644
index b1c5a2c31598..000000000000
--- a/contrib/wpa/hostapd/hostapd.c
+++ /dev/null
@@ -1,2043 +0,0 @@
-/*
- * hostapd / Initialization and configuration
- * Copyright (c) 2002-2009, Jouni Malinen 
- *
- * 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"
-#ifndef CONFIG_NATIVE_WINDOWS
-#include 
-#endif /* CONFIG_NATIVE_WINDOWS */
-
-#include "eloop.h"
-#include "hostapd.h"
-#include "ieee802_1x.h"
-#include "ieee802_11.h"
-#include "beacon.h"
-#include "hw_features.h"
-#include "accounting.h"
-#include "eapol_sm.h"
-#include "iapp.h"
-#include "ap.h"
-#include "ieee802_11_auth.h"
-#include "ap_list.h"
-#include "sta_info.h"
-#include "driver.h"
-#include "radius/radius_client.h"
-#include "radius/radius_server.h"
-#include "wpa.h"
-#include "preauth.h"
-#include "wme.h"
-#include "vlan_init.h"
-#include "ctrl_iface.h"
-#include "tls.h"
-#include "eap_server/eap_sim_db.h"
-#include "eap_server/eap.h"
-#include "eap_server/tncs.h"
-#include "version.h"
-#include "l2_packet/l2_packet.h"
-#include "wps_hostapd.h"
-
-
-static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
-				       size_t identity_len, int phase2,
-				       struct eap_user *user);
-static int hostapd_flush_old_stations(struct hostapd_data *hapd);
-static int hostapd_setup_wpa(struct hostapd_data *hapd);
-static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
-
-struct hapd_interfaces {
-	size_t count;
-	struct hostapd_iface **iface;
-};
-
-unsigned char rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-
-
-extern int wpa_debug_level;
-extern int wpa_debug_show_keys;
-extern int wpa_debug_timestamp;
-
-
-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);
-}
-
-
-static void hostapd_deauth_all_stas(struct hostapd_data *hapd)
-{
-	u8 addr[ETH_ALEN];
-
-	/* New Prism2.5/3 STA firmware versions seem to have issues with this
-	 * broadcast deauth frame. This gets the firmware in odd state where
-	 * nothing works correctly, so let's skip sending this for the hostap
-	 * driver. */
-
-	if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") != 0) {
-		os_memset(addr, 0xff, ETH_ALEN);
-		hostapd_sta_deauth(hapd, addr,
-				   WLAN_REASON_PREV_AUTH_NOT_VALID);
-	}
-}
-
-
-/**
- * hostapd_prune_associations - Remove extraneous associations
- * @hapd: Pointer to BSS data for the most recent association
- * @sta: Pointer to the associated STA data
- *
- * This function looks through all radios and BSS's for previous
- * (stale) associations of STA. If any are found they are removed.
- */
-static void hostapd_prune_associations(struct hostapd_data *hapd,
-				       struct sta_info *sta)
-{
-	struct sta_info *osta;
-	struct hostapd_data *ohapd;
-	size_t i, j;
-	struct hapd_interfaces *interfaces = eloop_get_user_data();
-
-	for (i = 0; i < interfaces->count; i++) {
-		for (j = 0; j < interfaces->iface[i]->num_bss; j++) {
-			ohapd = interfaces->iface[i]->bss[j];
-			if (ohapd == hapd)
-				continue;
-			osta = ap_get_sta(ohapd, sta->addr);
-			if (!osta)
-				continue;
-
-			ap_sta_disassociate(ohapd, osta,
-					    WLAN_REASON_UNSPECIFIED);
-		}
-	}
-}
-
-
-/**
- * hostapd_new_assoc_sta - Notify that a new station associated with the AP
- * @hapd: Pointer to BSS data
- * @sta: Pointer to the associated STA data
- * @reassoc: 1 to indicate this was a re-association; 0 = first association
- *
- * This function will be called whenever a station associates with the AP. It
- * can be called for ieee802_11.c for drivers that export MLME to hostapd and
- * from driver_*.c for drivers that take care of management frames (IEEE 802.11
- * authentication and association) internally.
- */
-void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
-			   int reassoc)
-{
-	if (hapd->tkip_countermeasures) {
-		hostapd_sta_deauth(hapd, sta->addr,
-				   WLAN_REASON_MICHAEL_MIC_FAILURE);
-		return;
-	}
-
-	hostapd_prune_associations(hapd, sta);
-
-	/* IEEE 802.11F (IAPP) */
-	if (hapd->conf->ieee802_11f)
-		iapp_new_station(hapd->iapp, sta);
-
-	/* Start accounting here, if IEEE 802.1X and WPA are not used.
-	 * IEEE 802.1X/WPA code will start accounting after the station has
-	 * been authorized. */
-	if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
-		accounting_sta_start(hapd, sta);
-
-	hostapd_wmm_sta_config(hapd, sta);
-
-	/* Start IEEE 802.1X authentication process for new stations */
-	ieee802_1x_new_station(hapd, sta);
-	if (reassoc) {
-		if (sta->auth_alg != WLAN_AUTH_FT &&
-		    !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
-			wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
-	} else
-		wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
-}
-
-
-#ifdef EAP_SERVER
-static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd,
-				 struct sta_info *sta, void *ctx)
-{
-	if (eapol_auth_eap_pending_cb(sta->eapol_sm, ctx) == 0)
-		return 1;
-	return 0;
-}
-
-
-static void hostapd_sim_db_cb(void *ctx, void *session_ctx)
-{
-	struct hostapd_data *hapd = ctx;
-	if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0)
-		radius_server_eap_pending_cb(hapd->radius_srv, session_ctx);
-}
-#endif /* EAP_SERVER */
-
-
-/**
- * handle_term - SIGINT and SIGTERM handler to terminate hostapd process
- */
-static void handle_term(int sig, void *eloop_ctx, void *signal_ctx)
-{
-	wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
-	eloop_terminate();
-}
-
-
-static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
-				  struct wpa_auth_config *wconf)
-{
-	wconf->wpa = conf->wpa;
-	wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
-	wconf->wpa_pairwise = conf->wpa_pairwise;
-	wconf->wpa_group = conf->wpa_group;
-	wconf->wpa_group_rekey = conf->wpa_group_rekey;
-	wconf->wpa_strict_rekey = conf->wpa_strict_rekey;
-	wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey;
-	wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey;
-	wconf->rsn_pairwise = conf->rsn_pairwise;
-	wconf->rsn_preauth = conf->rsn_preauth;
-	wconf->eapol_version = conf->eapol_version;
-	wconf->peerkey = conf->peerkey;
-	wconf->wmm_enabled = conf->wmm_enabled;
-	wconf->okc = conf->okc;
-#ifdef CONFIG_IEEE80211W
-	wconf->ieee80211w = conf->ieee80211w;
-#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_IEEE80211R
-	wconf->ssid_len = conf->ssid.ssid_len;
-	if (wconf->ssid_len > SSID_LEN)
-		wconf->ssid_len = SSID_LEN;
-	os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len);
-	os_memcpy(wconf->mobility_domain, conf->mobility_domain,
-		  MOBILITY_DOMAIN_ID_LEN);
-	if (conf->nas_identifier &&
-	    os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) {
-		wconf->r0_key_holder_len = os_strlen(conf->nas_identifier);
-		os_memcpy(wconf->r0_key_holder, conf->nas_identifier,
-			  wconf->r0_key_holder_len);
-	}
-	os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN);
-	wconf->r0_key_lifetime = conf->r0_key_lifetime;
-	wconf->reassociation_deadline = conf->reassociation_deadline;
-	wconf->r0kh_list = conf->r0kh_list;
-	wconf->r1kh_list = conf->r1kh_list;
-	wconf->pmk_r1_push = conf->pmk_r1_push;
-#endif /* CONFIG_IEEE80211R */
-}
-
-
-int hostapd_reload_config(struct hostapd_iface *iface)
-{
-	struct hostapd_data *hapd = iface->bss[0];
-	struct hostapd_config *newconf, *oldconf;
-	struct wpa_auth_config wpa_auth_conf;
-	size_t j;
-
-	newconf = hostapd_config_read(iface->config_fname);
-	if (newconf == NULL)
-		return -1;
-
-	/*
-	 * Deauthenticate all stations since the new configuration may not
-	 * allow them to use the BSS anymore.
-	 */
-	for (j = 0; j < iface->num_bss; j++)
-		hostapd_flush_old_stations(iface->bss[j]);
-
-	/* TODO: update dynamic data based on changed configuration
-	 * items (e.g., open/close sockets, etc.) */
-	radius_client_flush(hapd->radius, 0);
-
-	oldconf = hapd->iconf;
-	hapd->iconf = newconf;
-	hapd->conf = &newconf->bss[0];
-	iface->conf = newconf;
-
-	if (hostapd_setup_wpa_psk(hapd->conf)) {
-		wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
-			   "after reloading configuration");
-	}
-
-	if (hapd->conf->wpa && hapd->wpa_auth == NULL)
-		hostapd_setup_wpa(hapd);
-	else if (hapd->conf->wpa) {
-		hostapd_wpa_auth_conf(&newconf->bss[0], &wpa_auth_conf);
-		wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf);
-	} else if (hapd->wpa_auth) {
-		wpa_deinit(hapd->wpa_auth);
-		hapd->wpa_auth = NULL;
-		hostapd_set_privacy(hapd, 0);
-		hostapd_setup_encryption(hapd->conf->iface, hapd);
-	}
-
-	ieee802_11_set_beacon(hapd);
-
-	if (hapd->conf->ssid.ssid_set &&
-	    hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid,
-			     hapd->conf->ssid.ssid_len)) {
-		wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
-		/* try to continue */
-	}
-
-	if (hapd->conf->ieee802_1x || hapd->conf->wpa)
-		hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1);
-
-	hostapd_config_free(oldconf);
-
-	wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
-
-	return 0;
-}
-
-
-#ifndef CONFIG_NATIVE_WINDOWS
-/**
- * handle_reload - SIGHUP handler to reload configuration
- */
-static void handle_reload(int sig, void *eloop_ctx, void *signal_ctx)
-{
-	struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx;
-	size_t i;
-
-	wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
-		   sig);
-
-	for (i = 0; i < hapds->count; i++) {
-		if (hostapd_reload_config(hapds->iface[i]) < 0) {
-			wpa_printf(MSG_WARNING, "Failed to read new "
-				   "configuration file - continuing with "
-				   "old.");
-			continue;
-		}
-	}
-}
-
-
-#ifdef HOSTAPD_DUMP_STATE
-/**
- * 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;
-	char *buf;
-
-	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\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_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);
-	}
-
-	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);
-
-		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);
-		os_free(buf);
-	}
-	fclose(f);
-}
-#endif /* HOSTAPD_DUMP_STATE */
-
-
-static void handle_dump_state(int sig, void *eloop_ctx, void *signal_ctx)
-{
-#ifdef HOSTAPD_DUMP_STATE
-	struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx;
-	size_t i, j;
-
-	for (i = 0; i < hapds->count; i++) {
-		struct hostapd_iface *hapd_iface = hapds->iface[i];
-		for (j = 0; j < hapd_iface->num_bss; j++)
-			hostapd_dump_state(hapd_iface->bss[j]);
-	}
-#endif /* HOSTAPD_DUMP_STATE */
-}
-#endif /* CONFIG_NATIVE_WINDOWS */
-
-static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
-					      char *ifname)
-{
-	int i;
-
-	for (i = 0; i < NUM_WEP_KEYS; i++) {
-		if (hostapd_set_encryption(ifname, hapd, "none", NULL, i, NULL,
-					   0, i == 0 ? 1 : 0)) {
-			wpa_printf(MSG_DEBUG, "Failed to clear default "
-				   "encryption keys (ifname=%s keyidx=%d)",
-				   ifname, i);
-		}
-	}
-#ifdef CONFIG_IEEE80211W
-	if (hapd->conf->ieee80211w) {
-		for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
-			if (hostapd_set_encryption(ifname, hapd, "none", NULL,
-						   i, NULL, 0,
-						   i == 0 ? 1 : 0)) {
-				wpa_printf(MSG_DEBUG, "Failed to clear "
-					   "default mgmt encryption keys "
-					   "(ifname=%s keyidx=%d)", ifname, i);
-			}
-		}
-	}
-#endif /* CONFIG_IEEE80211W */
-}
-
-
-static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd)
-{
-	hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface);
-	return 0;
-}
-
-
-static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
-{
-	int errors = 0, idx;
-	struct hostapd_ssid *ssid = &hapd->conf->ssid;
-
-	idx = ssid->wep.idx;
-	if (ssid->wep.default_len &&
-	    hostapd_set_encryption(hapd->conf->iface,
-				   hapd, "WEP", NULL, idx,
-			 	   ssid->wep.key[idx],
-			 	   ssid->wep.len[idx],
-				   idx == ssid->wep.idx)) {
-		wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
-		errors++;
-	}
-
-	if (ssid->dyn_vlan_keys) {
-		size_t i;
-		for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
-			const char *ifname;
-			struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i];
-			if (key == NULL)
-				continue;
-			ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan,
-							    i);
-			if (ifname == NULL)
-				continue;
-
-			idx = key->idx;
-			if (hostapd_set_encryption(ifname, hapd, "WEP", NULL,
-						   idx, key->key[idx],
-						   key->len[idx],
-						   idx == key->idx)) {
-				wpa_printf(MSG_WARNING, "Could not set "
-					   "dynamic VLAN WEP encryption.");
-				errors++;
-			}
-		}
-	}
-
-	return errors;
-}
-
-/**
- * hostapd_cleanup - Per-BSS cleanup (deinitialization)
- * @hapd: Pointer to BSS data
- *
- * This function is used to free all per-BSS data structures and resources.
- * This gets called in a loop for each BSS between calls to
- * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface
- * is deinitialized. Most of the modules that are initialized in
- * hostapd_setup_bss() are deinitialized here.
- */
-static void hostapd_cleanup(struct hostapd_data *hapd)
-{
-	hostapd_ctrl_iface_deinit(hapd);
-
-	os_free(hapd->default_wep_key);
-	hapd->default_wep_key = NULL;
-	iapp_deinit(hapd->iapp);
-	hapd->iapp = NULL;
-	accounting_deinit(hapd);
-	rsn_preauth_iface_deinit(hapd);
-	if (hapd->wpa_auth) {
-		wpa_deinit(hapd->wpa_auth);
-		hapd->wpa_auth = NULL;
-
-		if (hostapd_set_privacy(hapd, 0)) {
-			wpa_printf(MSG_DEBUG, "Could not disable "
-				   "PrivacyInvoked for interface %s",
-				   hapd->conf->iface);
-		}
-
-		if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) {
-			wpa_printf(MSG_DEBUG, "Could not remove generic "
-				   "information element from interface %s",
-				   hapd->conf->iface);
-		}
-	}
-	ieee802_1x_deinit(hapd);
-	vlan_deinit(hapd);
-	hostapd_acl_deinit(hapd);
-	radius_client_deinit(hapd->radius);
-	hapd->radius = NULL;
-	radius_server_deinit(hapd->radius_srv);
-	hapd->radius_srv = NULL;
-
-#ifdef CONFIG_IEEE80211R
-	l2_packet_deinit(hapd->l2);
-#endif /* CONFIG_IEEE80211R */
-
-	hostapd_deinit_wps(hapd);
-
-	hostapd_wireless_event_deinit(hapd);
-
-#ifdef EAP_TLS_FUNCS
-	if (hapd->ssl_ctx) {
-		tls_deinit(hapd->ssl_ctx);
-		hapd->ssl_ctx = NULL;
-	}
-#endif /* EAP_TLS_FUNCS */
-
-#ifdef EAP_SERVER
-	if (hapd->eap_sim_db_priv) {
-		eap_sim_db_deinit(hapd->eap_sim_db_priv);
-		hapd->eap_sim_db_priv = NULL;
-	}
-#endif /* EAP_SERVER */
-
-	if (hapd->interface_added &&
-	    hostapd_bss_remove(hapd, hapd->conf->iface)) {
-		wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
-			   hapd->conf->iface);
-	}
-}
-
-
-/**
- * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup
- * @iface: Pointer to interface data
- *
- * This function is called before per-BSS data structures are deinitialized
- * with hostapd_cleanup().
- */
-static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
-{
-}
-
-
-/**
- * hostapd_cleanup_iface - Complete per-interface cleanup
- * @iface: Pointer to interface data
- *
- * This function is called after per-BSS data structures are deinitialized
- * with hostapd_cleanup().
- */
-static void hostapd_cleanup_iface(struct hostapd_iface *iface)
-{
-	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
-	iface->hw_features = NULL;
-	os_free(iface->current_rates);
-	iface->current_rates = NULL;
-	ap_list_deinit(iface);
-	hostapd_config_free(iface->conf);
-	iface->conf = NULL;
-
-	os_free(iface->config_fname);
-	os_free(iface->bss);
-	os_free(iface);
-}
-
-
-static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
-{
-	int i;
-
-	hostapd_broadcast_wep_set(hapd);
-
-	if (hapd->conf->ssid.wep.default_len)
-		return 0;
-
-	for (i = 0; i < 4; i++) {
-		if (hapd->conf->ssid.wep.key[i] &&
-		    hostapd_set_encryption(iface, hapd, "WEP", NULL,
-					   i, hapd->conf->ssid.wep.key[i],
-					   hapd->conf->ssid.wep.len[i],
-					   i == hapd->conf->ssid.wep.idx)) {
-			wpa_printf(MSG_WARNING, "Could not set WEP "
-				   "encryption.");
-			return -1;
-		}
-		if (hapd->conf->ssid.wep.key[i] &&
-		    i == hapd->conf->ssid.wep.idx)
-			hostapd_set_privacy(hapd, 1);
-	}
-
-	return 0;
-}
-
-
-static int hostapd_flush_old_stations(struct hostapd_data *hapd)
-{
-	int ret = 0;
-
-	if (hostapd_drv_none(hapd))
-		return 0;
-
-	wpa_printf(MSG_DEBUG, "Flushing old station entries");
-	if (hostapd_flush(hapd)) {
-		wpa_printf(MSG_WARNING, "Could not connect to kernel driver.");
-		ret = -1;
-	}
-	wpa_printf(MSG_DEBUG, "Deauthenticate all stations");
-	hostapd_deauth_all_stas(hapd);
-
-	return ret;
-}
-
-
-static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr,
-				    logger_level level, const char *txt)
-{
-	struct hostapd_data *hapd = ctx;
-	int hlevel;
-
-	switch (level) {
-	case LOGGER_WARNING:
-		hlevel = HOSTAPD_LEVEL_WARNING;
-		break;
-	case LOGGER_INFO:
-		hlevel = HOSTAPD_LEVEL_INFO;
-		break;
-	case LOGGER_DEBUG:
-	default:
-		hlevel = HOSTAPD_LEVEL_DEBUG;
-		break;
-	}
-
-	hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt);
-}
-
-
-static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr,
-					u16 reason)
-{
-	struct hostapd_data *hapd = ctx;
-	struct sta_info *sta;
-
-	wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: "
-		   "STA " MACSTR " reason %d",
-		   __func__, MAC2STR(addr), reason);
-
-	sta = ap_get_sta(hapd, addr);
-	hostapd_sta_deauth(hapd, addr, reason);
-	if (sta == NULL)
-		return;
-	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED);
-	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
-	eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
-	sta->timeout_next = STA_REMOVE;
-}
-
-
-static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
-{
-	struct hostapd_data *hapd = ctx;
-	ieee80211_michael_mic_failure(hapd, addr, 0);
-}
-
-
-static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr,
-				       wpa_eapol_variable var, int value)
-{
-	struct hostapd_data *hapd = ctx;
-	struct sta_info *sta = ap_get_sta(hapd, addr);
-	if (sta == NULL)
-		return;
-	switch (var) {
-	case WPA_EAPOL_portEnabled:
-		ieee802_1x_notify_port_enabled(sta->eapol_sm, value);
-		break;
-	case WPA_EAPOL_portValid:
-		ieee802_1x_notify_port_valid(sta->eapol_sm, value);
-		break;
-	case WPA_EAPOL_authorized:
-		ieee802_1x_set_sta_authorized(hapd, sta, value);
-		break;
-	case WPA_EAPOL_portControl_Auto:
-		if (sta->eapol_sm)
-			sta->eapol_sm->portControl = Auto;
-		break;
-	case WPA_EAPOL_keyRun:
-		if (sta->eapol_sm)
-			sta->eapol_sm->keyRun = value ? TRUE : FALSE;
-		break;
-	case WPA_EAPOL_keyAvailable:
-		if (sta->eapol_sm)
-			sta->eapol_sm->eap_if->eapKeyAvailable =
-				value ? TRUE : FALSE;
-		break;
-	case WPA_EAPOL_keyDone:
-		if (sta->eapol_sm)
-			sta->eapol_sm->keyDone = value ? TRUE : FALSE;
-		break;
-	case WPA_EAPOL_inc_EapolFramesTx:
-		if (sta->eapol_sm)
-			sta->eapol_sm->dot1xAuthEapolFramesTx++;
-		break;
-	}
-}
-
-
-static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr,
-				      wpa_eapol_variable var)
-{
-	struct hostapd_data *hapd = ctx;
-	struct sta_info *sta = ap_get_sta(hapd, addr);
-	if (sta == NULL || sta->eapol_sm == NULL)
-		return -1;
-	switch (var) {
-	case WPA_EAPOL_keyRun:
-		return sta->eapol_sm->keyRun;
-	case WPA_EAPOL_keyAvailable:
-		return sta->eapol_sm->eap_if->eapKeyAvailable;
-	default:
-		return -1;
-	}
-}
-
-
-static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
-					   const u8 *prev_psk)
-{
-	struct hostapd_data *hapd = ctx;
-	return hostapd_get_psk(hapd->conf, addr, prev_psk);
-}
-
-
-static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk,
-				    size_t *len)
-{
-	struct hostapd_data *hapd = ctx;
-	const u8 *key;
-	size_t keylen;
-	struct sta_info *sta;
-
-	sta = ap_get_sta(hapd, addr);
-	if (sta == NULL)
-		return -1;
-
-	key = ieee802_1x_get_key(sta->eapol_sm, &keylen);
-	if (key == NULL)
-		return -1;
-
-	if (keylen > *len)
-		keylen = *len;
-	os_memcpy(msk, key, keylen);
-	*len = keylen;
-
-	return 0;
-}
-
-
-static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, const char *alg,
-				    const u8 *addr, int idx, u8 *key,
-				    size_t key_len)
-{
-	struct hostapd_data *hapd = ctx;
-	const char *ifname = hapd->conf->iface;
-
-	if (vlan_id > 0) {
-		ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id);
-		if (ifname == NULL)
-			return -1;
-	}
-
-	return hostapd_set_encryption(ifname, hapd, alg, addr, idx,
-				      key, key_len, 1);
-}
-
-
-static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx,
-				       u8 *seq)
-{
-	struct hostapd_data *hapd = ctx;
-	return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq);
-}
-
-
-static int hostapd_wpa_auth_get_seqnum_igtk(void *ctx, const u8 *addr, int idx,
-					    u8 *seq)
-{
-	struct hostapd_data *hapd = ctx;
-	return hostapd_get_seqnum_igtk(hapd->conf->iface, hapd, addr, idx,
-				       seq);
-}
-
-
-static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
-				       const u8 *data, size_t data_len,
-				       int encrypt)
-{
-	struct hostapd_data *hapd = ctx;
-	return hostapd_send_eapol(hapd, addr, data, data_len, encrypt);
-}
-
-
-static int hostapd_wpa_auth_for_each_sta(
-	void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx),
-	void *cb_ctx)
-{
-	struct hostapd_data *hapd = ctx;
-	struct sta_info *sta;
-
-	for (sta = hapd->sta_list; sta; sta = sta->next) {
-		if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx))
-			return 1;
-	}
-	return 0;
-}
-
-
-static int hostapd_wpa_auth_for_each_auth(
-	void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx),
-	void *cb_ctx)
-{
-	struct hostapd_data *ohapd;
-	size_t i, j;
-	struct hapd_interfaces *interfaces = eloop_get_user_data();
-
-	for (i = 0; i < interfaces->count; i++) {
-		for (j = 0; j < interfaces->iface[i]->num_bss; j++) {
-			ohapd = interfaces->iface[i]->bss[j];
-			if (cb(ohapd->wpa_auth, cb_ctx))
-				return 1;
-		}
-	}
-
-	return 0;
-}
-
-
-static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
-				       const u8 *data, size_t data_len)
-{
-	struct hostapd_data *hapd = ctx;
-
-	if (hapd->driver && hapd->driver->send_ether)
-		return hapd->driver->send_ether(hapd->drv_priv, dst,
-						hapd->own_addr, proto,
-						data, data_len);
-	if (hapd->l2 == NULL)
-		return -1;
-	return l2_packet_send(hapd->l2, dst, proto, data, data_len);
-}
-
-
-#ifdef CONFIG_IEEE80211R
-
-static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
-					   const u8 *data, size_t data_len)
-{
-	struct hostapd_data *hapd = ctx;
-	int res;
-	struct ieee80211_mgmt *m;
-	size_t mlen;
-	struct sta_info *sta;
-
-	sta = ap_get_sta(hapd, dst);
-	if (sta == NULL || sta->wpa_sm == NULL)
-		return -1;
-
-	m = os_zalloc(sizeof(*m) + data_len);
-	if (m == NULL)
-		return -1;
-	mlen = ((u8 *) &m->u - (u8 *) m) + data_len;
-	m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
-					WLAN_FC_STYPE_ACTION);
-	os_memcpy(m->da, dst, ETH_ALEN);
-	os_memcpy(m->sa, hapd->own_addr, ETH_ALEN);
-	os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
-	os_memcpy(&m->u, data, data_len);
-
-	res = hostapd_send_mgmt_frame(hapd, (u8 *) m, mlen, 0);
-	os_free(m);
-	return res;
-}
-
-
-static struct wpa_state_machine *
-hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
-{
-	struct hostapd_data *hapd = ctx;
-	struct sta_info *sta;
-
-	sta = ap_sta_add(hapd, sta_addr);
-	if (sta == NULL)
-		return NULL;
-	if (sta->wpa_sm)
-		return sta->wpa_sm;
-
-	sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr);
-	if (sta->wpa_sm == NULL) {
-		ap_free_sta(hapd, sta);
-		return NULL;
-	}
-	sta->auth_alg = WLAN_AUTH_FT;
-
-	return sta->wpa_sm;
-}
-
-
-static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
-				size_t len)
-{
-	struct hostapd_data *hapd = ctx;
-	wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len);
-}
-
-#endif /* CONFIG_IEEE80211R */
-
-
-/**
- * hostapd_validate_bssid_configuration - Validate BSSID configuration
- * @iface: Pointer to interface data
- * Returns: 0 on success, -1 on failure
- *
- * This function is used to validate that the configured BSSIDs are valid.
- */
-static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
-{
-	u8 mask[ETH_ALEN] = { 0 };
-	struct hostapd_data *hapd = iface->bss[0];
-	unsigned int i = iface->conf->num_bss, bits = 0, j;
-	int res;
-
-	if (hostapd_drv_none(hapd))
-		return 0;
-
-	/* Generate BSSID mask that is large enough to cover the BSSIDs. */
-
-	/* Determine the bits necessary to cover the number of BSSIDs. */
-	for (i--; i; i >>= 1)
-		bits++;
-
-	/* Determine the bits necessary to any configured BSSIDs,
-	   if they are higher than the number of BSSIDs. */
-	for (j = 0; j < iface->conf->num_bss; j++) {
-		if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0)
-			continue;
-
-		for (i = 0; i < ETH_ALEN; i++) {
-			mask[i] |=
-				iface->conf->bss[j].bssid[i] ^
-				hapd->own_addr[i];
-		}
-	}
-
-	for (i = 0; i < ETH_ALEN && mask[i] == 0; i++)
-		;
-	j = 0;
-	if (i < ETH_ALEN) {
-		j = (5 - i) * 8;
-
-		while (mask[i] != 0) {
-			mask[i] >>= 1;
-			j++;
-		}
-	}
-
-	if (bits < j)
-		bits = j;
-
-	if (bits > 40)
-		return -1;
-
-	os_memset(mask, 0xff, ETH_ALEN);
-	j = bits / 8;
-	for (i = 5; i > 5 - j; i--)
-		mask[i] = 0;
-	j = bits % 8;
-	while (j--)
-		mask[i] <<= 1;
-
-	wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
-		   (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
-
-	res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask);
-	if (res == 0)
-		return 0;
-
-	if (res < 0) {
-		wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask "
-			   MACSTR " for start address " MACSTR ".",
-			   MAC2STR(mask), MAC2STR(hapd->own_addr));
-		return -1;
-	}
-
-	for (i = 0; i < ETH_ALEN; i++) {
-		if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) {
-			wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR
-				   " for start address " MACSTR ".",
-				   MAC2STR(mask), MAC2STR(hapd->own_addr));
-			wpa_printf(MSG_ERROR, "Start address must be the "
-				   "first address in the block (i.e., addr "
-				   "AND mask == addr).");
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-
-static int mac_in_conf(struct hostapd_config *conf, const void *a)
-{
-	size_t i;
-
-	for (i = 0; i < conf->num_bss; i++) {
-		if (hostapd_mac_comp(conf->bss[i].bssid, a) == 0) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-
-static int hostapd_setup_wpa(struct hostapd_data *hapd)
-{
-	struct wpa_auth_config _conf;
-	struct wpa_auth_callbacks cb;
-	const u8 *wpa_ie;
-	size_t wpa_ie_len;
-
-	hostapd_wpa_auth_conf(hapd->conf, &_conf);
-	os_memset(&cb, 0, sizeof(cb));
-	cb.ctx = hapd;
-	cb.logger = hostapd_wpa_auth_logger;
-	cb.disconnect = hostapd_wpa_auth_disconnect;
-	cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report;
-	cb.set_eapol = hostapd_wpa_auth_set_eapol;
-	cb.get_eapol = hostapd_wpa_auth_get_eapol;
-	cb.get_psk = hostapd_wpa_auth_get_psk;
-	cb.get_msk = hostapd_wpa_auth_get_msk;
-	cb.set_key = hostapd_wpa_auth_set_key;
-	cb.get_seqnum = hostapd_wpa_auth_get_seqnum;
-	cb.get_seqnum_igtk = hostapd_wpa_auth_get_seqnum_igtk;
-	cb.send_eapol = hostapd_wpa_auth_send_eapol;
-	cb.for_each_sta = hostapd_wpa_auth_for_each_sta;
-	cb.for_each_auth = hostapd_wpa_auth_for_each_auth;
-	cb.send_ether = hostapd_wpa_auth_send_ether;
-#ifdef CONFIG_IEEE80211R
-	cb.send_ft_action = hostapd_wpa_auth_send_ft_action;
-	cb.add_sta = hostapd_wpa_auth_add_sta;
-#endif /* CONFIG_IEEE80211R */
-	hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb);
-	if (hapd->wpa_auth == NULL) {
-		wpa_printf(MSG_ERROR, "WPA initialization failed.");
-		return -1;
-	}
-
-	if (hostapd_set_privacy(hapd, 1)) {
-		wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked "
-			   "for interface %s", hapd->conf->iface);
-		return -1;
-	}
-
-	wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
-	if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) {
-		wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
-			   "the kernel driver.");
-		return -1;
-	}
-
-	if (rsn_preauth_iface_init(hapd)) {
-		wpa_printf(MSG_ERROR, "Initialization of RSN "
-			   "pre-authentication failed.");
-		return -1;
-	}
-
-	return 0;
-
-}
-
-
-static int hostapd_setup_radius_srv(struct hostapd_data *hapd,
-				    struct hostapd_bss_config *conf)
-{
-	struct radius_server_conf srv;
-	os_memset(&srv, 0, sizeof(srv));
-	srv.client_file = conf->radius_server_clients;
-	srv.auth_port = conf->radius_server_auth_port;
-	srv.conf_ctx = conf;
-	srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
-	srv.ssl_ctx = hapd->ssl_ctx;
-	srv.pac_opaque_encr_key = conf->pac_opaque_encr_key;
-	srv.eap_fast_a_id = conf->eap_fast_a_id;
-	srv.eap_fast_a_id_len = conf->eap_fast_a_id_len;
-	srv.eap_fast_a_id_info = conf->eap_fast_a_id_info;
-	srv.eap_fast_prov = conf->eap_fast_prov;
-	srv.pac_key_lifetime = conf->pac_key_lifetime;
-	srv.pac_key_refresh_time = conf->pac_key_refresh_time;
-	srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
-	srv.tnc = conf->tnc;
-	srv.wps = hapd->wps;
-	srv.ipv6 = conf->radius_server_ipv6;
-	srv.get_eap_user = hostapd_radius_get_eap_user;
-	srv.eap_req_id_text = conf->eap_req_id_text;
-	srv.eap_req_id_text_len = conf->eap_req_id_text_len;
-
-	hapd->radius_srv = radius_server_init(&srv);
-	if (hapd->radius_srv == NULL) {
-		wpa_printf(MSG_ERROR, "RADIUS server initialization failed.");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-/**
- * hostapd_setup_bss - Per-BSS setup (initialization)
- * @hapd: Pointer to BSS data
- * @first: Whether this BSS is the first BSS of an interface
- *
- * This function is used to initialize all per-BSS data structures and
- * resources. This gets called in a loop for each BSS when an interface is
- * initialized. Most of the modules that are initialized here will be
- * deinitialized in hostapd_cleanup().
- */
-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
-{
-	struct hostapd_bss_config *conf = hapd->conf;
-	u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
-	int ssid_len, set_ssid;
-
-	if (!first) {
-		if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
-			/* Allocate the next available BSSID. */
-			do {
-				inc_byte_array(hapd->own_addr, ETH_ALEN);
-			} while (mac_in_conf(hapd->iconf, hapd->own_addr));
-		} else {
-			/* Allocate the configured BSSID. */
-			os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN);
-
-			if (hostapd_mac_comp(hapd->own_addr,
-					     hapd->iface->bss[0]->own_addr) ==
-			    0) {
-				wpa_printf(MSG_ERROR, "BSS '%s' may not have "
-					   "BSSID set to the MAC address of "
-					   "the radio", hapd->conf->iface);
-				return -1;
-			}
-		}
-
-		hapd->interface_added = 1;
-		if (hostapd_bss_add(hapd->iface->bss[0], hapd->conf->iface,
-				    hapd->own_addr)) {
-			wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
-				   MACSTR ")", MAC2STR(hapd->own_addr));
-			return -1;
-		}
-	}
-
-	hostapd_flush_old_stations(hapd);
-	hostapd_set_privacy(hapd, 0);
-
-	hostapd_broadcast_wep_clear(hapd);
-	if (hostapd_setup_encryption(hapd->conf->iface, hapd))
-		return -1;
-
-	/*
-	 * Fetch the SSID from the system and use it or,
-	 * if one was specified in the config file, verify they
-	 * match.
-	 */
-	ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid));
-	if (ssid_len < 0) {
-		wpa_printf(MSG_ERROR, "Could not read SSID from system");
-		return -1;
-	}
-	if (conf->ssid.ssid_set) {
-		/*
-		 * If SSID is specified in the config file and it differs
-		 * from what is being used then force installation of the
-		 * new SSID.
-		 */
-		set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len ||
-			    os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0);
-	} else {
-		/*
-		 * No SSID in the config file; just use the one we got
-		 * from the system.
-		 */
-		set_ssid = 0;
-		conf->ssid.ssid_len = ssid_len;
-		os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
-		conf->ssid.ssid[conf->ssid.ssid_len] = '\0';
-	}
-
-	if (!hostapd_drv_none(hapd)) {
-		wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
-			   " and ssid '%s'",
-			   hapd->conf->iface, MAC2STR(hapd->own_addr),
-			   hapd->conf->ssid.ssid);
-	}
-
-	if (hostapd_setup_wpa_psk(conf)) {
-		wpa_printf(MSG_ERROR, "WPA-PSK setup failed.");
-		return -1;
-	}
-
-	/* Set flag for whether SSID is broadcast in beacons */
-	if (hostapd_set_broadcast_ssid(hapd,
-				       !!hapd->conf->ignore_broadcast_ssid)) {
-		wpa_printf(MSG_ERROR, "Could not set broadcast SSID flag for "
-			   "kernel driver");
-		return -1;
-	}
-
-	if (hostapd_set_dtim_period(hapd, hapd->conf->dtim_period)) {
-		wpa_printf(MSG_ERROR, "Could not set DTIM period for kernel "
-			   "driver");
-		return -1;
-	}
-
-	/* Set SSID for the kernel driver (to be used in beacon and probe
-	 * response frames) */
-	if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid.ssid,
-					 conf->ssid.ssid_len)) {
-		wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
-		return -1;
-	}
-
-	if (wpa_debug_level == MSG_MSGDUMP)
-		conf->radius->msg_dumps = 1;
-	hapd->radius = radius_client_init(hapd, conf->radius);
-	if (hapd->radius == NULL) {
-		wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
-		return -1;
-	}
-
-	if (hostapd_acl_init(hapd)) {
-		wpa_printf(MSG_ERROR, "ACL initialization failed.");
-		return -1;
-	}
-	if (hostapd_init_wps(hapd, conf))
-		return -1;
-
-	if (ieee802_1x_init(hapd)) {
-		wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed.");
-		return -1;
-	}
-
-	if (hapd->conf->wpa && hostapd_setup_wpa(hapd))
-		return -1;
-
-	if (accounting_init(hapd)) {
-		wpa_printf(MSG_ERROR, "Accounting initialization failed.");
-		return -1;
-	}
-
-	if (hapd->conf->ieee802_11f &&
-	    (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) {
-		wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
-			   "failed.");
-		return -1;
-	}
-
-	if (hostapd_ctrl_iface_init(hapd)) {
-		wpa_printf(MSG_ERROR, "Failed to setup control interface");
-		return -1;
-	}
-
-	if (!hostapd_drv_none(hapd) && vlan_init(hapd)) {
-		wpa_printf(MSG_ERROR, "VLAN initialization failed.");
-		return -1;
-	}
-
-#ifdef CONFIG_IEEE80211R
-	if (!hostapd_drv_none(hapd)) {
-		hapd->l2 = l2_packet_init(hapd->conf->iface, NULL, ETH_P_RRB,
-					  hostapd_rrb_receive, hapd, 0);
-		if (hapd->l2 == NULL &&
-		    (hapd->driver == NULL ||
-		     hapd->driver->send_ether == NULL)) {
-			wpa_printf(MSG_ERROR, "Failed to open l2_packet "
-				   "interface");
-			return -1;
-		}
-	}
-#endif /* CONFIG_IEEE80211R */
-
-	ieee802_11_set_beacon(hapd);
-
-	if (conf->radius_server_clients &&
-	    hostapd_setup_radius_srv(hapd, conf))
-		return -1;
-
-	return 0;
-}
-
-
-static void hostapd_tx_queue_params(struct hostapd_iface *iface)
-{
-	struct hostapd_data *hapd = iface->bss[0];
-	int i;
-	struct hostapd_tx_queue_params *p;
-
-	for (i = 0; i < NUM_TX_QUEUES; i++) {
-		p = &iface->conf->tx_queue[i];
-
-		if (!p->configured)
-			continue;
-
-		if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin,
-						p->cwmax, p->burst)) {
-			wpa_printf(MSG_DEBUG, "Failed to set TX queue "
-				   "parameters for queue %d.", i);
-			/* Continue anyway */
-		}
-	}
-}
-
-
-static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
-				       size_t identity_len, int phase2,
-				       struct eap_user *user)
-{
-	const struct hostapd_eap_user *eap_user;
-	int i, count;
-
-	eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
-	if (eap_user == NULL)
-		return -1;
-
-	if (user == NULL)
-		return 0;
-
-	os_memset(user, 0, sizeof(*user));
-	count = EAP_USER_MAX_METHODS;
-	if (count > EAP_MAX_METHODS)
-		count = EAP_MAX_METHODS;
-	for (i = 0; i < count; i++) {
-		user->methods[i].vendor = eap_user->methods[i].vendor;
-		user->methods[i].method = eap_user->methods[i].method;
-	}
-
-	if (eap_user->password) {
-		user->password = os_malloc(eap_user->password_len);
-		if (user->password == NULL)
-			return -1;
-		os_memcpy(user->password, eap_user->password,
-			  eap_user->password_len);
-		user->password_len = eap_user->password_len;
-		user->password_hash = eap_user->password_hash;
-	}
-	user->force_version = eap_user->force_version;
-	user->ttls_auth = eap_user->ttls_auth;
-
-	return 0;
-}
-
-
-static int setup_interface(struct hostapd_iface *iface)
-{
-	struct hostapd_data *hapd = iface->bss[0];
-	struct hostapd_bss_config *conf = hapd->conf;
-	size_t i;
-	char country[4];
-	u8 *b = conf->bssid;
-	int freq;
-	size_t j;
-	u8 *prev_addr;
-
-	/*
-	 * Initialize the driver interface and make sure that all BSSes get
-	 * configured with a pointer to this driver interface.
-	 */
-	if (b[0] | b[1] | b[2] | b[3] | b[4] | b[5]) {
-		hapd->drv_priv = hostapd_driver_init_bssid(hapd, b);
-	} else {
-		hapd->drv_priv = hostapd_driver_init(hapd);
-	}
-
-	if (hapd->drv_priv == NULL) {
-		wpa_printf(MSG_ERROR, "%s driver initialization failed.",
-			   hapd->driver ? hapd->driver->name : "Unknown");
-		hapd->driver = NULL;
-		return -1;
-	}
-	for (i = 0; i < iface->num_bss; i++) {
-		iface->bss[i]->driver = hapd->driver;
-		iface->bss[i]->drv_priv = hapd->drv_priv;
-	}
-
-	if (hostapd_validate_bssid_configuration(iface))
-		return -1;
-
-#ifdef CONFIG_IEEE80211N
-	SET_2BIT_LE16(&iface->ht_op_mode,
-		      HT_INFO_OPERATION_MODE_OP_MODE_OFFSET,
-		      OP_MODE_PURE);
-#endif /* CONFIG_IEEE80211N */
-
-	if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
-		os_memcpy(country, hapd->iconf->country, 3);
-		country[3] = '\0';
-		if (hostapd_set_country(hapd, country) < 0) {
-			wpa_printf(MSG_ERROR, "Failed to set country code");
-			return -1;
-		}
-	}
-
-	if (hapd->iconf->ieee80211d &&
-	    hostapd_set_ieee80211d(hapd, 1) < 0) {
-		wpa_printf(MSG_ERROR, "Failed to set ieee80211d (%d)",
-			   hapd->iconf->ieee80211d);
-		return -1;
-	}
-
-	if (hapd->iconf->bridge_packets != INTERNAL_BRIDGE_DO_NOT_CONTROL &&
-	    hostapd_set_internal_bridge(hapd, hapd->iconf->bridge_packets)) {
-		wpa_printf(MSG_ERROR, "Failed to set bridge_packets for "
-			   "kernel driver");
-		return -1;
-	}
-
-	/* TODO: merge with hostapd_driver_init() ? */
-	if (hostapd_wireless_event_init(hapd) < 0)
-		return -1;
-
-	if (hostapd_get_hw_features(iface)) {
-		/* Not all drivers support this yet, so continue without hw
-		 * feature data. */
-	} else {
-		int ret = hostapd_select_hw_mode(iface);
-		if (ret < 0) {
-			wpa_printf(MSG_ERROR, "Could not select hw_mode and "
-				   "channel. (%d)", ret);
-			return -1;
-		}
-	}
-
-	if (hapd->iconf->channel) {
-		freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel);
-		wpa_printf(MSG_DEBUG, "Mode: %s  Channel: %d  "
-			   "Frequency: %d MHz",
-			   hostapd_hw_mode_txt(hapd->iconf->hw_mode),
-			   hapd->iconf->channel, freq);
-
-		if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, freq,
-				     hapd->iconf->ieee80211n,
-				     hapd->iconf->secondary_channel)) {
-			wpa_printf(MSG_ERROR, "Could not set channel for "
-				   "kernel driver");
-			return -1;
-		}
-	}
-
-	hostapd_set_beacon_int(hapd, hapd->iconf->beacon_int);
-
-	if (hapd->iconf->rts_threshold > -1 &&
-	    hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
-		wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
-			   "kernel driver");
-		return -1;
-	}
-
-	if (hapd->iconf->fragm_threshold > -1 &&
-	    hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {
-		wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
-			   "for kernel driver");
-		return -1;
-	}
-
-	prev_addr = hapd->own_addr;
-
-	for (j = 0; j < iface->num_bss; j++) {
-		hapd = iface->bss[j];
-		if (j)
-			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
-		if (hostapd_setup_bss(hapd, j == 0))
-			return -1;
-		if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
-			prev_addr = hapd->own_addr;
-	}
-
-	hostapd_tx_queue_params(iface);
-
-	ap_list_init(iface);
-
-	if (hostapd_driver_commit(hapd) < 0) {
-		wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
-			   "configuration", __func__);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-/**
- * hostapd_setup_interface - Setup of an interface
- * @iface: Pointer to interface data.
- * Returns: 0 on success, -1 on failure
- *
- * Initializes the driver interface, validates the configuration,
- * and sets driver parameters based on the configuration.
- * Flushes old stations, sets the channel, encryption,
- * beacons, and WDS links based on the configuration.
- */
-static int hostapd_setup_interface(struct hostapd_iface *iface)
-{
-	int ret;
-
-	ret = setup_interface(iface);
-	if (ret) {
-		wpa_printf(MSG_DEBUG, "%s: Unable to setup interface.",
-			   iface->bss[0]->conf->iface);
-		eloop_terminate();
-		return -1;
-	} else if (!hostapd_drv_none(iface->bss[0])) {
-		wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
-			   iface->bss[0]->conf->iface);
-	}
-
-	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-2009, Jouni Malinen  "
-		"and contributors\n");
-}
-
-
-static void usage(void)
-{
-	show_version();
-	fprintf(stderr,
-		"\n"
-		"usage: hostapd [-hdBKtv] [-P ] "
-		"\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);
-}
-
-
-/**
- * hostapd_alloc_bss_data - Allocate and initialize per-BSS data
- * @hapd_iface: Pointer to interface data
- * @conf: Pointer to per-interface configuration
- * @bss: Pointer to per-BSS configuration for this BSS
- * Returns: Pointer to allocated BSS data
- *
- * This function is used to allocate per-BSS data structure. This data will be
- * freed after hostapd_cleanup() is called for it during interface
- * deinitialization.
- */
-static struct hostapd_data *
-hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
-		       struct hostapd_config *conf,
-		       struct hostapd_bss_config *bss)
-{
-	struct hostapd_data *hapd;
-
-	hapd = os_zalloc(sizeof(*hapd));
-	if (hapd == NULL)
-		return NULL;
-
-	hapd->iconf = conf;
-	hapd->conf = bss;
-	hapd->iface = hapd_iface;
-
-	if (hapd->conf->individual_wep_key_len > 0) {
-		/* use key0 in individual key and key1 in broadcast key */
-		hapd->default_wep_key_idx = 1;
-	}
-
-#ifdef EAP_TLS_FUNCS
-	if (hapd->conf->eap_server &&
-	    (hapd->conf->ca_cert || hapd->conf->server_cert ||
-	     hapd->conf->dh_file)) {
-		struct tls_connection_params params;
-
-		hapd->ssl_ctx = tls_init(NULL);
-		if (hapd->ssl_ctx == NULL) {
-			wpa_printf(MSG_ERROR, "Failed to initialize TLS");
-			goto fail;
-		}
-
-		os_memset(¶ms, 0, sizeof(params));
-		params.ca_cert = hapd->conf->ca_cert;
-		params.client_cert = hapd->conf->server_cert;
-		params.private_key = hapd->conf->private_key;
-		params.private_key_passwd = hapd->conf->private_key_passwd;
-		params.dh_file = hapd->conf->dh_file;
-
-		if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) {
-			wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
-			goto fail;
-		}
-
-		if (tls_global_set_verify(hapd->ssl_ctx,
-					  hapd->conf->check_crl)) {
-			wpa_printf(MSG_ERROR, "Failed to enable check_crl");
-			goto fail;
-		}
-	}
-#endif /* EAP_TLS_FUNCS */
-
-#ifdef EAP_SERVER
-	if (hapd->conf->eap_sim_db) {
-		hapd->eap_sim_db_priv =
-			eap_sim_db_init(hapd->conf->eap_sim_db,
-					hostapd_sim_db_cb, hapd);
-		if (hapd->eap_sim_db_priv == NULL) {
-			wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM "
-				   "database interface");
-			goto fail;
-		}
-	}
-#endif /* EAP_SERVER */
-
-	hapd->driver = hapd->iconf->driver;
-
-	return hapd;
-
-#if defined(EAP_TLS_FUNCS) || defined(EAP_SERVER)
-fail:
-#endif
-	/* TODO: cleanup allocated resources(?) */
-	os_free(hapd);
-	return NULL;
-}
-
-
-/**
- * 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->config_fname = os_strdup(config_file);
-	if (hapd_iface->config_fname == NULL)
-		goto fail;
-
-	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;
-	}
-
-	return hapd_iface;
-
-fail:
-	if (conf)
-		hostapd_config_free(conf);
-	if (hapd_iface) {
-		for (i = 0; hapd_iface->bss && i < hapd_iface->num_bss; i++) {
-			hapd = hapd_iface->bss[i];
-			if (hapd && hapd->ssl_ctx)
-				tls_deinit(hapd->ssl_ctx);
-		}
-
-		os_free(hapd_iface->config_fname);
-		os_free(hapd_iface->bss);
-		os_free(hapd_iface);
-	}
-	return NULL;
-}
-
-
-int main(int argc, char *argv[])
-{
-	struct hapd_interfaces interfaces;
-	int ret = 1, k;
-	size_t i, j;
-	int c, debug = 0, daemonize = 0, tnc = 0;
-	char *pid_file = NULL;
-
-	hostapd_logger_register_cb(hostapd_logger_cb);
-
-	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();
-
-#ifdef EAP_SERVER
-	if (eap_server_register_methods()) {
-		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
-		return -1;
-	}
-#endif /* EAP_SERVER */
-
-	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 (eloop_init(&interfaces)) {
-		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
-		return -1;
-	}
-
-#ifndef CONFIG_NATIVE_WINDOWS
-	eloop_register_signal(SIGHUP, handle_reload, NULL);
-	eloop_register_signal(SIGUSR1, handle_dump_state, NULL);
-#endif /* CONFIG_NATIVE_WINDOWS */
-	eloop_register_signal_terminate(handle_term, NULL);
-
-	/* Initialize interfaces */
-	for (i = 0; i < interfaces.count; i++) {
-		wpa_printf(MSG_ERROR, "Configuration file: %s",
-			   argv[optind + i]);
-		interfaces.iface[i] = hostapd_init(argv[optind + i]);
-		if (!interfaces.iface[i])
-			goto out;
-		for (k = 0; k < debug; k++) {
-			if (interfaces.iface[i]->bss[0]->conf->
-			    logger_stdout_level > 0)
-				interfaces.iface[i]->bss[0]->conf->
-					logger_stdout_level--;
-		}
-
-		ret = hostapd_setup_interface(interfaces.iface[i]);
-		if (ret)
-			goto out;
-
-		for (k = 0; k < (int) interfaces.iface[i]->num_bss; k++) {
-			if (interfaces.iface[i]->bss[0]->conf->tnc)
-				tnc++;
-		}
-	}
-
-#ifdef EAP_TNC
-	if (tnc && tncs_global_init() < 0) {
-		wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
-		goto out;
-	}
-#endif /* EAP_TNC */
-
-	if (daemonize && os_daemonize(pid_file)) {
-		perror("daemon");
-		goto out;
-	}
-
-#ifndef CONFIG_NATIVE_WINDOWS
-	openlog("hostapd", 0, LOG_DAEMON);
-#endif /* CONFIG_NATIVE_WINDOWS */
-
-	eloop_run();
-
-	/* Disconnect associated stations from all interfaces and BSSes */
-	for (i = 0; i < interfaces.count; i++) {
-		for (j = 0; j < interfaces.iface[i]->num_bss; j++) {
-			struct hostapd_data *hapd =
-				interfaces.iface[i]->bss[j];
-			hostapd_free_stas(hapd);
-			hostapd_flush_old_stations(hapd);
-		}
-	}
-
-	ret = 0;
-
- out:
-	/* Deinitialize all interfaces */
-	for (i = 0; i < interfaces.count; i++) {
-		if (!interfaces.iface[i])
-			continue;
-		hostapd_cleanup_iface_pre(interfaces.iface[i]);
-		for (j = 0; j < interfaces.iface[i]->num_bss; j++) {
-			struct hostapd_data *hapd =
-				interfaces.iface[i]->bss[j];
-			hostapd_cleanup(hapd);
-			if (j == interfaces.iface[i]->num_bss - 1 &&
-			    hapd->driver)
-				hostapd_driver_deinit(hapd);
-		}
-		for (j = 0; j < interfaces.iface[i]->num_bss; j++)
-			os_free(interfaces.iface[i]->bss[j]);
-		hostapd_cleanup_iface(interfaces.iface[i]);
-	}
-	os_free(interfaces.iface);
-
-#ifdef EAP_TNC
-	tncs_global_deinit();
-#endif /* EAP_TNC */
-
-	eloop_destroy();
-
-#ifndef CONFIG_NATIVE_WINDOWS
-	closelog();
-#endif /* CONFIG_NATIVE_WINDOWS */
-
-#ifdef EAP_SERVER
-	eap_server_unregister_methods();
-#endif /* EAP_SERVER */
-
-	os_daemonize_terminate(pid_file);
-	os_free(pid_file);
-
-	return ret;
-}
diff --git a/contrib/wpa/hostapd/hostapd.conf b/contrib/wpa/hostapd/hostapd.conf
index 703b6469b0b8..b44a81868c83 100644
--- a/contrib/wpa/hostapd/hostapd.conf
+++ b/contrib/wpa/hostapd/hostapd.conf
@@ -5,12 +5,20 @@
 # management frames); ath0 for madwifi
 interface=wlan0
 
-# In case of madwifi and nl80211 driver interfaces, an additional configuration
-# parameter, bridge, must be used to notify hostapd if the interface is
-# included in a bridge. This parameter is not used with Host AP driver.
+# 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/prism54/test/none/nl80211/bsd);
+# 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.
@@ -275,6 +283,10 @@ ignore_broadcast_ssid=0
 #
 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
@@ -342,34 +354,16 @@ wmm_ac_vo_acm=0
 # default: 300 (i.e., 5 minutes)
 #ap_max_inactivity=300
 
-# Enable/disable internal bridge for packets between associated stations.
-#
-# When IEEE 802.11 is used in managed mode, packets are usually send through
-# the AP even if they are from a wireless station to another wireless station.
-# This functionality requires that the AP has a bridge functionality that sends
-# frames back to the same interface if their destination is another associated
-# station. In addition, broadcast/multicast frames from wireless stations will
-# be sent both to the host system net stack (e.g., to eventually wired network)
-# and back to the wireless interface.
-#
-# The internal bridge is implemented within the wireless kernel module and it
-# bypasses kernel filtering (netfilter/iptables/ebtables). If direct
-# communication between the stations needs to be prevented, the internal
-# bridge can be disabled by setting bridge_packets=0.
-#
-# Note: If this variable is not included in hostapd.conf, hostapd does not
-# change the configuration and iwpriv can be used to set the value with
-# 'iwpriv wlan# param 10 0' command. If the variable is in hostapd.conf,
-# hostapd will override possible iwpriv configuration whenever configuration
-# file is reloaded.
-#
-# default: do not control from hostapd (80211.o defaults to 1=enabled)
-#bridge_packets=1
-
 # Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to
 # remain asleep). Default: 65535 (no limit apart from field size)
 #max_listen_interval=100
 
+# WDS (4-address frame) mode with per-station virtual interfaces
+# (only supported with driver=nl80211)
+# This mode allows associated stations to use 4-address frames to allow layer 2
+# bridging to be used.
+#wds_sta=1
+
 ##### IEEE 802.11n related configuration ######################################
 
 # ieee80211n: Whether IEEE 802.11n (HT) is enabled
@@ -392,6 +386,10 @@ wmm_ac_vo_acm=0
 #	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)
@@ -522,9 +520,9 @@ eap_server=0
 # 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 required A-ID to be
+# 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 provided interoperability with deployed peer implementation. This
+# field to provid interoperability with deployed peer implementations. This
 # field is configured in hex format.
 #eap_fast_a_id=101112131415161718191a1b1c1d1e1f
 
@@ -808,7 +806,7 @@ own_ip_addr=127.0.0.1
 # And so on.. One line per R0KH.
 
 # List of R1KHs in the same Mobility Domain
-# format:   <128-bit key as hex string>
+# format:   <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.
@@ -821,27 +819,11 @@ own_ip_addr=127.0.0.1
 # 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived
 #pmk_r1_push=1
 
-##### Passive scanning ########################################################
-# Scan different channels every N seconds. 0 = disable passive scanning.
-#passive_scan_interval=60
-
-# Listen N usecs on each channel when doing passive scanning.
-# This value plus the time needed for changing channels should be less than
-# 32 milliseconds (i.e. 32000 usec) to avoid interruptions to normal
-# operations. Time needed for channel changing varies based on the used wlan
-# hardware.
-# default: disabled (0)
-#passive_scan_listen=10000
-
-# Passive scanning mode:
-# 0 = scan all supported modes (802.11a/b/g/Turbo) (default)
-# 1 = scan only the mode that is currently used for normal operations
-#passive_scan_mode=1
-
-# Maximum number of entries kept in AP table (either for passive scanning or
-# for detecting Overlapping Legacy BSS Condition). The oldest entry will be
+##### 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! Wi-Fi certification for IEEE 802.11g requires that OLBC is
+# 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
@@ -927,11 +909,17 @@ own_ip_addr=127.0.0.1
 
 # 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
 
-# Access point PIN for initial configuration and adding Registrars
+# 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.
+# 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
@@ -1002,7 +990,10 @@ own_ip_addr=127.0.0.1
 # 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 ).
+# hostapd (ifconfig wlan0 hw ether ). 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.
diff --git a/contrib/wpa/hostapd/hostapd.h b/contrib/wpa/hostapd/hostapd.h
deleted file mode 100644
index 26f30d7016ff..000000000000
--- a/contrib/wpa/hostapd/hostapd.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * hostapd / Initialization and configuration
- * Host AP kernel driver
- * Copyright (c) 2002-2008, Jouni Malinen 
- * Copyright (c) 2007-2008, Intel Corporation
- *
- * 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 HOSTAPD_H
-#define HOSTAPD_H
-
-#include "common.h"
-#include "ap.h"
-
-#ifndef ETH_ALEN
-#define ETH_ALEN 6
-#endif
-#ifndef IFNAMSIZ
-#define IFNAMSIZ 16
-#endif
-#ifndef ETH_P_ALL
-#define ETH_P_ALL 0x0003
-#endif
-#ifndef ETH_P_PAE
-#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
-#endif /* ETH_P_PAE */
-#ifndef ETH_P_EAPOL
-#define ETH_P_EAPOL ETH_P_PAE
-#endif /* ETH_P_EAPOL */
-
-#ifndef ETH_P_RRB
-#define ETH_P_RRB 0x890D
-#endif /* ETH_P_RRB */
-
-#include "config.h"
-
-#ifdef _MSC_VER
-#pragma pack(push, 1)
-#endif /* _MSC_VER */
-
-#define MAX_VLAN_ID 4094
-
-struct ieee8023_hdr {
-	u8 dest[6];
-	u8 src[6];
-	u16 ethertype;
-} STRUCT_PACKED;
-
-
-struct ieee80211_hdr {
-	le16 frame_control;
-	le16 duration_id;
-	u8 addr1[6];
-	u8 addr2[6];
-	u8 addr3[6];
-	le16 seq_ctrl;
-	/* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame
-	 */
-} STRUCT_PACKED;
-
-#ifdef _MSC_VER
-#pragma pack(pop)
-#endif /* _MSC_VER */
-
-#define IEEE80211_DA_FROMDS addr1
-#define IEEE80211_BSSID_FROMDS addr2
-#define IEEE80211_SA_FROMDS addr3
-
-#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))
-
-#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
-
-/* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X
- * frames that might be longer than normal default MTU and they are not
- * fragmented */
-#define HOSTAPD_MTU 2290
-
-extern unsigned char rfc1042_header[6];
-
-struct hostap_sta_driver_data {
-	unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes;
-	unsigned long current_tx_rate;
-	unsigned long inactive_msec;
-	unsigned long flags;
-	unsigned long num_ps_buf_frames;
-	unsigned long tx_retry_failed;
-	unsigned long tx_retry_count;
-	int last_rssi;
-	int last_ack_rssi;
-};
-
-struct wpa_driver_ops;
-struct wpa_ctrl_dst;
-struct radius_server_data;
-struct upnp_wps_device_sm;
-
-#ifdef CONFIG_FULL_DYNAMIC_VLAN
-struct full_dynamic_vlan;
-#endif /* CONFIG_FULL_DYNAMIC_VLAN */
-
-/**
- * struct hostapd_data - hostapd per-BSS data structure
- */
-struct hostapd_data {
-	struct hostapd_iface *iface;
-	struct hostapd_config *iconf;
-	struct hostapd_bss_config *conf;
-	int interface_added; /* virtual interface added for this BSS */
-
-	u8 own_addr[ETH_ALEN];
-
-	int num_sta; /* number of entries in sta_list */
-	struct sta_info *sta_list; /* STA info list head */
-	struct sta_info *sta_hash[STA_HASH_SIZE];
-
-	/* pointers to STA info; based on allocated AID or NULL if AID free
-	 * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1
-	 * and so on
-	 */
-	struct sta_info *sta_aid[MAX_AID_TABLE_SIZE];
-
-	const struct wpa_driver_ops *driver;
-	void *drv_priv;
-
-	u8 *default_wep_key;
-	u8 default_wep_key_idx;
-
-	struct radius_client_data *radius;
-	int radius_client_reconfigured;
-	u32 acct_session_id_hi, acct_session_id_lo;
-
-	struct iapp_data *iapp;
-
-	struct hostapd_cached_radius_acl *acl_cache;
-	struct hostapd_acl_query_data *acl_queries;
-
-	struct wpa_authenticator *wpa_auth;
-	struct eapol_authenticator *eapol_auth;
-
-	struct rsn_preauth_interface *preauth_iface;
-	time_t michael_mic_failure;
-	int michael_mic_failures;
-	int tkip_countermeasures;
-
-	int ctrl_sock;
-	struct wpa_ctrl_dst *ctrl_dst;
-
-	void *ssl_ctx;
-	void *eap_sim_db_priv;
-	struct radius_server_data *radius_srv;
-
-	int parameter_set_count;
-
-#ifdef CONFIG_FULL_DYNAMIC_VLAN
-	struct full_dynamic_vlan *full_dynamic_vlan;
-#endif /* CONFIG_FULL_DYNAMIC_VLAN */
-
-	struct l2_packet_data *l2;
-	struct wps_context *wps;
-
-#ifdef CONFIG_WPS
-	u8 *wps_beacon_ie;
-	size_t wps_beacon_ie_len;
-	u8 *wps_probe_resp_ie;
-	size_t wps_probe_resp_ie_len;
-	unsigned int ap_pin_failures;
-	struct upnp_wps_device_sm *wps_upnp;
-#endif /* CONFIG_WPS */
-};
-
-
-/**
- * struct hostapd_iface - hostapd per-interface data structure
- */
-struct hostapd_iface {
-	char *config_fname;
-	struct hostapd_config *conf;
-
-	size_t num_bss;
-	struct hostapd_data **bss;
-
-	int num_ap; /* number of entries in ap_list */
-	struct ap_info *ap_list; /* AP info list head */
-	struct ap_info *ap_hash[STA_HASH_SIZE];
-	struct ap_info *ap_iter_list;
-
-	struct hostapd_hw_modes *hw_features;
-	int num_hw_features;
-	struct hostapd_hw_modes *current_mode;
-	/* Rates that are currently used (i.e., filtered copy of
-	 * current_mode->channels */
-	int num_rates;
-	struct hostapd_rate_data *current_rates;
-
-	u16 hw_flags;
-
-	/* Number of associated Non-ERP stations (i.e., stations using 802.11b
-	 * in 802.11g BSS) */
-	int num_sta_non_erp;
-
-	/* Number of associated stations that do not support Short Slot Time */
-	int num_sta_no_short_slot_time;
-
-	/* Number of associated stations that do not support Short Preamble */
-	int num_sta_no_short_preamble;
-
-	int olbc; /* Overlapping Legacy BSS Condition */
-
-	/* Number of HT associated stations that do not support greenfield */
-	int num_sta_ht_no_gf;
-
-	/* Number of associated non-HT stations */
-	int num_sta_no_ht;
-
-	/* Number of HT associated stations 20 MHz */
-	int num_sta_ht_20mhz;
-
-	/* Overlapping BSS information */
-	int olbc_ht;
-
-#ifdef CONFIG_IEEE80211N
-	u16 ht_op_mode;
-#endif /* CONFIG_IEEE80211N */
-};
-
-void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
-			   int reassoc);
-int hostapd_reload_config(struct hostapd_iface *iface);
-
-#endif /* HOSTAPD_H */
diff --git a/contrib/wpa/hostapd/hostapd_cli.1 b/contrib/wpa/hostapd/hostapd_cli.1
index 2fe49071a2e3..218ea1588a4a 100644
--- a/contrib/wpa/hostapd/hostapd_cli.1
+++ b/contrib/wpa/hostapd/hostapd_cli.1
@@ -3,7 +3,7 @@
 hostapd_cli \- hostapd command-line interface
 .SH SYNOPSIS
 .B hostapd_cli
-[\-p] [\-i] [\-hv] [command..]
+[\-p] [\-i] [\-a] [\-hvB] [command..]
 .SH DESCRIPTION
 This manual page documents briefly the
 .B hostapd_cli
@@ -38,6 +38,12 @@ Interface to listen on.
 
 Default: first interface found in socket path.
 .TP
+.B \-a
+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
diff --git a/contrib/wpa/hostapd/hostapd_cli.c b/contrib/wpa/hostapd/hostapd_cli.c
index c2ecd4e23cae..589530e419fc 100644
--- a/contrib/wpa/hostapd/hostapd_cli.c
+++ b/contrib/wpa/hostapd/hostapd_cli.c
@@ -1,6 +1,6 @@
 /*
  * hostapd - command line interface for hostapd daemon
- * Copyright (c) 2004-2009, Jouni Malinen 
+ * Copyright (c) 2004-2010, Jouni Malinen 
  *
  * 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
@@ -15,14 +15,14 @@
 #include "includes.h"
 #include 
 
-#include "wpa_ctrl.h"
+#include "common/wpa_ctrl.h"
 #include "common.h"
-#include "version.h"
+#include "common/version.h"
 
 
 static const char *hostapd_cli_version =
 "hostapd_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2009, Jouni Malinen  and contributors";
+"Copyright (c) 2004-2010, Jouni Malinen  and contributors";
 
 
 static const char *hostapd_cli_license =
@@ -83,12 +83,18 @@ static const char *commands_help =
 "   sta            get MIB variables for one station\n"
 "   all_sta              get MIB variables for all stations\n"
 "   new_sta        add a new station\n"
+"   deauthenticate   deauthenticate a station\n"
+"   disassociate   disassociate a station\n"
 #ifdef CONFIG_IEEE80211W
 "   sa_query       send SA Query to a station\n"
 #endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_WPS
 "   wps_pin   [timeout]  add WPS Enrollee PIN (Device Password)\n"
 "   wps_pbc              indicate button pushed to initiate PBC\n"
+#ifdef CONFIG_WPS_OOB
+"   wps_oob     use WPS with out-of-band (UFD)\n"
+#endif /* CONFIG_WPS_OOB */
+"   wps_ap_pin  [params..]  enable/disable AP PIN\n"
 #endif /* CONFIG_WPS */
 "   help                 show this usage help\n"
 "   interface [ifname]   show interfaces/select interface\n"
@@ -101,23 +107,29 @@ 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] [-i] [-hv] "
-		"[-G] \\\n"
-		"        [command..]\n"
+	fprintf(stderr,
+		"\n"
+		"usage: hostapd_cli [-p] [-i] [-hvB] "
+		"[-a] \\\n"
+		"                   [-G] [command..]\n"
 		"\n"
 		"Options:\n"
 		"   -h           help (show this usage text)\n"
 		"   -v           shown version information\n"
 		"   -p     path to find control sockets (default: "
 		"/var/run/hostapd)\n"
+		"   -a     run in daemon mode executing the action file "
+		"based on events\n"
+		"                from hostapd\n"
+		"   -B           run a daemon in the background\n"
 		"   -i   Interface to listen on (default: first "
 		"interface found in the\n"
 		"                socket path)\n\n"
@@ -212,6 +224,51 @@ static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
+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];
@@ -239,6 +296,42 @@ static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
 }
 
 
+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[])
@@ -279,6 +372,61 @@ static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
 {
 	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 */
 
 
@@ -430,12 +578,18 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
 	{ "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 },
@@ -480,7 +634,8 @@ static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
 }
 
 
-static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read)
+static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
+				     int action_monitor)
 {
 	int first = 1;
 	if (ctrl_conn == NULL)
@@ -490,10 +645,14 @@ static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read)
 		size_t len = sizeof(buf) - 1;
 		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
 			buf[len] = '\0';
-			if (in_read && first)
-				printf("\n");
-			first = 0;
-			printf("%s\n", buf);
+			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;
@@ -511,7 +670,7 @@ static void hostapd_cli_interactive(void)
 	printf("\nInteractive mode\n\n");
 
 	do {
-		hostapd_cli_recv_pending(ctrl_conn, 0);
+		hostapd_cli_recv_pending(ctrl_conn, 0, 0);
 		printf("> ");
 		alarm(ping_interval);
 		res = fgets(cmd, sizeof(cmd), stdin);
@@ -548,9 +707,19 @@ static void hostapd_cli_interactive(void)
 }
 
 
-static void hostapd_cli_terminate(int sig)
+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);
 }
 
@@ -574,22 +743,69 @@ static void hostapd_cli_alarm(int sig)
 		}
 	}
 	if (ctrl_conn)
-		hostapd_cli_recv_pending(ctrl_conn, 1);
+		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, "hG:i:p:v");
+		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;
@@ -600,8 +816,8 @@ int main(int argc, char *argv[])
 			printf("%s\n", hostapd_cli_version);
 			return 0;
 		case 'i':
-			free(ctrl_ifname);
-			ctrl_ifname = strdup(optarg);
+			os_free(ctrl_ifname);
+			ctrl_ifname = os_strdup(optarg);
 			break;
 		case 'p':
 			ctrl_iface_dir = optarg;
@@ -612,7 +828,7 @@ int main(int argc, char *argv[])
 		}
 	}
 
-	interactive = argc == optind;
+	interactive = (argc == optind) && (action_file == NULL);
 
 	if (interactive) {
 		printf("%s\n\n%s\n\n", hostapd_cli_version,
@@ -625,12 +841,13 @@ int main(int argc, char *argv[])
 			DIR *dir = opendir(ctrl_iface_dir);
 			if (dir) {
 				while ((dent = readdir(dir))) {
-					if (strcmp(dent->d_name, ".") == 0 ||
-					    strcmp(dent->d_name, "..") == 0)
+					if (os_strcmp(dent->d_name, ".") == 0
+					    ||
+					    os_strcmp(dent->d_name, "..") == 0)
 						continue;
 					printf("Selected interface '%s'\n",
 					       dent->d_name);
-					ctrl_ifname = strdup(dent->d_name);
+					ctrl_ifname = os_strdup(dent->d_name);
 					break;
 				}
 				closedir(dir);
@@ -653,7 +870,7 @@ int main(int argc, char *argv[])
 			printf("Could not connect to hostapd - re-trying\n");
 			warning_displayed = 1;
 		}
-		sleep(1);
+		os_sleep(1, 0);
 		continue;
 	}
 
@@ -661,17 +878,27 @@ int main(int argc, char *argv[])
 	signal(SIGTERM, hostapd_cli_terminate);
 	signal(SIGALRM, hostapd_cli_alarm);
 
-	if (interactive) {
+	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
+	else if (action_file)
+		hostapd_cli_action(ctrl_conn);
+	else
 		wpa_request(ctrl_conn, argc - optind, &argv[optind]);
 
-	free(ctrl_ifname);
-	hostapd_cli_close_connection();
+	os_free(ctrl_ifname);
+	hostapd_cli_cleanup();
 	return 0;
 }
diff --git a/contrib/wpa/hostapd/main.c b/contrib/wpa/hostapd/main.c
new file mode 100644
index 000000000000..9c532d4cce6e
--- /dev/null
+++ b/contrib/wpa/hostapd/main.c
@@ -0,0 +1,565 @@
+/*
+ * hostapd / main()
+ * Copyright (c) 2002-2010, Jouni Malinen 
+ *
+ * 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 
+#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(¶ms, 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, ¶ms);
+	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  "
+		"and contributors\n");
+}
+
+
+static void usage(void)
+{
+	show_version();
+	fprintf(stderr,
+		"\n"
+		"usage: hostapd [-hdBKtv] [-P ] "
+		"\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/contrib/wpa/hostapd/nt_password_hash.c b/contrib/wpa/hostapd/nt_password_hash.c
index 9df307d54a84..839802a744c5 100644
--- a/contrib/wpa/hostapd/nt_password_hash.c
+++ b/contrib/wpa/hostapd/nt_password_hash.c
@@ -15,7 +15,7 @@
 #include "includes.h"
 
 #include "common.h"
-#include "ms_funcs.h"
+#include "crypto/ms_funcs.h"
 
 
 int main(int argc, char *argv[])
@@ -43,7 +43,8 @@ int main(int argc, char *argv[])
 		password = buf;
 	}
 
-	nt_password_hash((u8 *) password, strlen(password), password_hash);
+	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");
diff --git a/contrib/wpa/hostapd/radiotap.h b/contrib/wpa/hostapd/radiotap.h
deleted file mode 100644
index 508264c4cf33..000000000000
--- a/contrib/wpa/hostapd/radiotap.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
-/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */
-
-/*-
- * Copyright (c) 2003, 2004 David Young.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of David Young may not be used to endorse or promote
- *    products derived from this software without specific prior
- *    written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``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 DAVID
- * YOUNG 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.
- */
-
-/*
- * Modifications to fit into the linux IEEE 802.11 stack,
- * Mike Kershaw (dragorn@kismetwireless.net)
- */
-
-#ifndef IEEE80211RADIOTAP_H
-#define IEEE80211RADIOTAP_H
-
-#include 
-
-/* Base version of the radiotap packet header data */
-#define PKTHDR_RADIOTAP_VERSION		0
-
-/* A generic radio capture format is desirable. There is one for
- * Linux, but it is neither rigidly defined (there were not even
- * units given for some fields) nor easily extensible.
- *
- * I suggest the following extensible radio capture format. It is
- * based on a bitmap indicating which fields are present.
- *
- * I am trying to describe precisely what the application programmer
- * should expect in the following, and for that reason I tell the
- * units and origin of each measurement (where it applies), or else I
- * use sufficiently weaselly language ("is a monotonically nondecreasing
- * function of...") that I cannot set false expectations for lawyerly
- * readers.
- */
-
-/* The radio capture header precedes the 802.11 header.
- * All data in the header is little endian on all platforms.
- */
-struct ieee80211_radiotap_header {
-	uint8_t it_version;	/* Version 0. Only increases
-				 * for drastic changes,
-				 * introduction of compatible
-				 * new fields does not count.
-				 */
-	uint8_t it_pad;
-	uint16_t it_len;	/* length of the whole
-				 * header in bytes, including
-				 * it_version, it_pad,
-				 * it_len, and data fields.
-				 */
-	uint32_t it_present;	/* A bitmap telling which
-				 * fields are present. Set bit 31
-				 * (0x80000000) to extend the
-				 * bitmap by another 32 bits.
-				 * Additional extensions are made
-				 * by setting bit 31.
-				 */
-};
-
-/* Name                                 Data type    Units
- * ----                                 ---------    -----
- *
- * IEEE80211_RADIOTAP_TSFT              __le64       microseconds
- *
- *      Value in microseconds of the MAC's 64-bit 802.11 Time
- *      Synchronization Function timer when the first bit of the
- *      MPDU arrived at the MAC. For received frames, only.
- *
- * IEEE80211_RADIOTAP_CHANNEL           2 x uint16_t   MHz, bitmap
- *
- *      Tx/Rx frequency in MHz, followed by flags (see below).
- *
- * IEEE80211_RADIOTAP_FHSS              uint16_t       see below
- *
- *      For frequency-hopping radios, the hop set (first byte)
- *      and pattern (second byte).
- *
- * IEEE80211_RADIOTAP_RATE              u8           500kb/s
- *
- *      Tx/Rx data rate
- *
- * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     s8           decibels from
- *                                                   one milliwatt (dBm)
- *
- *      RF signal power at the antenna, decibel difference from
- *      one milliwatt.
- *
- * IEEE80211_RADIOTAP_DBM_ANTNOISE      s8           decibels from
- *                                                   one milliwatt (dBm)
- *
- *      RF noise power at the antenna, decibel difference from one
- *      milliwatt.
- *
- * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u8           decibel (dB)
- *
- *      RF signal power at the antenna, decibel difference from an
- *      arbitrary, fixed reference.
- *
- * IEEE80211_RADIOTAP_DB_ANTNOISE       u8           decibel (dB)
- *
- *      RF noise power at the antenna, decibel difference from an
- *      arbitrary, fixed reference point.
- *
- * IEEE80211_RADIOTAP_LOCK_QUALITY      uint16_t       unitless
- *
- *      Quality of Barker code lock. Unitless. Monotonically
- *      nondecreasing with "better" lock strength. Called "Signal
- *      Quality" in datasheets.  (Is there a standard way to measure
- *      this?)
- *
- * IEEE80211_RADIOTAP_TX_ATTENUATION    uint16_t       unitless
- *
- *      Transmit power expressed as unitless distance from max
- *      power set at factory calibration.  0 is max power.
- *      Monotonically nondecreasing with lower power levels.
- *
- * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t       decibels (dB)
- *
- *      Transmit power expressed as decibel distance from max power
- *      set at factory calibration.  0 is max power.  Monotonically
- *      nondecreasing with lower power levels.
- *
- * IEEE80211_RADIOTAP_DBM_TX_POWER      s8           decibels from
- *                                                   one milliwatt (dBm)
- *
- *      Transmit power expressed as dBm (decibels from a 1 milliwatt
- *      reference). This is the absolute power level measured at
- *      the antenna port.
- *
- * IEEE80211_RADIOTAP_FLAGS             u8           bitmap
- *
- *      Properties of transmitted and received frames. See flags
- *      defined below.
- *
- * IEEE80211_RADIOTAP_ANTENNA           u8           antenna index
- *
- *      Unitless indication of the Rx/Tx antenna for this packet.
- *      The first antenna is antenna 0.
- *
- * IEEE80211_RADIOTAP_RX_FLAGS          uint16_t       bitmap
- *
- *     Properties of received frames. See flags defined below.
- *
- * IEEE80211_RADIOTAP_TX_FLAGS          uint16_t       bitmap
- *
- *     Properties of transmitted frames. See flags defined below.
- *
- * IEEE80211_RADIOTAP_RTS_RETRIES       u8           data
- *
- *     Number of rts retries a transmitted frame used.
- *
- * IEEE80211_RADIOTAP_DATA_RETRIES      u8           data
- *
- *     Number of unicast retries a transmitted frame used.
- *
- */
-enum ieee80211_radiotap_type {
-	IEEE80211_RADIOTAP_TSFT = 0,
-	IEEE80211_RADIOTAP_FLAGS = 1,
-	IEEE80211_RADIOTAP_RATE = 2,
-	IEEE80211_RADIOTAP_CHANNEL = 3,
-	IEEE80211_RADIOTAP_FHSS = 4,
-	IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
-	IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
-	IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
-	IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
-	IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
-	IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
-	IEEE80211_RADIOTAP_ANTENNA = 11,
-	IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
-	IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
-	IEEE80211_RADIOTAP_RX_FLAGS = 14,
-	IEEE80211_RADIOTAP_TX_FLAGS = 15,
-	IEEE80211_RADIOTAP_RTS_RETRIES = 16,
-	IEEE80211_RADIOTAP_DATA_RETRIES = 17,
-	IEEE80211_RADIOTAP_EXT = 31
-};
-
-/* Channel flags. */
-#define	IEEE80211_CHAN_TURBO	0x0010	/* Turbo channel */
-#define	IEEE80211_CHAN_CCK	0x0020	/* CCK channel */
-#define	IEEE80211_CHAN_OFDM	0x0040	/* OFDM channel */
-#define	IEEE80211_CHAN_2GHZ	0x0080	/* 2 GHz spectrum channel. */
-#define	IEEE80211_CHAN_5GHZ	0x0100	/* 5 GHz spectrum channel */
-#define	IEEE80211_CHAN_PASSIVE	0x0200	/* Only passive scan allowed */
-#define	IEEE80211_CHAN_DYN	0x0400	/* Dynamic CCK-OFDM channel */
-#define	IEEE80211_CHAN_GFSK	0x0800	/* GFSK channel (FHSS PHY) */
-
-/* For IEEE80211_RADIOTAP_FLAGS */
-#define	IEEE80211_RADIOTAP_F_CFP	0x01	/* sent/received
-						 * during CFP
-						 */
-#define	IEEE80211_RADIOTAP_F_SHORTPRE	0x02	/* sent/received
-						 * with short
-						 * preamble
-						 */
-#define	IEEE80211_RADIOTAP_F_WEP	0x04	/* sent/received
-						 * with WEP encryption
-						 */
-#define	IEEE80211_RADIOTAP_F_FRAG	0x08	/* sent/received
-						 * with fragmentation
-						 */
-#define	IEEE80211_RADIOTAP_F_FCS	0x10	/* frame includes FCS */
-#define	IEEE80211_RADIOTAP_F_DATAPAD	0x20	/* frame has padding between
-						 * 802.11 header and payload
-						 * (to 32-bit boundary)
-						 */
-/* For IEEE80211_RADIOTAP_RX_FLAGS */
-#define IEEE80211_RADIOTAP_F_RX_BADFCS	0x0001	/* frame failed crc check */
-
-/* For IEEE80211_RADIOTAP_TX_FLAGS */
-#define IEEE80211_RADIOTAP_F_TX_FAIL	0x0001	/* failed due to excessive
-						 * retries */
-#define IEEE80211_RADIOTAP_F_TX_CTS	0x0002	/* used cts 'protection' */
-#define IEEE80211_RADIOTAP_F_TX_RTS	0x0004	/* used rts/cts handshake */
-
-#endif				/* IEEE80211_RADIOTAP_H */
diff --git a/contrib/wpa/hostapd/sta_info.h b/contrib/wpa/hostapd/sta_info.h
deleted file mode 100644
index e83597092381..000000000000
--- a/contrib/wpa/hostapd/sta_info.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * hostapd / Station table
- * Copyright (c) 2002-2008, Jouni Malinen 
- *
- * 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 STA_INFO_H
-#define STA_INFO_H
-
-int ap_for_each_sta(struct hostapd_data *hapd,
-		    int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
-			      void *ctx),
-		    void *ctx);
-struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
-void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
-void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
-void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
-void hostapd_free_stas(struct hostapd_data *hapd);
-void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
-void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
-			    u32 session_timeout);
-void ap_sta_no_session_timeout(struct hostapd_data *hapd,
-			       struct sta_info *sta);
-struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr);
-void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
-			 u16 reason);
-void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
-			   u16 reason);
-int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
-		     int old_vlanid);
-void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
-void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
-int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
-
-#endif /* STA_INFO_H */
diff --git a/contrib/wpa/hostapd/wme.h b/contrib/wpa/hostapd/wme.h
deleted file mode 100644
index 9bc48cb84950..000000000000
--- a/contrib/wpa/hostapd/wme.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * hostapd / WMM (Wi-Fi Multimedia)
- * Copyright 2002-2003, Instant802 Networks, Inc.
- * Copyright 2005-2006, Devicescape Software, Inc.
- *
- * 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 WME_H
-#define WME_H
-
-/*
- * WMM Information Element (used in (Re)Association Request frames; may also be
- * used in Beacon frames)
- */
-struct wmm_information_element {
-	/* Element ID: 221 (0xdd); Length: 7 */
-	/* required fields for WMM version 1 */
-	u8 oui[3]; /* 00:50:f2 */
-	u8 oui_type; /* 2 */
-	u8 oui_subtype; /* 0 */
-	u8 version; /* 1 for WMM version 1.0 */
-	u8 qos_info; /* AP/STA specific QoS info */
-};
-
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
-#include 
-#include 
-#endif /* defined(__FreeBSD__) || defined(__NetBSD__) ||
-	* defined(__DragonFly__) */
-
-
-static inline u16 tsinfo(int tag1d, int contention_based, int direction)
-{
-	return (tag1d << 11) | (contention_based << 7) | (direction << 5) |
-	  (tag1d << 1);
-}
-
-
-struct wme_information_element {
-	/* required fields for WME version 1 */
-	u8 oui[3];
-	u8 oui_type;
-	u8 oui_subtype;
-	u8 version;
-	u8 acInfo;
-
-} __attribute__ ((packed));
-
-#define WMM_AC_AIFSN_MASK 0x0f
-#define WMM_AC_AIFNS_SHIFT 0
-#define WMM_AC_ACM 0x10
-#define WMM_AC_ACI_MASK 0x60
-#define WMM_AC_ACI_SHIFT 5
-
-#define WMM_AC_ECWMIN_MASK 0x0f
-#define WMM_AC_ECWMIN_SHIFT 0
-#define WMM_AC_ECWMAX_MASK 0xf0
-#define WMM_AC_ECWMAX_SHIFT 4
-
-struct wmm_ac_parameter {
-	u8 aci_aifsn; /* AIFSN, ACM, ACI */
-	u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
-	le16 txop_limit;
-} __attribute__ ((packed));
-
-/*
- * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association
- * Response frmaes)
- */
-struct wmm_parameter_element {
-	/* Element ID: 221 (0xdd); Length: 24 */
-	/* required fields for WMM version 1 */
-	u8 oui[3]; /* 00:50:f2 */
-	u8 oui_type; /* 2 */
-	u8 oui_subtype; /* 1 */
-	u8 version; /* 1 for WMM version 1.0 */
-	u8 qos_info; /* AP/STA specif QoS info */
-	u8 reserved; /* 0 */
-	struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
-
-} __attribute__ ((packed));
-
-/* WMM TSPEC Element */
-struct wmm_tspec_element {
-	u8 eid; /* 221 = 0xdd */
-	u8 length; /* 6 + 55 = 61 */
-	u8 oui[3]; /* 00:50:f2 */
-	u8 oui_type; /* 2 */
-	u8 oui_subtype; /* 2 */
-	u8 version; /* 1 */
-	/* WMM TSPEC body (55 octets): */
-	u8 ts_info[3];
-	le16 nominal_msdu_size;
-	le16 maximum_msdu_size;
-	le32 minimum_service_interval;
-	le32 maximum_service_interval;
-	le32 inactivity_interval;
-	le32 suspension_interval;
-	le32 service_start_time;
-	le32 minimum_data_rate;
-	le32 mean_data_rate;
-	le32 peak_data_rate;
-	le32 maximum_burst_size;
-	le32 delay_bound;
-	le32 minimum_phy_rate;
-	le16 surplus_bandwidth_allowance;
-	le16 medium_time;
-} __attribute__ ((packed));
-
-
-/* Access Categories / ACI to AC coding */
-enum {
-	WMM_AC_BE = 0 /* Best Effort */,
-	WMM_AC_BK = 1 /* Background */,
-	WMM_AC_VI = 2 /* Video */,
-	WMM_AC_VO = 3 /* Voice */
-};
-
-struct ieee80211_mgmt;
-
-u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid);
-int hostapd_eid_wmm_valid(struct hostapd_data *hapd, u8 *eid, size_t len);
-int hostapd_wmm_sta_config(struct hostapd_data *hapd, struct sta_info *sta);
-void hostapd_wmm_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
-			size_t len);
-
-#endif /* WME_H */
diff --git a/contrib/wpa/patches/openssl-0.9.8-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8-tls-extensions.patch
new file mode 100644
index 000000000000..44490cca226e
--- /dev/null
+++ b/contrib/wpa/patches/openssl-0.9.8-tls-extensions.patch
@@ -0,0 +1,429 @@
+This patch is adding support for TLS hello extensions and externally
+generated pre-shared key material to OpenSSL 0.9.8. This is
+based on the patch from Alexey Kobozev 
+(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
+
+
+
+diff -uprN openssl-0.9.8.orig/include/openssl/ssl.h openssl-0.9.8/include/openssl/ssl.h
+--- openssl-0.9.8.orig/include/openssl/ssl.h	2005-06-10 12:51:16.000000000 -0700
++++ openssl-0.9.8/include/openssl/ssl.h	2005-07-19 20:02:15.000000000 -0700
+@@ -340,6 +340,7 @@ extern "C" {
+  * 'struct ssl_st *' function parameters used to prototype callbacks
+  * in SSL_CTX. */
+ typedef struct ssl_st *ssl_crock_st;
++typedef struct tls_extension_st TLS_EXTENSION;
+ 
+ /* used to hold info on the particular ciphers used */
+ typedef struct ssl_cipher_st
+@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
+ typedef struct ssl_st SSL;
+ typedef struct ssl_ctx_st SSL_CTX;
+ 
++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
++
+ /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+ typedef struct ssl_method_st
+ 	{
+@@ -968,6 +971,15 @@ struct ssl_st
+ 	int first_packet;
+ 	int client_version;	/* what was passed, used for
+ 				 * SSLv3/TLS rollback check */
++
++	/* TLS externsions */
++	TLS_EXTENSION *tls_extension;
++	int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
++	void *tls_extension_cb_arg;
++
++	/* TLS pre-shared secret session resumption */
++	tls_session_secret_cb_fn tls_session_secret_cb;
++	void *tls_session_secret_cb_arg;
+ 	};
+ 
+ #ifdef __cplusplus
+@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v
+ int SSL_COMP_add_compression_method(int id,void *cm);
+ #endif
+ 
++/* TLS extensions functions */
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
++
++/* Pre-shared secret session resumption functions */
++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
++
+ /* BEGIN ERROR CODES */
+ /* The following lines are auto generated by the script mkerr.pl. Any changes
+  * made after this point may be overwritten when the script is next run.
+@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_TLS1_ENC					 210
+ #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+ #define SSL_F_WRITE_PENDING				 212
++#define SSL_F_SSL_SET_HELLO_EXTENSION	 213
+ 
+ /* Reason codes. */
+ #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+diff -uprN openssl-0.9.8.orig/include/openssl/tls1.h openssl-0.9.8/include/openssl/tls1.h
+--- openssl-0.9.8.orig/include/openssl/tls1.h	2003-07-22 05:34:21.000000000 -0700
++++ openssl-0.9.8/include/openssl/tls1.h	2005-07-19 20:02:15.000000000 -0700
+@@ -282,6 +282,14 @@ extern "C" {
+ #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+ #endif
+ 
++/* TLS extension struct */
++struct tls_extension_st
++{
++	unsigned short type;
++	unsigned short length;
++	void *data;
++};
++
+ #ifdef  __cplusplus
+ }
+ #endif
+diff -uprN openssl-0.9.8.orig/ssl/Makefile openssl-0.9.8/ssl/Makefile
+--- openssl-0.9.8.orig/ssl/Makefile	2005-05-30 16:20:30.000000000 -0700
++++ openssl-0.9.8/ssl/Makefile	2005-07-19 20:02:15.000000000 -0700
+@@ -24,7 +24,7 @@ LIBSRC=	\
+ 	s2_meth.c   s2_srvr.c s2_clnt.c  s2_lib.c  s2_enc.c s2_pkt.c \
+ 	s3_meth.c   s3_srvr.c s3_clnt.c  s3_lib.c  s3_enc.c s3_pkt.c s3_both.c \
+ 	s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c          s23_pkt.c \
+-	t1_meth.c   t1_srvr.c t1_clnt.c  t1_lib.c  t1_enc.c \
++	t1_meth.c   t1_srvr.c t1_clnt.c  t1_lib.c  t1_enc.c                    t1_ext.c \
+ 	d1_meth.c   d1_srvr.c d1_clnt.c  d1_lib.c  d1_pkt.c \
+ 	d1_both.c d1_enc.c \
+ 	ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
+@@ -35,7 +35,7 @@ LIBOBJ= \
+ 	s2_meth.o  s2_srvr.o  s2_clnt.o  s2_lib.o  s2_enc.o s2_pkt.o \
+ 	s3_meth.o  s3_srvr.o  s3_clnt.o  s3_lib.o  s3_enc.o s3_pkt.o s3_both.o \
+ 	s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o          s23_pkt.o \
+-	t1_meth.o   t1_srvr.o t1_clnt.o  t1_lib.o  t1_enc.o \
++	t1_meth.o   t1_srvr.o t1_clnt.o  t1_lib.o  t1_enc.o                    t1_ext.o \
+ 	d1_meth.o   d1_srvr.o d1_clnt.o  d1_lib.o  d1_pkt.o \
+ 	d1_both.o d1_enc.o \
+ 	ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
+@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h ..
+ t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c
++t1_ext.o: t1_ext.c ssl_locl.h
+diff -uprN openssl-0.9.8.orig/ssl/s3_clnt.c openssl-0.9.8/ssl/s3_clnt.c
+--- openssl-0.9.8.orig/ssl/s3_clnt.c	2005-05-16 03:11:03.000000000 -0700
++++ openssl-0.9.8/ssl/s3_clnt.c	2005-07-19 20:02:15.000000000 -0700
+@@ -606,6 +606,20 @@ int ssl3_client_hello(SSL *s)
+ 			}
+ 		*(p++)=0; /* Add the NULL method */
+ 		
++		/* send client hello extensions if any */
++		if (s->version >= TLS1_VERSION && s->tls_extension)
++		{
++			// set the total extensions length
++			s2n(s->tls_extension->length + 4, p);
++
++			// put the extensions with type and length
++			s2n(s->tls_extension->type, p);
++			s2n(s->tls_extension->length, p);
++			
++			memcpy(p, s->tls_extension->data, s->tls_extension->length);
++			p+=s->tls_extension->length;
++		}
++
+ 		l=(p-d);
+ 		d=buf;
+ 		*(d++)=SSL3_MT_CLIENT_HELLO;
+@@ -628,7 +642,7 @@ int ssl3_get_server_hello(SSL *s)
+ 	STACK_OF(SSL_CIPHER) *sk;
+ 	SSL_CIPHER *c;
+ 	unsigned char *p,*d;
+-	int i,al,ok;
++	int i,al,ok,pre_shared;
+ 	unsigned int j;
+ 	long n;
+ 	SSL_COMP *comp;
+@@ -693,7 +707,24 @@ int ssl3_get_server_hello(SSL *s)
+ 		goto f_err;
+ 		}
+ 
+-	if (j != 0 && j == s->session->session_id_length
++	/* check if we want to resume the session based on external pre-shared secret */
++	pre_shared = 0;
++	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++	{
++		SSL_CIPHER *pref_cipher=NULL;
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
++			NULL, &pref_cipher, s->tls_session_secret_cb_arg))
++		{
++			s->hit=1;
++			s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
++			s->session->session_id_length = j;
++			memcpy(s->session->session_id, p, j);
++			pre_shared = 1;
++		}
++	}
++
++	if ((pre_shared || j != 0) && j == s->session->session_id_length
+ 	    && memcmp(p,s->session->session_id,j) == 0)
+ 	    {
+ 	    if(s->sid_ctx_length != s->session->sid_ctx_length
+diff -uprN openssl-0.9.8.orig/ssl/s3_srvr.c openssl-0.9.8/ssl/s3_srvr.c
+--- openssl-0.9.8.orig/ssl/s3_srvr.c	2005-05-22 17:32:55.000000000 -0700
++++ openssl-0.9.8/ssl/s3_srvr.c	2005-07-19 20:02:15.000000000 -0700
+@@ -955,6 +955,75 @@ int ssl3_get_client_hello(SSL *s)
+ 		}
+ #endif
+ 
++	/* Check for TLS client hello extension here */
++	if (p < (d+n) && s->version >= TLS1_VERSION)
++	{
++		if (s->tls_extension_cb)
++		{
++			TLS_EXTENSION tls_ext;
++			unsigned short ext_total_len;
++			
++			n2s(p, ext_total_len);
++			n2s(p, tls_ext.type);
++			n2s(p, tls_ext.length);
++
++			// sanity check in TLS extension len
++			if (tls_ext.length > (d+n) - p)
++			{
++				// just cut the lenth to packet border
++				tls_ext.length = (d+n) - p;
++			}
++
++			tls_ext.data = p;
++
++			// returns an alert code or 0
++			al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg);
++			if (al != 0)
++			{
++				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
++				goto f_err;
++			}
++		}
++	}
++
++	/* Check if we want to use external pre-shared secret for this handshake */
++	/* for not reused session only */
++	if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++	{
++		SSL_CIPHER *pref_cipher=NULL;
++
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, 
++			ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
++		{
++			s->hit=1;
++			s->session->ciphers=ciphers;
++			s->session->verify_result=X509_V_OK;
++			
++			ciphers=NULL;
++			
++			/* check if some cipher was preferred by call back */
++			pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
++			if (pref_cipher == NULL)
++				{
++				al=SSL_AD_HANDSHAKE_FAILURE;
++				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
++				goto f_err;
++				}
++
++			s->session->cipher=pref_cipher;
++
++			if (s->cipher_list)
++				sk_SSL_CIPHER_free(s->cipher_list);
++
++			if (s->cipher_list_by_id)
++				sk_SSL_CIPHER_free(s->cipher_list_by_id);
++
++			s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
++			s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
++		}
++	}
++
+ 	/* Given s->session->ciphers and SSL_get_ciphers, we must
+ 	 * pick a cipher */
+ 
+diff -uprN openssl-0.9.8.orig/ssl/ssl_err.c openssl-0.9.8/ssl/ssl_err.c
+--- openssl-0.9.8.orig/ssl/ssl_err.c	2005-06-10 12:51:16.000000000 -0700
++++ openssl-0.9.8/ssl/ssl_err.c	2005-07-19 20:02:15.000000000 -0700
+@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
+ {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
+ {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
+ {ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
++{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
+ {0,NULL}
+ 	};
+ 
+diff -uprN openssl-0.9.8.orig/ssl/ssl.h openssl-0.9.8/ssl/ssl.h
+--- openssl-0.9.8.orig/ssl/ssl.h	2005-06-10 12:51:16.000000000 -0700
++++ openssl-0.9.8/ssl/ssl.h	2005-07-19 20:02:15.000000000 -0700
+@@ -340,6 +340,7 @@ extern "C" {
+  * 'struct ssl_st *' function parameters used to prototype callbacks
+  * in SSL_CTX. */
+ typedef struct ssl_st *ssl_crock_st;
++typedef struct tls_extension_st TLS_EXTENSION;
+ 
+ /* used to hold info on the particular ciphers used */
+ typedef struct ssl_cipher_st
+@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
+ typedef struct ssl_st SSL;
+ typedef struct ssl_ctx_st SSL_CTX;
+ 
++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
++
+ /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+ typedef struct ssl_method_st
+ 	{
+@@ -968,6 +971,15 @@ struct ssl_st
+ 	int first_packet;
+ 	int client_version;	/* what was passed, used for
+ 				 * SSLv3/TLS rollback check */
++
++	/* TLS externsions */
++	TLS_EXTENSION *tls_extension;
++	int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
++	void *tls_extension_cb_arg;
++
++	/* TLS pre-shared secret session resumption */
++	tls_session_secret_cb_fn tls_session_secret_cb;
++	void *tls_session_secret_cb_arg;
+ 	};
+ 
+ #ifdef __cplusplus
+@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v
+ int SSL_COMP_add_compression_method(int id,void *cm);
+ #endif
+ 
++/* TLS extensions functions */
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
++
++/* Pre-shared secret session resumption functions */
++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
++
+ /* BEGIN ERROR CODES */
+ /* The following lines are auto generated by the script mkerr.pl. Any changes
+  * made after this point may be overwritten when the script is next run.
+@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_TLS1_ENC					 210
+ #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+ #define SSL_F_WRITE_PENDING				 212
++#define SSL_F_SSL_SET_HELLO_EXTENSION	 213
+ 
+ /* Reason codes. */
+ #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+diff -uprN openssl-0.9.8.orig/ssl/ssl_sess.c openssl-0.9.8/ssl/ssl_sess.c
+--- openssl-0.9.8.orig/ssl/ssl_sess.c	2005-04-29 13:10:06.000000000 -0700
++++ openssl-0.9.8/ssl/ssl_sess.c	2005-07-19 20:02:15.000000000 -0700
+@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX *
+ 	return(s->session_timeout);
+ 	}
+ 
++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, 
++	STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
++{
++	if (s == NULL) return(0);
++	s->tls_session_secret_cb = tls_session_secret_cb;
++	s->tls_session_secret_cb_arg = arg;
++	return(1);
++}
++
+ typedef struct timeout_param_st
+ 	{
+ 	SSL_CTX *ctx;
+diff -uprN openssl-0.9.8.orig/ssl/t1_ext.c openssl-0.9.8/ssl/t1_ext.c
+--- openssl-0.9.8.orig/ssl/t1_ext.c	1969-12-31 16:00:00.000000000 -0800
++++ openssl-0.9.8/ssl/t1_ext.c	2005-07-19 20:03:29.000000000 -0700
+@@ -0,0 +1,48 @@
++
++#include 
++#include "ssl_locl.h"
++
++
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
++{
++	if(s->version >= TLS1_VERSION)
++	{
++		if(s->tls_extension)
++		{
++			OPENSSL_free(s->tls_extension);
++			s->tls_extension = NULL;
++		}
++
++		if(ext_data)
++		{
++			s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
++			if(!s->tls_extension)
++			{
++				SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
++				return 0;
++			}
++
++			s->tls_extension->type = ext_type;
++			s->tls_extension->length = ext_len;
++			s->tls_extension->data = s->tls_extension + 1;
++			memcpy(s->tls_extension->data, ext_data, ext_len);
++		}
++
++		return 1;
++	}
++
++	return 0;
++}
++
++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg)
++{
++	if(s->version >= TLS1_VERSION)
++	{
++		s->tls_extension_cb = cb;
++		s->tls_extension_cb_arg = arg;
++
++		return 1;
++	}
++
++	return 0;
++}
+diff -uprN openssl-0.9.8.orig/ssl/t1_lib.c openssl-0.9.8/ssl/t1_lib.c
+--- openssl-0.9.8.orig/ssl/t1_lib.c	2005-04-26 09:02:40.000000000 -0700
++++ openssl-0.9.8/ssl/t1_lib.c	2005-07-19 20:02:15.000000000 -0700
+@@ -131,6 +131,10 @@ int tls1_new(SSL *s)
+ 
+ void tls1_free(SSL *s)
+ 	{
++	if(s->tls_extension)
++	{
++		OPENSSL_free(s->tls_extension);
++	}
+ 	ssl3_free(s);
+ 	}
+ 
+diff -uprN openssl-0.9.8.orig/ssl/tls1.h openssl-0.9.8/ssl/tls1.h
+--- openssl-0.9.8.orig/ssl/tls1.h	2003-07-22 05:34:21.000000000 -0700
++++ openssl-0.9.8/ssl/tls1.h	2005-07-19 20:02:15.000000000 -0700
+@@ -282,6 +282,14 @@ extern "C" {
+ #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+ #endif
+ 
++/* TLS extension struct */
++struct tls_extension_st
++{
++	unsigned short type;
++	unsigned short length;
++	void *data;
++};
++
+ #ifdef  __cplusplus
+ }
+ #endif
+diff -uprN openssl-0.9.8.orig/util/ssleay.num openssl-0.9.8/util/ssleay.num
+--- openssl-0.9.8.orig/util/ssleay.num	2005-05-08 17:22:02.000000000 -0700
++++ openssl-0.9.8/util/ssleay.num	2005-07-19 20:02:15.000000000 -0700
+@@ -226,3 +226,6 @@ DTLSv1_server_method                    
+ SSL_COMP_get_compression_methods        276	EXIST:!VMS:FUNCTION:COMP
+ SSL_COMP_get_compress_methods           276	EXIST:VMS:FUNCTION:COMP
+ SSL_SESSION_get_id                      277	EXIST::FUNCTION:
++SSL_set_hello_extension			278	EXIST::FUNCTION:
++SSL_set_hello_extension_cb		279	EXIST::FUNCTION:
++SSL_set_session_secret_cb		280	EXIST::FUNCTION:
diff --git a/contrib/wpa/patches/openssl-0.9.8d-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8d-tls-extensions.patch
new file mode 100644
index 000000000000..eec6db8a1341
--- /dev/null
+++ b/contrib/wpa/patches/openssl-0.9.8d-tls-extensions.patch
@@ -0,0 +1,429 @@
+This patch is adding support for TLS hello extensions and externally
+generated pre-shared key material to OpenSSL 0.9.8d. This is
+based on the patch from Alexey Kobozev 
+(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
+
+
+
+diff -uprN openssl-0.9.8d.orig/include/openssl/ssl.h openssl-0.9.8d/include/openssl/ssl.h
+--- openssl-0.9.8d.orig/include/openssl/ssl.h	2006-06-14 06:52:49.000000000 -0700
++++ openssl-0.9.8d/include/openssl/ssl.h	2006-12-10 08:20:02.000000000 -0800
+@@ -345,6 +345,7 @@ extern "C" {
+  * 'struct ssl_st *' function parameters used to prototype callbacks
+  * in SSL_CTX. */
+ typedef struct ssl_st *ssl_crock_st;
++typedef struct tls_extension_st TLS_EXTENSION;
+ 
+ /* used to hold info on the particular ciphers used */
+ typedef struct ssl_cipher_st
+@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
+ typedef struct ssl_st SSL;
+ typedef struct ssl_ctx_st SSL_CTX;
+ 
++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
++
+ /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+ typedef struct ssl_method_st
+ 	{
+@@ -973,6 +976,15 @@ struct ssl_st
+ 	int first_packet;
+ 	int client_version;	/* what was passed, used for
+ 				 * SSLv3/TLS rollback check */
++
++	/* TLS externsions */
++	TLS_EXTENSION *tls_extension;
++	int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
++	void *tls_extension_cb_arg;
++
++	/* TLS pre-shared secret session resumption */
++	tls_session_secret_cb_fn tls_session_secret_cb;
++	void *tls_session_secret_cb_arg;
+ 	};
+ 
+ #ifdef __cplusplus
+@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v
+ int SSL_COMP_add_compression_method(int id,void *cm);
+ #endif
+ 
++/* TLS extensions functions */
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
++
++/* Pre-shared secret session resumption functions */
++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
++
+ /* BEGIN ERROR CODES */
+ /* The following lines are auto generated by the script mkerr.pl. Any changes
+  * made after this point may be overwritten when the script is next run.
+@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_TLS1_ENC					 210
+ #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+ #define SSL_F_WRITE_PENDING				 212
++#define SSL_F_SSL_SET_HELLO_EXTENSION	 213
+ 
+ /* Reason codes. */
+ #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+diff -uprN openssl-0.9.8d.orig/include/openssl/tls1.h openssl-0.9.8d/include/openssl/tls1.h
+--- openssl-0.9.8d.orig/include/openssl/tls1.h	2006-06-14 10:52:01.000000000 -0700
++++ openssl-0.9.8d/include/openssl/tls1.h	2006-12-10 08:20:02.000000000 -0800
+@@ -296,6 +296,14 @@ extern "C" {
+ #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+ #endif
+ 
++/* TLS extension struct */
++struct tls_extension_st
++{
++	unsigned short type;
++	unsigned short length;
++	void *data;
++};
++
+ #ifdef  __cplusplus
+ }
+ #endif
+diff -uprN openssl-0.9.8d.orig/ssl/Makefile openssl-0.9.8d/ssl/Makefile
+--- openssl-0.9.8d.orig/ssl/Makefile	2006-02-03 17:49:35.000000000 -0800
++++ openssl-0.9.8d/ssl/Makefile	2006-12-10 08:20:02.000000000 -0800
+@@ -24,7 +24,7 @@ LIBSRC=	\
+ 	s2_meth.c   s2_srvr.c s2_clnt.c  s2_lib.c  s2_enc.c s2_pkt.c \
+ 	s3_meth.c   s3_srvr.c s3_clnt.c  s3_lib.c  s3_enc.c s3_pkt.c s3_both.c \
+ 	s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c          s23_pkt.c \
+-	t1_meth.c   t1_srvr.c t1_clnt.c  t1_lib.c  t1_enc.c \
++	t1_meth.c   t1_srvr.c t1_clnt.c  t1_lib.c  t1_enc.c                    t1_ext.c \
+ 	d1_meth.c   d1_srvr.c d1_clnt.c  d1_lib.c  d1_pkt.c \
+ 	d1_both.c d1_enc.c \
+ 	ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
+@@ -35,7 +35,7 @@ LIBOBJ= \
+ 	s2_meth.o  s2_srvr.o  s2_clnt.o  s2_lib.o  s2_enc.o s2_pkt.o \
+ 	s3_meth.o  s3_srvr.o  s3_clnt.o  s3_lib.o  s3_enc.o s3_pkt.o s3_both.o \
+ 	s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o          s23_pkt.o \
+-	t1_meth.o   t1_srvr.o t1_clnt.o  t1_lib.o  t1_enc.o \
++	t1_meth.o   t1_srvr.o t1_clnt.o  t1_lib.o  t1_enc.o                    t1_ext.o \
+ 	d1_meth.o   d1_srvr.o d1_clnt.o  d1_lib.o  d1_pkt.o \
+ 	d1_both.o d1_enc.o \
+ 	ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
+@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h ..
+ t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c
++t1_ext.o: t1_ext.c ssl_locl.h
+diff -uprN openssl-0.9.8d.orig/ssl/s3_clnt.c openssl-0.9.8d/ssl/s3_clnt.c
+--- openssl-0.9.8d.orig/ssl/s3_clnt.c	2005-12-12 23:41:46.000000000 -0800
++++ openssl-0.9.8d/ssl/s3_clnt.c	2006-12-10 08:20:02.000000000 -0800
+@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s)
+ #endif
+ 		*(p++)=0; /* Add the NULL method */
+ 		
++		/* send client hello extensions if any */
++		if (s->version >= TLS1_VERSION && s->tls_extension)
++		{
++			// set the total extensions length
++			s2n(s->tls_extension->length + 4, p);
++
++			// put the extensions with type and length
++			s2n(s->tls_extension->type, p);
++			s2n(s->tls_extension->length, p);
++			
++			memcpy(p, s->tls_extension->data, s->tls_extension->length);
++			p+=s->tls_extension->length;
++		}
++
+ 		l=(p-d);
+ 		d=buf;
+ 		*(d++)=SSL3_MT_CLIENT_HELLO;
+@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s)
+ 	STACK_OF(SSL_CIPHER) *sk;
+ 	SSL_CIPHER *c;
+ 	unsigned char *p,*d;
+-	int i,al,ok;
++	int i,al,ok,pre_shared;
+ 	unsigned int j;
+ 	long n;
+ #ifndef OPENSSL_NO_COMP
+@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s)
+ 		goto f_err;
+ 		}
+ 
+-	if (j != 0 && j == s->session->session_id_length
++	/* check if we want to resume the session based on external pre-shared secret */
++	pre_shared = 0;
++	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++	{
++		SSL_CIPHER *pref_cipher=NULL;
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
++			NULL, &pref_cipher, s->tls_session_secret_cb_arg))
++		{
++			s->hit=1;
++			s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
++			s->session->session_id_length = j;
++			memcpy(s->session->session_id, p, j);
++			pre_shared = 1;
++		}
++	}
++
++	if ((pre_shared || j != 0) && j == s->session->session_id_length
+ 	    && memcmp(p,s->session->session_id,j) == 0)
+ 	    {
+ 	    if(s->sid_ctx_length != s->session->sid_ctx_length
+diff -uprN openssl-0.9.8d.orig/ssl/s3_srvr.c openssl-0.9.8d/ssl/s3_srvr.c
+--- openssl-0.9.8d.orig/ssl/s3_srvr.c	2006-09-28 04:29:03.000000000 -0700
++++ openssl-0.9.8d/ssl/s3_srvr.c	2006-12-10 08:20:02.000000000 -0800
+@@ -943,6 +943,75 @@ int ssl3_get_client_hello(SSL *s)
+ 		}
+ #endif
+ 
++	/* Check for TLS client hello extension here */
++	if (p < (d+n) && s->version >= TLS1_VERSION)
++	{
++		if (s->tls_extension_cb)
++		{
++			TLS_EXTENSION tls_ext;
++			unsigned short ext_total_len;
++			
++			n2s(p, ext_total_len);
++			n2s(p, tls_ext.type);
++			n2s(p, tls_ext.length);
++
++			// sanity check in TLS extension len
++			if (tls_ext.length > (d+n) - p)
++			{
++				// just cut the lenth to packet border
++				tls_ext.length = (d+n) - p;
++			}
++
++			tls_ext.data = p;
++
++			// returns an alert code or 0
++			al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg);
++			if (al != 0)
++			{
++				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
++				goto f_err;
++			}
++		}
++	}
++
++	/* Check if we want to use external pre-shared secret for this handshake */
++	/* for not reused session only */
++	if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++	{
++		SSL_CIPHER *pref_cipher=NULL;
++
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, 
++			ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
++		{
++			s->hit=1;
++			s->session->ciphers=ciphers;
++			s->session->verify_result=X509_V_OK;
++			
++			ciphers=NULL;
++			
++			/* check if some cipher was preferred by call back */
++			pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
++			if (pref_cipher == NULL)
++				{
++				al=SSL_AD_HANDSHAKE_FAILURE;
++				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
++				goto f_err;
++				}
++
++			s->session->cipher=pref_cipher;
++
++			if (s->cipher_list)
++				sk_SSL_CIPHER_free(s->cipher_list);
++
++			if (s->cipher_list_by_id)
++				sk_SSL_CIPHER_free(s->cipher_list_by_id);
++
++			s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
++			s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
++		}
++	}
++
+ 	/* Given s->session->ciphers and SSL_get_ciphers, we must
+ 	 * pick a cipher */
+ 
+diff -uprN openssl-0.9.8d.orig/ssl/ssl.h openssl-0.9.8d/ssl/ssl.h
+--- openssl-0.9.8d.orig/ssl/ssl.h	2006-06-14 06:52:49.000000000 -0700
++++ openssl-0.9.8d/ssl/ssl.h	2006-12-10 08:20:02.000000000 -0800
+@@ -345,6 +345,7 @@ extern "C" {
+  * 'struct ssl_st *' function parameters used to prototype callbacks
+  * in SSL_CTX. */
+ typedef struct ssl_st *ssl_crock_st;
++typedef struct tls_extension_st TLS_EXTENSION;
+ 
+ /* used to hold info on the particular ciphers used */
+ typedef struct ssl_cipher_st
+@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
+ typedef struct ssl_st SSL;
+ typedef struct ssl_ctx_st SSL_CTX;
+ 
++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
++
+ /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+ typedef struct ssl_method_st
+ 	{
+@@ -973,6 +976,15 @@ struct ssl_st
+ 	int first_packet;
+ 	int client_version;	/* what was passed, used for
+ 				 * SSLv3/TLS rollback check */
++
++	/* TLS externsions */
++	TLS_EXTENSION *tls_extension;
++	int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
++	void *tls_extension_cb_arg;
++
++	/* TLS pre-shared secret session resumption */
++	tls_session_secret_cb_fn tls_session_secret_cb;
++	void *tls_session_secret_cb_arg;
+ 	};
+ 
+ #ifdef __cplusplus
+@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v
+ int SSL_COMP_add_compression_method(int id,void *cm);
+ #endif
+ 
++/* TLS extensions functions */
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
++
++/* Pre-shared secret session resumption functions */
++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
++
+ /* BEGIN ERROR CODES */
+ /* The following lines are auto generated by the script mkerr.pl. Any changes
+  * made after this point may be overwritten when the script is next run.
+@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_TLS1_ENC					 210
+ #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+ #define SSL_F_WRITE_PENDING				 212
++#define SSL_F_SSL_SET_HELLO_EXTENSION	 213
+ 
+ /* Reason codes. */
+ #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+diff -uprN openssl-0.9.8d.orig/ssl/ssl_err.c openssl-0.9.8d/ssl/ssl_err.c
+--- openssl-0.9.8d.orig/ssl/ssl_err.c	2006-01-08 13:52:46.000000000 -0800
++++ openssl-0.9.8d/ssl/ssl_err.c	2006-12-10 08:20:02.000000000 -0800
+@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
+ {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
+ {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
+ {ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
++{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
+ {0,NULL}
+ 	};
+ 
+diff -uprN openssl-0.9.8d.orig/ssl/ssl_sess.c openssl-0.9.8d/ssl/ssl_sess.c
+--- openssl-0.9.8d.orig/ssl/ssl_sess.c	2005-12-30 15:51:57.000000000 -0800
++++ openssl-0.9.8d/ssl/ssl_sess.c	2006-12-10 08:20:02.000000000 -0800
+@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX *
+ 	return(s->session_timeout);
+ 	}
+ 
++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, 
++	STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
++{
++	if (s == NULL) return(0);
++	s->tls_session_secret_cb = tls_session_secret_cb;
++	s->tls_session_secret_cb_arg = arg;
++	return(1);
++}
++
+ typedef struct timeout_param_st
+ 	{
+ 	SSL_CTX *ctx;
+diff -uprN openssl-0.9.8d.orig/ssl/t1_ext.c openssl-0.9.8d/ssl/t1_ext.c
+--- openssl-0.9.8d.orig/ssl/t1_ext.c	1969-12-31 16:00:00.000000000 -0800
++++ openssl-0.9.8d/ssl/t1_ext.c	2006-12-10 08:20:02.000000000 -0800
+@@ -0,0 +1,48 @@
++
++#include 
++#include "ssl_locl.h"
++
++
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
++{
++	if(s->version >= TLS1_VERSION)
++	{
++		if(s->tls_extension)
++		{
++			OPENSSL_free(s->tls_extension);
++			s->tls_extension = NULL;
++		}
++
++		if(ext_data)
++		{
++			s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
++			if(!s->tls_extension)
++			{
++				SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
++				return 0;
++			}
++
++			s->tls_extension->type = ext_type;
++			s->tls_extension->length = ext_len;
++			s->tls_extension->data = s->tls_extension + 1;
++			memcpy(s->tls_extension->data, ext_data, ext_len);
++		}
++
++		return 1;
++	}
++
++	return 0;
++}
++
++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg)
++{
++	if(s->version >= TLS1_VERSION)
++	{
++		s->tls_extension_cb = cb;
++		s->tls_extension_cb_arg = arg;
++
++		return 1;
++	}
++
++	return 0;
++}
+diff -uprN openssl-0.9.8d.orig/ssl/t1_lib.c openssl-0.9.8d/ssl/t1_lib.c
+--- openssl-0.9.8d.orig/ssl/t1_lib.c	2005-08-05 16:52:07.000000000 -0700
++++ openssl-0.9.8d/ssl/t1_lib.c	2006-12-10 08:20:02.000000000 -0800
+@@ -97,6 +97,10 @@ int tls1_new(SSL *s)
+ 
+ void tls1_free(SSL *s)
+ 	{
++	if(s->tls_extension)
++	{
++		OPENSSL_free(s->tls_extension);
++	}
+ 	ssl3_free(s);
+ 	}
+ 
+diff -uprN openssl-0.9.8d.orig/ssl/tls1.h openssl-0.9.8d/ssl/tls1.h
+--- openssl-0.9.8d.orig/ssl/tls1.h	2006-06-14 10:52:01.000000000 -0700
++++ openssl-0.9.8d/ssl/tls1.h	2006-12-10 08:20:02.000000000 -0800
+@@ -296,6 +296,14 @@ extern "C" {
+ #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+ #endif
+ 
++/* TLS extension struct */
++struct tls_extension_st
++{
++	unsigned short type;
++	unsigned short length;
++	void *data;
++};
++
+ #ifdef  __cplusplus
+ }
+ #endif
+diff -uprN openssl-0.9.8d.orig/util/ssleay.num openssl-0.9.8d/util/ssleay.num
+--- openssl-0.9.8d.orig/util/ssleay.num	2005-05-08 17:22:02.000000000 -0700
++++ openssl-0.9.8d/util/ssleay.num	2006-12-10 08:20:02.000000000 -0800
+@@ -226,3 +226,6 @@ DTLSv1_server_method                    
+ SSL_COMP_get_compression_methods        276	EXIST:!VMS:FUNCTION:COMP
+ SSL_COMP_get_compress_methods           276	EXIST:VMS:FUNCTION:COMP
+ SSL_SESSION_get_id                      277	EXIST::FUNCTION:
++SSL_set_hello_extension			278	EXIST::FUNCTION:
++SSL_set_hello_extension_cb		279	EXIST::FUNCTION:
++SSL_set_session_secret_cb		280	EXIST::FUNCTION:
diff --git a/contrib/wpa/patches/openssl-0.9.8e-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8e-tls-extensions.patch
new file mode 100644
index 000000000000..ede053f779b6
--- /dev/null
+++ b/contrib/wpa/patches/openssl-0.9.8e-tls-extensions.patch
@@ -0,0 +1,353 @@
+This patch is adding support for TLS hello extensions and externally
+generated pre-shared key material to OpenSSL 0.9.8e. This is
+based on the patch from Alexey Kobozev 
+(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
+
+
+
+diff -uprN openssl-0.9.8e.orig/ssl/Makefile openssl-0.9.8e/ssl/Makefile
+--- openssl-0.9.8e.orig/ssl/Makefile	2006-02-03 17:49:35.000000000 -0800
++++ openssl-0.9.8e/ssl/Makefile	2007-03-22 20:23:19.000000000 -0700
+@@ -24,7 +24,7 @@ LIBSRC=	\
+ 	s2_meth.c   s2_srvr.c s2_clnt.c  s2_lib.c  s2_enc.c s2_pkt.c \
+ 	s3_meth.c   s3_srvr.c s3_clnt.c  s3_lib.c  s3_enc.c s3_pkt.c s3_both.c \
+ 	s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c          s23_pkt.c \
+-	t1_meth.c   t1_srvr.c t1_clnt.c  t1_lib.c  t1_enc.c \
++	t1_meth.c   t1_srvr.c t1_clnt.c  t1_lib.c  t1_enc.c                    t1_ext.c \
+ 	d1_meth.c   d1_srvr.c d1_clnt.c  d1_lib.c  d1_pkt.c \
+ 	d1_both.c d1_enc.c \
+ 	ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \
+@@ -35,7 +35,7 @@ LIBOBJ= \
+ 	s2_meth.o  s2_srvr.o  s2_clnt.o  s2_lib.o  s2_enc.o s2_pkt.o \
+ 	s3_meth.o  s3_srvr.o  s3_clnt.o  s3_lib.o  s3_enc.o s3_pkt.o s3_both.o \
+ 	s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o          s23_pkt.o \
+-	t1_meth.o   t1_srvr.o t1_clnt.o  t1_lib.o  t1_enc.o \
++	t1_meth.o   t1_srvr.o t1_clnt.o  t1_lib.o  t1_enc.o                    t1_ext.o \
+ 	d1_meth.o   d1_srvr.o d1_clnt.o  d1_lib.o  d1_pkt.o \
+ 	d1_both.o d1_enc.o \
+ 	ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \
+@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h ..
+ t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
+ t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
+ t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c
++t1_ext.o: t1_ext.c ssl_locl.h
+diff -uprN openssl-0.9.8e.orig/ssl/s3_clnt.c openssl-0.9.8e/ssl/s3_clnt.c
+--- openssl-0.9.8e.orig/ssl/s3_clnt.c	2006-09-28 05:23:15.000000000 -0700
++++ openssl-0.9.8e/ssl/s3_clnt.c	2007-03-22 20:23:19.000000000 -0700
+@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s)
+ #endif
+ 		*(p++)=0; /* Add the NULL method */
+ 		
++		/* send client hello extensions if any */
++		if (s->version >= TLS1_VERSION && s->tls_extension)
++		{
++			// set the total extensions length
++			s2n(s->tls_extension->length + 4, p);
++
++			// put the extensions with type and length
++			s2n(s->tls_extension->type, p);
++			s2n(s->tls_extension->length, p);
++			
++			memcpy(p, s->tls_extension->data, s->tls_extension->length);
++			p+=s->tls_extension->length;
++		}
++
+ 		l=(p-d);
+ 		d=buf;
+ 		*(d++)=SSL3_MT_CLIENT_HELLO;
+@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s)
+ 	STACK_OF(SSL_CIPHER) *sk;
+ 	SSL_CIPHER *c;
+ 	unsigned char *p,*d;
+-	int i,al,ok;
++	int i,al,ok,pre_shared;
+ 	unsigned int j;
+ 	long n;
+ #ifndef OPENSSL_NO_COMP
+@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s)
+ 		goto f_err;
+ 		}
+ 
+-	if (j != 0 && j == s->session->session_id_length
++	/* check if we want to resume the session based on external pre-shared secret */
++	pre_shared = 0;
++	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++	{
++		SSL_CIPHER *pref_cipher=NULL;
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
++			NULL, &pref_cipher, s->tls_session_secret_cb_arg))
++		{
++			s->hit=1;
++			s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
++			s->session->session_id_length = j;
++			memcpy(s->session->session_id, p, j);
++			pre_shared = 1;
++		}
++	}
++
++	if ((pre_shared || j != 0) && j == s->session->session_id_length
+ 	    && memcmp(p,s->session->session_id,j) == 0)
+ 	    {
+ 	    if(s->sid_ctx_length != s->session->sid_ctx_length
+diff -uprN openssl-0.9.8e.orig/ssl/s3_srvr.c openssl-0.9.8e/ssl/s3_srvr.c
+--- openssl-0.9.8e.orig/ssl/s3_srvr.c	2007-02-07 12:36:40.000000000 -0800
++++ openssl-0.9.8e/ssl/s3_srvr.c	2007-03-22 20:23:19.000000000 -0700
+@@ -945,6 +945,75 @@ int ssl3_get_client_hello(SSL *s)
+ 		}
+ #endif
+ 
++	/* Check for TLS client hello extension here */
++	if (p < (d+n) && s->version >= TLS1_VERSION)
++	{
++		if (s->tls_extension_cb)
++		{
++			TLS_EXTENSION tls_ext;
++			unsigned short ext_total_len;
++			
++			n2s(p, ext_total_len);
++			n2s(p, tls_ext.type);
++			n2s(p, tls_ext.length);
++
++			// sanity check in TLS extension len
++			if (tls_ext.length > (d+n) - p)
++			{
++				// just cut the lenth to packet border
++				tls_ext.length = (d+n) - p;
++			}
++
++			tls_ext.data = p;
++
++			// returns an alert code or 0
++			al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg);
++			if (al != 0)
++			{
++				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR);
++				goto f_err;
++			}
++		}
++	}
++
++	/* Check if we want to use external pre-shared secret for this handshake */
++	/* for not reused session only */
++	if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++	{
++		SSL_CIPHER *pref_cipher=NULL;
++
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, 
++			ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
++		{
++			s->hit=1;
++			s->session->ciphers=ciphers;
++			s->session->verify_result=X509_V_OK;
++			
++			ciphers=NULL;
++			
++			/* check if some cipher was preferred by call back */
++			pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
++			if (pref_cipher == NULL)
++				{
++				al=SSL_AD_HANDSHAKE_FAILURE;
++				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
++				goto f_err;
++				}
++
++			s->session->cipher=pref_cipher;
++
++			if (s->cipher_list)
++				sk_SSL_CIPHER_free(s->cipher_list);
++
++			if (s->cipher_list_by_id)
++				sk_SSL_CIPHER_free(s->cipher_list_by_id);
++
++			s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
++			s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
++		}
++	}
++
+ 	/* Given s->session->ciphers and SSL_get_ciphers, we must
+ 	 * pick a cipher */
+ 
+diff -uprN openssl-0.9.8e.orig/ssl/ssl.h openssl-0.9.8e/ssl/ssl.h
+--- openssl-0.9.8e.orig/ssl/ssl.h	2007-02-19 09:55:07.000000000 -0800
++++ openssl-0.9.8e/ssl/ssl.h	2007-03-22 20:23:19.000000000 -0700
+@@ -345,6 +345,7 @@ extern "C" {
+  * 'struct ssl_st *' function parameters used to prototype callbacks
+  * in SSL_CTX. */
+ typedef struct ssl_st *ssl_crock_st;
++typedef struct tls_extension_st TLS_EXTENSION;
+ 
+ /* used to hold info on the particular ciphers used */
+ typedef struct ssl_cipher_st
+@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
+ typedef struct ssl_st SSL;
+ typedef struct ssl_ctx_st SSL_CTX;
+ 
++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
++
+ /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+ typedef struct ssl_method_st
+ 	{
+@@ -973,6 +976,15 @@ struct ssl_st
+ 	int first_packet;
+ 	int client_version;	/* what was passed, used for
+ 				 * SSLv3/TLS rollback check */
++
++	/* TLS externsions */
++	TLS_EXTENSION *tls_extension;
++	int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg);
++	void *tls_extension_cb_arg;
++
++	/* TLS pre-shared secret session resumption */
++	tls_session_secret_cb_fn tls_session_secret_cb;
++	void *tls_session_secret_cb_arg;
+ 	};
+ 
+ #ifdef __cplusplus
+@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v
+ int SSL_COMP_add_compression_method(int id,void *cm);
+ #endif
+ 
++/* TLS extensions functions */
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg);
++
++/* Pre-shared secret session resumption functions */
++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
++
+ /* BEGIN ERROR CODES */
+ /* The following lines are auto generated by the script mkerr.pl. Any changes
+  * made after this point may be overwritten when the script is next run.
+@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_TLS1_ENC					 210
+ #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+ #define SSL_F_WRITE_PENDING				 212
++#define SSL_F_SSL_SET_HELLO_EXTENSION	 213
+ 
+ /* Reason codes. */
+ #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+diff -uprN openssl-0.9.8e.orig/ssl/ssl_err.c openssl-0.9.8e/ssl/ssl_err.c
+--- openssl-0.9.8e.orig/ssl/ssl_err.c	2006-11-21 12:14:46.000000000 -0800
++++ openssl-0.9.8e/ssl/ssl_err.c	2007-03-22 20:23:19.000000000 -0700
+@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
+ {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
+ {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
+ {ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
++{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
+ {0,NULL}
+ 	};
+ 
+diff -uprN openssl-0.9.8e.orig/ssl/ssl_sess.c openssl-0.9.8e/ssl/ssl_sess.c
+--- openssl-0.9.8e.orig/ssl/ssl_sess.c	2007-02-10 02:40:24.000000000 -0800
++++ openssl-0.9.8e/ssl/ssl_sess.c	2007-03-22 20:23:19.000000000 -0700
+@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX *
+ 	return(s->session_timeout);
+ 	}
+ 
++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, 
++	STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
++{
++	if (s == NULL) return(0);
++	s->tls_session_secret_cb = tls_session_secret_cb;
++	s->tls_session_secret_cb_arg = arg;
++	return(1);
++}
++
+ typedef struct timeout_param_st
+ 	{
+ 	SSL_CTX *ctx;
+diff -uprN openssl-0.9.8e.orig/ssl/t1_ext.c openssl-0.9.8e/ssl/t1_ext.c
+--- openssl-0.9.8e.orig/ssl/t1_ext.c	1969-12-31 16:00:00.000000000 -0800
++++ openssl-0.9.8e/ssl/t1_ext.c	2007-03-22 20:23:19.000000000 -0700
+@@ -0,0 +1,48 @@
++
++#include 
++#include "ssl_locl.h"
++
++
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
++{
++	if(s->version >= TLS1_VERSION)
++	{
++		if(s->tls_extension)
++		{
++			OPENSSL_free(s->tls_extension);
++			s->tls_extension = NULL;
++		}
++
++		if(ext_data)
++		{
++			s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
++			if(!s->tls_extension)
++			{
++				SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
++				return 0;
++			}
++
++			s->tls_extension->type = ext_type;
++			s->tls_extension->length = ext_len;
++			s->tls_extension->data = s->tls_extension + 1;
++			memcpy(s->tls_extension->data, ext_data, ext_len);
++		}
++
++		return 1;
++	}
++
++	return 0;
++}
++
++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg)
++{
++	if(s->version >= TLS1_VERSION)
++	{
++		s->tls_extension_cb = cb;
++		s->tls_extension_cb_arg = arg;
++
++		return 1;
++	}
++
++	return 0;
++}
+diff -uprN openssl-0.9.8e.orig/ssl/t1_lib.c openssl-0.9.8e/ssl/t1_lib.c
+--- openssl-0.9.8e.orig/ssl/t1_lib.c	2007-01-21 08:07:25.000000000 -0800
++++ openssl-0.9.8e/ssl/t1_lib.c	2007-03-22 20:23:19.000000000 -0700
+@@ -97,6 +97,10 @@ int tls1_new(SSL *s)
+ 
+ void tls1_free(SSL *s)
+ 	{
++	if(s->tls_extension)
++	{
++		OPENSSL_free(s->tls_extension);
++	}
+ 	ssl3_free(s);
+ 	}
+ 
+diff -uprN openssl-0.9.8e.orig/ssl/tls1.h openssl-0.9.8e/ssl/tls1.h
+--- openssl-0.9.8e.orig/ssl/tls1.h	2006-06-14 10:52:01.000000000 -0700
++++ openssl-0.9.8e/ssl/tls1.h	2007-03-22 20:23:19.000000000 -0700
+@@ -296,6 +296,14 @@ extern "C" {
+ #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+ #endif
+ 
++/* TLS extension struct */
++struct tls_extension_st
++{
++	unsigned short type;
++	unsigned short length;
++	void *data;
++};
++
+ #ifdef  __cplusplus
+ }
+ #endif
+diff -uprN openssl-0.9.8e.orig/util/ssleay.num openssl-0.9.8e/util/ssleay.num
+--- openssl-0.9.8e.orig/util/ssleay.num	2006-11-30 05:04:43.000000000 -0800
++++ openssl-0.9.8e/util/ssleay.num	2007-03-22 20:24:07.000000000 -0700
+@@ -238,3 +238,6 @@ SSL_CTX_set_info_callback               
+ SSL_CTX_sess_get_new_cb                 287	EXIST::FUNCTION:
+ SSL_CTX_get_client_cert_cb              288	EXIST::FUNCTION:
+ SSL_CTX_sess_get_remove_cb              289	EXIST::FUNCTION:
++SSL_set_hello_extension			290	EXIST::FUNCTION:
++SSL_set_hello_extension_cb		291	EXIST::FUNCTION:
++SSL_set_session_secret_cb		292	EXIST::FUNCTION:
diff --git a/contrib/wpa/patches/openssl-0.9.8g-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8g-tls-extensions.patch
new file mode 100644
index 000000000000..8ccbfaa29ddf
--- /dev/null
+++ b/contrib/wpa/patches/openssl-0.9.8g-tls-extensions.patch
@@ -0,0 +1,330 @@
+This patch adds support for TLS SessionTicket extension (RFC 5077) for
+the parts used by EAP-FAST (RFC 4851).
+
+This is based on the patch from Alexey Kobozev 
+(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
+
+OpenSSL 0.9.8g does not enable TLS extension support by default, so it
+will need to be enabled by adding enable-tlsext to config script
+command line.
+
+
+diff -upr openssl-0.9.8g.orig/ssl/s3_clnt.c openssl-0.9.8g/ssl/s3_clnt.c
+--- openssl-0.9.8g.orig/ssl/s3_clnt.c	2007-08-31 03:28:51.000000000 +0300
++++ openssl-0.9.8g/ssl/s3_clnt.c	2008-04-15 17:11:46.000000000 +0300
+@@ -727,6 +727,20 @@ int ssl3_get_server_hello(SSL *s)
+ 		goto f_err;
+ 		}
+ 
++#ifndef OPENSSL_NO_TLSEXT
++	/* check if we want to resume the session based on external pre-shared secret */
++	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++	{
++		SSL_CIPHER *pref_cipher=NULL;
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
++			NULL, &pref_cipher, s->tls_session_secret_cb_arg))
++		{
++			s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
++		}
++	}
++#endif /* OPENSSL_NO_TLSEXT */
++
+ 	if (j != 0 && j == s->session->session_id_length
+ 	    && memcmp(p,s->session->session_id,j) == 0)
+ 	    {
+diff -upr openssl-0.9.8g.orig/ssl/s3_srvr.c openssl-0.9.8g/ssl/s3_srvr.c
+--- openssl-0.9.8g.orig/ssl/s3_srvr.c	2007-09-30 21:55:59.000000000 +0300
++++ openssl-0.9.8g/ssl/s3_srvr.c	2008-04-15 17:10:37.000000000 +0300
+@@ -928,6 +928,59 @@ int ssl3_get_client_hello(SSL *s)
+ 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
+ 			goto err;
+ 		}
++
++	/* Check if we want to use external pre-shared secret for this
++	 * handshake for not reused session only. We need to generate
++	 * server_random before calling tls_session_secret_cb in order to allow
++	 * SessionTicket processing to use it in key derivation. */
++	{
++		unsigned long Time;
++		unsigned char *pos;
++		Time=(unsigned long)time(NULL);			/* Time */
++		pos=s->s3->server_random;
++		l2n(Time,pos);
++		if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
++		{
++			al=SSL_AD_INTERNAL_ERROR;
++			goto f_err;
++		}
++	}
++
++	if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++	{
++		SSL_CIPHER *pref_cipher=NULL;
++
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, 
++			ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
++		{
++			s->hit=1;
++			s->session->ciphers=ciphers;
++			s->session->verify_result=X509_V_OK;
++			
++			ciphers=NULL;
++			
++			/* check if some cipher was preferred by call back */
++			pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
++			if (pref_cipher == NULL)
++				{
++				al=SSL_AD_HANDSHAKE_FAILURE;
++				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
++				goto f_err;
++				}
++
++			s->session->cipher=pref_cipher;
++
++			if (s->cipher_list)
++				sk_SSL_CIPHER_free(s->cipher_list);
++
++			if (s->cipher_list_by_id)
++				sk_SSL_CIPHER_free(s->cipher_list_by_id);
++
++			s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
++			s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
++		}
++	}
+ #endif
+ 	/* Worst case, we will use the NULL compression, but if we have other
+ 	 * options, we will now look for them.  We have i-1 compression
+@@ -1066,16 +1119,22 @@ int ssl3_send_server_hello(SSL *s)
+ 	unsigned char *buf;
+ 	unsigned char *p,*d;
+ 	int i,sl;
+-	unsigned long l,Time;
++	unsigned long l;
++#ifdef OPENSSL_NO_TLSEXT
++	unsigned long Time;
++#endif
+ 
+ 	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
+ 		{
+ 		buf=(unsigned char *)s->init_buf->data;
++#ifdef OPENSSL_NO_TLSEXT
+ 		p=s->s3->server_random;
++		/* Generate server_random if it was not needed previously */
+ 		Time=(unsigned long)time(NULL);			/* Time */
+ 		l2n(Time,p);
+ 		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+ 			return -1;
++#endif
+ 		/* Do the message type and length last */
+ 		d=p= &(buf[4]);
+ 
+diff -upr openssl-0.9.8g.orig/ssl/ssl.h openssl-0.9.8g/ssl/ssl.h
+--- openssl-0.9.8g.orig/ssl/ssl.h	2007-10-19 10:42:38.000000000 +0300
++++ openssl-0.9.8g/ssl/ssl.h	2008-04-15 17:10:37.000000000 +0300
+@@ -342,6 +342,7 @@ extern "C" {
+  * 'struct ssl_st *' function parameters used to prototype callbacks
+  * in SSL_CTX. */
+ typedef struct ssl_st *ssl_crock_st;
++typedef struct tls_extension_st TLS_EXTENSION;
+ 
+ /* used to hold info on the particular ciphers used */
+ typedef struct ssl_cipher_st
+@@ -363,6 +364,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
+ typedef struct ssl_st SSL;
+ typedef struct ssl_ctx_st SSL_CTX;
+ 
++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
++
+ /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+ typedef struct ssl_method_st
+ 	{
+@@ -1004,6 +1007,14 @@ struct ssl_st
+ 	                       */
+ 	/* RFC4507 session ticket expected to be received or sent */
+ 	int tlsext_ticket_expected;
++
++	/* TLS extensions */
++	TLS_EXTENSION *tls_extension;
++
++	/* TLS pre-shared secret session resumption */
++	tls_session_secret_cb_fn tls_session_secret_cb;
++	void *tls_session_secret_cb_arg;
++
+ 	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
+ #define session_ctx initial_ctx
+ #else
+@@ -1589,6 +1600,12 @@ void *SSL_COMP_get_compression_methods(v
+ int SSL_COMP_add_compression_method(int id,void *cm);
+ #endif
+ 
++/* TLS extensions functions */
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
++
++/* Pre-shared secret session resumption functions */
++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
++
+ /* BEGIN ERROR CODES */
+ /* The following lines are auto generated by the script mkerr.pl. Any changes
+  * made after this point may be overwritten when the script is next run.
+@@ -1778,6 +1795,7 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_TLS1_ENC					 210
+ #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+ #define SSL_F_WRITE_PENDING				 212
++#define SSL_F_SSL_SET_HELLO_EXTENSION			 213
+ 
+ /* Reason codes. */
+ #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+diff -upr openssl-0.9.8g.orig/ssl/ssl_err.c openssl-0.9.8g/ssl/ssl_err.c
+--- openssl-0.9.8g.orig/ssl/ssl_err.c	2007-10-11 17:36:59.000000000 +0300
++++ openssl-0.9.8g/ssl/ssl_err.c	2008-04-15 17:10:37.000000000 +0300
+@@ -250,6 +250,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
+ {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
+ {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
+ {ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
++{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
+ {0,NULL}
+ 	};
+ 
+diff -upr openssl-0.9.8g.orig/ssl/ssl_sess.c openssl-0.9.8g/ssl/ssl_sess.c
+--- openssl-0.9.8g.orig/ssl/ssl_sess.c	2007-10-19 10:36:34.000000000 +0300
++++ openssl-0.9.8g/ssl/ssl_sess.c	2008-04-15 17:10:37.000000000 +0300
+@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX *
+ 	return(s->session_timeout);
+ 	}
+ 
++#ifndef OPENSSL_NO_TLSEXT
++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, 
++	STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
++{
++	if (s == NULL) return(0);
++	s->tls_session_secret_cb = tls_session_secret_cb;
++	s->tls_session_secret_cb_arg = arg;
++	return(1);
++}
++
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
++{
++	if(s->version >= TLS1_VERSION)
++	{
++		if(s->tls_extension)
++		{
++			OPENSSL_free(s->tls_extension);
++			s->tls_extension = NULL;
++		}
++
++		s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
++		if(!s->tls_extension)
++		{
++			SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
++			return 0;
++		}
++
++		s->tls_extension->type = ext_type;
++
++		if(ext_data)
++		{
++			s->tls_extension->length = ext_len;
++			s->tls_extension->data = s->tls_extension + 1;
++			memcpy(s->tls_extension->data, ext_data, ext_len);
++		} else {
++			s->tls_extension->length = 0;
++			s->tls_extension->data = NULL;
++		}
++
++		return 1;
++	}
++
++	return 0;
++}
++#endif /* OPENSSL_NO_TLSEXT */
++
+ typedef struct timeout_param_st
+ 	{
+ 	SSL_CTX *ctx;
+diff -upr openssl-0.9.8g.orig/ssl/t1_lib.c openssl-0.9.8g/ssl/t1_lib.c
+--- openssl-0.9.8g.orig/ssl/t1_lib.c	2007-10-19 10:44:10.000000000 +0300
++++ openssl-0.9.8g/ssl/t1_lib.c	2008-04-15 17:10:37.000000000 +0300
+@@ -105,6 +105,12 @@ int tls1_new(SSL *s)
+ 
+ void tls1_free(SSL *s)
+ 	{
++#ifndef OPENSSL_NO_TLSEXT
++	if(s->tls_extension)
++	{
++		OPENSSL_free(s->tls_extension);
++	}
++#endif
+ 	ssl3_free(s);
+ 	}
+ 
+@@ -174,8 +180,24 @@ unsigned char *ssl_add_clienthello_tlsex
+ 		int ticklen;
+ 		if (s->session && s->session->tlsext_tick)
+ 			ticklen = s->session->tlsext_ticklen;
++		else if (s->session && s->tls_extension &&
++			s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
++			s->tls_extension->data)
++		{
++			ticklen = s->tls_extension->length;
++			s->session->tlsext_tick = OPENSSL_malloc(ticklen);
++			if (!s->session->tlsext_tick)
++				return NULL;
++			memcpy(s->session->tlsext_tick, s->tls_extension->data,
++			       ticklen);
++			s->session->tlsext_ticklen = ticklen;
++		}
+ 		else
+ 			ticklen = 0;
++		if (ticklen == 0 && s->tls_extension &&
++		    s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
++		    s->tls_extension->data == NULL)
++			goto skip_ext;
+ 		/* Check for enough room 2 for extension type, 2 for len
+  		 * rest for ticket
+   		 */
+@@ -189,6 +211,7 @@ unsigned char *ssl_add_clienthello_tlsex
+ 			ret += ticklen;
+ 			}
+ 		}
++		skip_ext:
+ 
+ 	if ((extdatalen = ret-p-2)== 0) 
+ 		return p;
+@@ -543,6 +566,8 @@ int tls1_process_ticket(SSL *s, unsigned
+ 				s->tlsext_ticket_expected = 1;
+ 				return 0;	/* Cache miss */
+ 				}
++			if (s->tls_session_secret_cb)
++				return 0;
+ 			return tls_decrypt_ticket(s, p, size, session_id, len,
+ 									ret);
+ 			}
+diff -upr openssl-0.9.8g.orig/ssl/tls1.h openssl-0.9.8g/ssl/tls1.h
+--- openssl-0.9.8g.orig/ssl/tls1.h	2007-08-28 04:12:44.000000000 +0300
++++ openssl-0.9.8g/ssl/tls1.h	2008-04-15 17:10:37.000000000 +0300
+@@ -365,6 +365,14 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SER
+ #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+ #endif
+ 
++/* TLS extension struct */
++struct tls_extension_st
++{
++	unsigned short type;
++	unsigned short length;
++	void *data;
++};
++
+ #ifdef  __cplusplus
+ }
+ #endif
+diff -upr openssl-0.9.8g.orig/util/ssleay.num openssl-0.9.8g/util/ssleay.num
+--- openssl-0.9.8g.orig/util/ssleay.num	2007-08-13 01:31:16.000000000 +0300
++++ openssl-0.9.8g/util/ssleay.num	2008-04-15 17:10:37.000000000 +0300
+@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb              
+ SSL_set_SSL_CTX                         290	EXIST::FUNCTION:
+ SSL_get_servername                      291	EXIST::FUNCTION:TLSEXT
+ SSL_get_servername_type                 292	EXIST::FUNCTION:TLSEXT
++SSL_set_hello_extension			305	EXIST::FUNCTION:TLSEXT
++SSL_set_session_secret_cb		306	EXIST::FUNCTION:TLSEXT
diff --git a/contrib/wpa/patches/openssl-0.9.8h-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8h-tls-extensions.patch
new file mode 100644
index 000000000000..c68f2279b762
--- /dev/null
+++ b/contrib/wpa/patches/openssl-0.9.8h-tls-extensions.patch
@@ -0,0 +1,344 @@
+This patch adds support for TLS SessionTicket extension (RFC 5077) for
+the parts used by EAP-FAST (RFC 4851).
+
+This is based on the patch from Alexey Kobozev 
+(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
+
+OpenSSL 0.9.8h does not enable TLS extension support by default, so it
+will need to be enabled by adding enable-tlsext to config script
+command line.
+
+
+diff -upr openssl-0.9.8h.orig/ssl/s3_clnt.c openssl-0.9.8h/ssl/s3_clnt.c
+--- openssl-0.9.8h.orig/ssl/s3_clnt.c	2008-05-28 10:29:27.000000000 +0300
++++ openssl-0.9.8h/ssl/s3_clnt.c	2008-05-29 10:44:25.000000000 +0300
+@@ -752,6 +752,20 @@ int ssl3_get_server_hello(SSL *s)
+ 		goto f_err;
+ 		}
+ 
++#ifndef OPENSSL_NO_TLSEXT
++	/* check if we want to resume the session based on external pre-shared secret */
++	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++	{
++		SSL_CIPHER *pref_cipher=NULL;
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
++			NULL, &pref_cipher, s->tls_session_secret_cb_arg))
++		{
++			s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j);
++		}
++	}
++#endif /* OPENSSL_NO_TLSEXT */
++
+ 	if (j != 0 && j == s->session->session_id_length
+ 	    && memcmp(p,s->session->session_id,j) == 0)
+ 	    {
+@@ -2693,11 +2707,8 @@ static int ssl3_check_finished(SSL *s)
+ 	{
+ 	int ok;
+ 	long n;
+-	/* If we have no ticket or session ID is non-zero length (a match of
+-	 * a non-zero session length would never reach here) it cannot be a
+-	 * resumed session.
+-	 */
+-	if (!s->session->tlsext_tick || s->session->session_id_length)
++	/* If we have no ticket it cannot be a resumed session. */
++	if (!s->session->tlsext_tick)
+ 		return 1;
+ 	/* this function is called when we really expect a Certificate
+ 	 * message, so permit appropriate message length */
+diff -upr openssl-0.9.8h.orig/ssl/s3_srvr.c openssl-0.9.8h/ssl/s3_srvr.c
+--- openssl-0.9.8h.orig/ssl/s3_srvr.c	2008-04-30 19:11:32.000000000 +0300
++++ openssl-0.9.8h/ssl/s3_srvr.c	2008-05-28 18:49:34.000000000 +0300
+@@ -959,6 +959,59 @@ int ssl3_get_client_hello(SSL *s)
+ 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
+ 			goto err;
+ 		}
++
++	/* Check if we want to use external pre-shared secret for this
++	 * handshake for not reused session only. We need to generate
++	 * server_random before calling tls_session_secret_cb in order to allow
++	 * SessionTicket processing to use it in key derivation. */
++	{
++		unsigned long Time;
++		unsigned char *pos;
++		Time=(unsigned long)time(NULL);			/* Time */
++		pos=s->s3->server_random;
++		l2n(Time,pos);
++		if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
++		{
++			al=SSL_AD_INTERNAL_ERROR;
++			goto f_err;
++		}
++	}
++
++	if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++	{
++		SSL_CIPHER *pref_cipher=NULL;
++
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, 
++			ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
++		{
++			s->hit=1;
++			s->session->ciphers=ciphers;
++			s->session->verify_result=X509_V_OK;
++			
++			ciphers=NULL;
++			
++			/* check if some cipher was preferred by call back */
++			pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
++			if (pref_cipher == NULL)
++				{
++				al=SSL_AD_HANDSHAKE_FAILURE;
++				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
++				goto f_err;
++				}
++
++			s->session->cipher=pref_cipher;
++
++			if (s->cipher_list)
++				sk_SSL_CIPHER_free(s->cipher_list);
++
++			if (s->cipher_list_by_id)
++				sk_SSL_CIPHER_free(s->cipher_list_by_id);
++
++			s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
++			s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
++		}
++	}
+ #endif
+ 	/* Worst case, we will use the NULL compression, but if we have other
+ 	 * options, we will now look for them.  We have i-1 compression
+@@ -1097,16 +1150,22 @@ int ssl3_send_server_hello(SSL *s)
+ 	unsigned char *buf;
+ 	unsigned char *p,*d;
+ 	int i,sl;
+-	unsigned long l,Time;
++	unsigned long l;
++#ifdef OPENSSL_NO_TLSEXT
++	unsigned long Time;
++#endif
+ 
+ 	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
+ 		{
+ 		buf=(unsigned char *)s->init_buf->data;
++#ifdef OPENSSL_NO_TLSEXT
+ 		p=s->s3->server_random;
++		/* Generate server_random if it was not needed previously */
+ 		Time=(unsigned long)time(NULL);			/* Time */
+ 		l2n(Time,p);
+ 		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+ 			return -1;
++#endif
+ 		/* Do the message type and length last */
+ 		d=p= &(buf[4]);
+ 
+diff -upr openssl-0.9.8h.orig/ssl/ssl.h openssl-0.9.8h/ssl/ssl.h
+--- openssl-0.9.8h.orig/ssl/ssl.h	2008-04-30 19:11:32.000000000 +0300
++++ openssl-0.9.8h/ssl/ssl.h	2008-05-28 18:49:34.000000000 +0300
+@@ -343,6 +343,7 @@ extern "C" {
+  * 'struct ssl_st *' function parameters used to prototype callbacks
+  * in SSL_CTX. */
+ typedef struct ssl_st *ssl_crock_st;
++typedef struct tls_extension_st TLS_EXTENSION;
+ 
+ /* used to hold info on the particular ciphers used */
+ typedef struct ssl_cipher_st
+@@ -364,6 +365,8 @@ DECLARE_STACK_OF(SSL_CIPHER)
+ typedef struct ssl_st SSL;
+ typedef struct ssl_ctx_st SSL_CTX;
+ 
++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
++
+ /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+ typedef struct ssl_method_st
+ 	{
+@@ -1027,6 +1030,14 @@ struct ssl_st
+ 
+ 	/* RFC4507 session ticket expected to be received or sent */
+ 	int tlsext_ticket_expected;
++
++	/* TLS extensions */
++	TLS_EXTENSION *tls_extension;
++
++	/* TLS pre-shared secret session resumption */
++	tls_session_secret_cb_fn tls_session_secret_cb;
++	void *tls_session_secret_cb_arg;
++
+ 	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
+ #define session_ctx initial_ctx
+ #else
+@@ -1625,6 +1636,12 @@ void *SSL_COMP_get_compression_methods(v
+ int SSL_COMP_add_compression_method(int id,void *cm);
+ #endif
+ 
++/* TLS extensions functions */
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
++
++/* Pre-shared secret session resumption functions */
++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
++
+ /* BEGIN ERROR CODES */
+ /* The following lines are auto generated by the script mkerr.pl. Any changes
+  * made after this point may be overwritten when the script is next run.
+@@ -1815,6 +1832,7 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_TLS1_ENC					 210
+ #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+ #define SSL_F_WRITE_PENDING				 212
++#define SSL_F_SSL_SET_HELLO_EXTENSION			 213
+ 
+ /* Reason codes. */
+ #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+diff -upr openssl-0.9.8h.orig/ssl/ssl_err.c openssl-0.9.8h/ssl/ssl_err.c
+--- openssl-0.9.8h.orig/ssl/ssl_err.c	2007-10-12 03:00:30.000000000 +0300
++++ openssl-0.9.8h/ssl/ssl_err.c	2008-05-28 18:49:34.000000000 +0300
+@@ -251,6 +251,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
+ {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
+ {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
+ {ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
++{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"},
+ {0,NULL}
+ 	};
+ 
+diff -upr openssl-0.9.8h.orig/ssl/ssl_sess.c openssl-0.9.8h/ssl/ssl_sess.c
+--- openssl-0.9.8h.orig/ssl/ssl_sess.c	2007-10-17 20:30:15.000000000 +0300
++++ openssl-0.9.8h/ssl/ssl_sess.c	2008-05-28 18:49:34.000000000 +0300
+@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX *
+ 	return(s->session_timeout);
+ 	}
+ 
++#ifndef OPENSSL_NO_TLSEXT
++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, 
++	STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
++{
++	if (s == NULL) return(0);
++	s->tls_session_secret_cb = tls_session_secret_cb;
++	s->tls_session_secret_cb_arg = arg;
++	return(1);
++}
++
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
++{
++	if(s->version >= TLS1_VERSION)
++	{
++		if(s->tls_extension)
++		{
++			OPENSSL_free(s->tls_extension);
++			s->tls_extension = NULL;
++		}
++
++		s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len);
++		if(!s->tls_extension)
++		{
++			SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE);
++			return 0;
++		}
++
++		s->tls_extension->type = ext_type;
++
++		if(ext_data)
++		{
++			s->tls_extension->length = ext_len;
++			s->tls_extension->data = s->tls_extension + 1;
++			memcpy(s->tls_extension->data, ext_data, ext_len);
++		} else {
++			s->tls_extension->length = 0;
++			s->tls_extension->data = NULL;
++		}
++
++		return 1;
++	}
++
++	return 0;
++}
++#endif /* OPENSSL_NO_TLSEXT */
++
+ typedef struct timeout_param_st
+ 	{
+ 	SSL_CTX *ctx;
+diff -upr openssl-0.9.8h.orig/ssl/t1_lib.c openssl-0.9.8h/ssl/t1_lib.c
+--- openssl-0.9.8h.orig/ssl/t1_lib.c	2008-05-28 10:26:33.000000000 +0300
++++ openssl-0.9.8h/ssl/t1_lib.c	2008-05-28 18:49:34.000000000 +0300
+@@ -106,6 +106,12 @@ int tls1_new(SSL *s)
+ 
+ void tls1_free(SSL *s)
+ 	{
++#ifndef OPENSSL_NO_TLSEXT
++	if(s->tls_extension)
++	{
++		OPENSSL_free(s->tls_extension);
++	}
++#endif
+ 	ssl3_free(s);
+ 	}
+ 
+@@ -175,8 +181,24 @@ unsigned char *ssl_add_clienthello_tlsex
+ 		int ticklen;
+ 		if (s->session && s->session->tlsext_tick)
+ 			ticklen = s->session->tlsext_ticklen;
++		else if (s->session && s->tls_extension &&
++			s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
++			s->tls_extension->data)
++		{
++			ticklen = s->tls_extension->length;
++			s->session->tlsext_tick = OPENSSL_malloc(ticklen);
++			if (!s->session->tlsext_tick)
++				return NULL;
++			memcpy(s->session->tlsext_tick, s->tls_extension->data,
++			       ticklen);
++			s->session->tlsext_ticklen = ticklen;
++		}
+ 		else
+ 			ticklen = 0;
++		if (ticklen == 0 && s->tls_extension &&
++		    s->tls_extension->type == TLSEXT_TYPE_session_ticket &&
++		    s->tls_extension->data == NULL)
++			goto skip_ext;
+ 		/* Check for enough room 2 for extension type, 2 for len
+  		 * rest for ticket
+   		 */
+@@ -190,6 +212,7 @@ unsigned char *ssl_add_clienthello_tlsex
+ 			ret += ticklen;
+ 			}
+ 		}
++		skip_ext:
+ 
+ 	if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+ 		{
+@@ -774,6 +797,8 @@ int tls1_process_ticket(SSL *s, unsigned
+ 				s->tlsext_ticket_expected = 1;
+ 				return 0;	/* Cache miss */
+ 				}
++			if (s->tls_session_secret_cb)
++				return 0;
+ 			return tls_decrypt_ticket(s, p, size, session_id, len,
+ 									ret);
+ 			}
+diff -upr openssl-0.9.8h.orig/ssl/tls1.h openssl-0.9.8h/ssl/tls1.h
+--- openssl-0.9.8h.orig/ssl/tls1.h	2008-04-30 19:11:33.000000000 +0300
++++ openssl-0.9.8h/ssl/tls1.h	2008-05-28 18:49:34.000000000 +0300
+@@ -398,6 +398,14 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
+ #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+ #endif
+ 
++/* TLS extension struct */
++struct tls_extension_st
++{
++	unsigned short type;
++	unsigned short length;
++	void *data;
++};
++
+ #ifdef  __cplusplus
+ }
+ #endif
+diff -upr openssl-0.9.8h.orig/util/ssleay.num openssl-0.9.8h/util/ssleay.num
+--- openssl-0.9.8h.orig/util/ssleay.num	2007-08-13 01:31:16.000000000 +0300
++++ openssl-0.9.8h/util/ssleay.num	2008-05-28 18:49:34.000000000 +0300
+@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb              
+ SSL_set_SSL_CTX                         290	EXIST::FUNCTION:
+ SSL_get_servername                      291	EXIST::FUNCTION:TLSEXT
+ SSL_get_servername_type                 292	EXIST::FUNCTION:TLSEXT
++SSL_set_hello_extension			305	EXIST::FUNCTION:TLSEXT
++SSL_set_session_secret_cb		306	EXIST::FUNCTION:TLSEXT
diff --git a/contrib/wpa/patches/openssl-0.9.8i-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8i-tls-extensions.patch
new file mode 100644
index 000000000000..90bff544eb59
--- /dev/null
+++ b/contrib/wpa/patches/openssl-0.9.8i-tls-extensions.patch
@@ -0,0 +1,404 @@
+This patch adds support for TLS SessionTicket extension (RFC 5077) for
+the parts used by EAP-FAST (RFC 4851).
+
+This is based on the patch from Alexey Kobozev 
+(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
+
+OpenSSL 0.9.8i does not enable TLS extension support by default, so it
+will need to be enabled by adding enable-tlsext to config script
+command line.
+
+
+Index: openssl-0.9.8i/ssl/s3_clnt.c
+===================================================================
+--- openssl-0.9.8i.orig/ssl/s3_clnt.c	2008-06-16 19:56:41.000000000 +0300
++++ openssl-0.9.8i/ssl/s3_clnt.c	2008-11-23 20:39:40.000000000 +0200
+@@ -759,6 +759,21 @@
+ 		goto f_err;
+ 		}
+ 
++#ifndef OPENSSL_NO_TLSEXT
++	/* check if we want to resume the session based on external pre-shared secret */
++	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++		{
++		SSL_CIPHER *pref_cipher=NULL;
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
++			NULL, &pref_cipher, s->tls_session_secret_cb_arg))
++			{
++			s->session->cipher=pref_cipher ?
++				pref_cipher : ssl_get_cipher_by_char(s,p+j);
++			}
++		}
++#endif /* OPENSSL_NO_TLSEXT */
++
+ 	if (j != 0 && j == s->session->session_id_length
+ 	    && memcmp(p,s->session->session_id,j) == 0)
+ 	    {
+@@ -2701,11 +2716,8 @@
+ 	{
+ 	int ok;
+ 	long n;
+-	/* If we have no ticket or session ID is non-zero length (a match of
+-	 * a non-zero session length would never reach here) it cannot be a
+-	 * resumed session.
+-	 */
+-	if (!s->session->tlsext_tick || s->session->session_id_length)
++	/* If we have no ticket it cannot be a resumed session. */
++	if (!s->session->tlsext_tick)
+ 		return 1;
+ 	/* this function is called when we really expect a Certificate
+ 	 * message, so permit appropriate message length */
+Index: openssl-0.9.8i/ssl/s3_srvr.c
+===================================================================
+--- openssl-0.9.8i.orig/ssl/s3_srvr.c	2008-09-14 21:16:09.000000000 +0300
++++ openssl-0.9.8i/ssl/s3_srvr.c	2008-11-23 20:37:40.000000000 +0200
+@@ -959,6 +959,59 @@
+ 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
+ 			goto err;
+ 		}
++
++	/* Check if we want to use external pre-shared secret for this
++	 * handshake for not reused session only. We need to generate
++	 * server_random before calling tls_session_secret_cb in order to allow
++	 * SessionTicket processing to use it in key derivation. */
++	{
++		unsigned long Time;
++		unsigned char *pos;
++		Time=(unsigned long)time(NULL);			/* Time */
++		pos=s->s3->server_random;
++		l2n(Time,pos);
++		if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
++			{
++			al=SSL_AD_INTERNAL_ERROR;
++			goto f_err;
++			}
++	}
++
++	if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++		{
++		SSL_CIPHER *pref_cipher=NULL;
++
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, 
++			ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
++			{
++			s->hit=1;
++			s->session->ciphers=ciphers;
++			s->session->verify_result=X509_V_OK;
++			
++			ciphers=NULL;
++			
++			/* check if some cipher was preferred by call back */
++			pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
++			if (pref_cipher == NULL)
++				{
++				al=SSL_AD_HANDSHAKE_FAILURE;
++				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
++				goto f_err;
++				}
++
++			s->session->cipher=pref_cipher;
++
++			if (s->cipher_list)
++				sk_SSL_CIPHER_free(s->cipher_list);
++
++			if (s->cipher_list_by_id)
++				sk_SSL_CIPHER_free(s->cipher_list_by_id);
++
++			s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
++			s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
++			}
++		}
+ #endif
+ 	/* Worst case, we will use the NULL compression, but if we have other
+ 	 * options, we will now look for them.  We have i-1 compression
+@@ -1097,16 +1150,22 @@
+ 	unsigned char *buf;
+ 	unsigned char *p,*d;
+ 	int i,sl;
+-	unsigned long l,Time;
++	unsigned long l;
++#ifdef OPENSSL_NO_TLSEXT
++	unsigned long Time;
++#endif
+ 
+ 	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
+ 		{
+ 		buf=(unsigned char *)s->init_buf->data;
++#ifdef OPENSSL_NO_TLSEXT
+ 		p=s->s3->server_random;
++		/* Generate server_random if it was not needed previously */
+ 		Time=(unsigned long)time(NULL);			/* Time */
+ 		l2n(Time,p);
+ 		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+ 			return -1;
++#endif
+ 		/* Do the message type and length last */
+ 		d=p= &(buf[4]);
+ 
+Index: openssl-0.9.8i/ssl/ssl_err.c
+===================================================================
+--- openssl-0.9.8i.orig/ssl/ssl_err.c	2008-08-13 22:44:44.000000000 +0300
++++ openssl-0.9.8i/ssl/ssl_err.c	2008-11-23 20:33:43.000000000 +0200
+@@ -253,6 +253,7 @@
+ {ERR_FUNC(SSL_F_TLS1_ENC),	"TLS1_ENC"},
+ {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
+ {ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
++{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
+ {0,NULL}
+ 	};
+ 
+Index: openssl-0.9.8i/ssl/ssl.h
+===================================================================
+--- openssl-0.9.8i.orig/ssl/ssl.h	2008-08-13 22:44:44.000000000 +0300
++++ openssl-0.9.8i/ssl/ssl.h	2008-11-23 20:35:41.000000000 +0200
+@@ -344,6 +344,7 @@
+  * 'struct ssl_st *' function parameters used to prototype callbacks
+  * in SSL_CTX. */
+ typedef struct ssl_st *ssl_crock_st;
++typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
+ 
+ /* used to hold info on the particular ciphers used */
+ typedef struct ssl_cipher_st
+@@ -362,6 +363,9 @@
+ 
+ DECLARE_STACK_OF(SSL_CIPHER)
+ 
++typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
++
+ /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+ typedef struct ssl_method_st
+ 	{
+@@ -1034,6 +1038,18 @@
+ 
+ 	/* RFC4507 session ticket expected to be received or sent */
+ 	int tlsext_ticket_expected;
++
++	/* TLS Session Ticket extension override */
++	TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
++
++	/* TLS Session Ticket extension callback */
++	tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
++	void *tls_session_ticket_ext_cb_arg;
++
++	/* TLS pre-shared secret session resumption */
++	tls_session_secret_cb_fn tls_session_secret_cb;
++	void *tls_session_secret_cb_arg;
++
+ 	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
+ #define session_ctx initial_ctx
+ #else
+@@ -1632,6 +1648,15 @@
+ int SSL_COMP_add_compression_method(int id,void *cm);
+ #endif
+ 
++/* TLS extensions functions */
++int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
++
++int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
++				  void *arg);
++
++/* Pre-shared secret session resumption functions */
++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
++
+ /* BEGIN ERROR CODES */
+ /* The following lines are auto generated by the script mkerr.pl. Any changes
+  * made after this point may be overwritten when the script is next run.
+@@ -1824,6 +1849,7 @@
+ #define SSL_F_TLS1_ENC					 210
+ #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+ #define SSL_F_WRITE_PENDING				 212
++#define SSL_F_SSL_SET_SESSION_TICKET_EXT		 213
+ 
+ /* Reason codes. */
+ #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+Index: openssl-0.9.8i/ssl/ssl_sess.c
+===================================================================
+--- openssl-0.9.8i.orig/ssl/ssl_sess.c	2008-06-04 21:35:27.000000000 +0300
++++ openssl-0.9.8i/ssl/ssl_sess.c	2008-11-23 20:32:24.000000000 +0200
+@@ -707,6 +707,61 @@
+ 	return(s->session_timeout);
+ 	}
+ 
++#ifndef OPENSSL_NO_TLSEXT
++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
++	STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
++	{
++	if (s == NULL) return(0);
++	s->tls_session_secret_cb = tls_session_secret_cb;
++	s->tls_session_secret_cb_arg = arg;
++	return(1);
++	}
++
++int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
++				  void *arg)
++	{
++	if (s == NULL) return(0);
++	s->tls_session_ticket_ext_cb = cb;
++	s->tls_session_ticket_ext_cb_arg = arg;
++	return(1);
++	}
++
++int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
++	{
++	if (s->version >= TLS1_VERSION)
++		{
++		if (s->tlsext_session_ticket)
++			{
++			OPENSSL_free(s->tlsext_session_ticket);
++			s->tlsext_session_ticket = NULL;
++			}
++
++		s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
++		if (!s->tlsext_session_ticket)
++			{
++			SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
++			return 0;
++			}
++
++		if (ext_data)
++			{
++			s->tlsext_session_ticket->length = ext_len;
++			s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
++			memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
++			}
++		else
++			{
++			s->tlsext_session_ticket->length = 0;
++			s->tlsext_session_ticket->data = NULL;
++			}
++
++		return 1;
++		}
++
++	return 0;
++	}
++#endif /* OPENSSL_NO_TLSEXT */
++
+ typedef struct timeout_param_st
+ 	{
+ 	SSL_CTX *ctx;
+Index: openssl-0.9.8i/ssl/t1_lib.c
+===================================================================
+--- openssl-0.9.8i.orig/ssl/t1_lib.c	2008-09-04 01:13:04.000000000 +0300
++++ openssl-0.9.8i/ssl/t1_lib.c	2008-11-23 20:31:20.000000000 +0200
+@@ -106,6 +106,12 @@
+ 
+ void tls1_free(SSL *s)
+ 	{
++#ifndef OPENSSL_NO_TLSEXT
++	if (s->tlsext_session_ticket)
++		{
++		OPENSSL_free(s->tlsext_session_ticket);
++		}
++#endif
+ 	ssl3_free(s);
+ 	}
+ 
+@@ -175,8 +181,23 @@
+ 		int ticklen;
+ 		if (s->session && s->session->tlsext_tick)
+ 			ticklen = s->session->tlsext_ticklen;
++		else if (s->session && s->tlsext_session_ticket &&
++			 s->tlsext_session_ticket->data)
++			{
++			ticklen = s->tlsext_session_ticket->length;
++			s->session->tlsext_tick = OPENSSL_malloc(ticklen);
++			if (!s->session->tlsext_tick)
++				return NULL;
++			memcpy(s->session->tlsext_tick,
++			       s->tlsext_session_ticket->data,
++			       ticklen);
++			s->session->tlsext_ticklen = ticklen;
++			}
+ 		else
+ 			ticklen = 0;
++		if (ticklen == 0 && s->tlsext_session_ticket &&
++		    s->tlsext_session_ticket->data == NULL)
++			goto skip_ext;
+ 		/* Check for enough room 2 for extension type, 2 for len
+  		 * rest for ticket
+   		 */
+@@ -190,6 +211,7 @@
+ 			ret += ticklen;
+ 			}
+ 		}
++		skip_ext:
+ 
+ 	if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+ 		{
+@@ -407,6 +429,15 @@
+ 				}
+ 
+ 			}
++		else if (type == TLSEXT_TYPE_session_ticket)
++			{
++			if (s->tls_session_ticket_ext_cb &&
++			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
++				{
++				*al = TLS1_AD_INTERNAL_ERROR;
++				return 0;
++				}
++			}
+ 		else if (type == TLSEXT_TYPE_status_request
+ 						&& s->ctx->tlsext_status_cb)
+ 			{
+@@ -553,6 +584,12 @@
+ 			}
+ 		else if (type == TLSEXT_TYPE_session_ticket)
+ 			{
++			if (s->tls_session_ticket_ext_cb &&
++			    !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
++				{
++				*al = TLS1_AD_INTERNAL_ERROR;
++				return 0;
++				}
+ 			if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
+ 				|| (size > 0))
+ 				{
+@@ -776,6 +813,15 @@
+ 				s->tlsext_ticket_expected = 1;
+ 				return 0;	/* Cache miss */
+ 				}
++			if (s->tls_session_secret_cb)
++				{
++				/* Indicate cache miss here and instead of
++				 * generating the session from ticket now,
++				 * trigger abbreviated handshake based on
++				 * external mechanism to calculate the master
++				 * secret later. */
++				return 0;
++				}
+ 			return tls_decrypt_ticket(s, p, size, session_id, len,
+ 									ret);
+ 			}
+Index: openssl-0.9.8i/ssl/tls1.h
+===================================================================
+--- openssl-0.9.8i.orig/ssl/tls1.h	2008-04-30 19:11:33.000000000 +0300
++++ openssl-0.9.8i/ssl/tls1.h	2008-11-23 20:22:38.000000000 +0200
+@@ -398,6 +398,13 @@
+ #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+ #endif
+ 
++/* TLS extension struct */
++struct tls_session_ticket_ext_st
++	{
++	unsigned short length;
++	void *data;
++	};
++
+ #ifdef  __cplusplus
+ }
+ #endif
+Index: openssl-0.9.8i/util/ssleay.num
+===================================================================
+--- openssl-0.9.8i.orig/util/ssleay.num	2008-06-05 13:57:21.000000000 +0300
++++ openssl-0.9.8i/util/ssleay.num	2008-11-23 20:22:05.000000000 +0200
+@@ -242,3 +242,5 @@
+ SSL_get_servername                      291	EXIST::FUNCTION:TLSEXT
+ SSL_get_servername_type                 292	EXIST::FUNCTION:TLSEXT
+ SSL_CTX_set_client_cert_engine          293	EXIST::FUNCTION:ENGINE
++SSL_set_session_ticket_ext		306	EXIST::FUNCTION:TLSEXT
++SSL_set_session_secret_cb		307	EXIST::FUNCTION:TLSEXT
diff --git a/contrib/wpa/patches/openssl-0.9.9-session-ticket.patch b/contrib/wpa/patches/openssl-0.9.9-session-ticket.patch
new file mode 100644
index 000000000000..3afa639ad898
--- /dev/null
+++ b/contrib/wpa/patches/openssl-0.9.9-session-ticket.patch
@@ -0,0 +1,374 @@
+This patch adds support for TLS SessionTicket extension (RFC 5077) for
+the parts used by EAP-FAST (RFC 4851).
+
+This is based on the patch from Alexey Kobozev 
+(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
+
+NOTE: This patch (without SSL_set_hello_extension() wrapper) was
+merged into the upstream OpenSSL 0.9.9 tree and as such, an external
+patch for EAP-FAST support is not needed anymore.
+
+
+
+Index: openssl-SNAP-20081111/ssl/s3_clnt.c
+===================================================================
+--- openssl-SNAP-20081111.orig/ssl/s3_clnt.c
++++ openssl-SNAP-20081111/ssl/s3_clnt.c
+@@ -788,6 +788,23 @@ int ssl3_get_server_hello(SSL *s)
+ 		goto f_err;
+ 		}
+ 
++#ifndef OPENSSL_NO_TLSEXT
++	/* check if we want to resume the session based on external pre-shared secret */
++	if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++		{
++		SSL_CIPHER *pref_cipher=NULL;
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if (s->tls_session_secret_cb(s, s->session->master_key,
++					     &s->session->master_key_length,
++					     NULL, &pref_cipher,
++					     s->tls_session_secret_cb_arg))
++			{
++			s->session->cipher = pref_cipher ?
++				pref_cipher : ssl_get_cipher_by_char(s, p+j);
++			}
++		}
++#endif /* OPENSSL_NO_TLSEXT */
++
+ 	if (j != 0 && j == s->session->session_id_length
+ 	    && memcmp(p,s->session->session_id,j) == 0)
+ 	    {
+@@ -2927,11 +2944,8 @@ static int ssl3_check_finished(SSL *s)
+ 	{
+ 	int ok;
+ 	long n;
+-	/* If we have no ticket or session ID is non-zero length (a match of
+-	 * a non-zero session length would never reach here) it cannot be a
+-	 * resumed session.
+-	 */
+-	if (!s->session->tlsext_tick || s->session->session_id_length)
++	/* If we have no ticket it cannot be a resumed session. */
++	if (!s->session->tlsext_tick)
+ 		return 1;
+ 	/* this function is called when we really expect a Certificate
+ 	 * message, so permit appropriate message length */
+Index: openssl-SNAP-20081111/ssl/s3_srvr.c
+===================================================================
+--- openssl-SNAP-20081111.orig/ssl/s3_srvr.c
++++ openssl-SNAP-20081111/ssl/s3_srvr.c
+@@ -1010,6 +1010,59 @@ int ssl3_get_client_hello(SSL *s)
+ 			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
+ 			goto err;
+ 		}
++
++	/* Check if we want to use external pre-shared secret for this
++	 * handshake for not reused session only. We need to generate
++	 * server_random before calling tls_session_secret_cb in order to allow
++	 * SessionTicket processing to use it in key derivation. */
++	{
++		unsigned long Time;
++		unsigned char *pos;
++		Time=(unsigned long)time(NULL);			/* Time */
++		pos=s->s3->server_random;
++		l2n(Time,pos);
++		if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
++			{
++			al=SSL_AD_INTERNAL_ERROR;
++			goto f_err;
++			}
++	}
++
++	if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
++		{
++		SSL_CIPHER *pref_cipher=NULL;
++
++		s->session->master_key_length=sizeof(s->session->master_key);
++		if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
++			ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
++			{
++			s->hit=1;
++			s->session->ciphers=ciphers;
++			s->session->verify_result=X509_V_OK;
++
++			ciphers=NULL;
++
++			/* check if some cipher was preferred by call back */
++			pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
++			if (pref_cipher == NULL)
++				{
++				al=SSL_AD_HANDSHAKE_FAILURE;
++				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
++				goto f_err;
++				}
++
++			s->session->cipher=pref_cipher;
++
++			if (s->cipher_list)
++				sk_SSL_CIPHER_free(s->cipher_list);
++
++			if (s->cipher_list_by_id)
++				sk_SSL_CIPHER_free(s->cipher_list_by_id);
++
++			s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
++			s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
++			}
++		}
+ #endif
+ 
+ 	/* Worst case, we will use the NULL compression, but if we have other
+@@ -1134,16 +1187,22 @@ int ssl3_send_server_hello(SSL *s)
+ 	unsigned char *buf;
+ 	unsigned char *p,*d;
+ 	int i,sl;
+-	unsigned long l,Time;
++	unsigned long l;
++#ifdef OPENSSL_NO_TLSEXT
++	unsigned long Time;
++#endif
+ 
+ 	if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
+ 		{
+ 		buf=(unsigned char *)s->init_buf->data;
++#ifdef OPENSSL_NO_TLSEXT
+ 		p=s->s3->server_random;
++		/* Generate server_random if it was not needed previously */
+ 		Time=(unsigned long)time(NULL);			/* Time */
+ 		l2n(Time,p);
+ 		if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+ 			return -1;
++#endif
+ 		/* Do the message type and length last */
+ 		d=p= &(buf[4]);
+ 
+Index: openssl-SNAP-20081111/ssl/ssl_err.c
+===================================================================
+--- openssl-SNAP-20081111.orig/ssl/ssl_err.c
++++ openssl-SNAP-20081111/ssl/ssl_err.c
+@@ -263,6 +263,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
+ {ERR_FUNC(SSL_F_TLS1_PRF),	"tls1_prf"},
+ {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK),	"TLS1_SETUP_KEY_BLOCK"},
+ {ERR_FUNC(SSL_F_WRITE_PENDING),	"WRITE_PENDING"},
++{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
+ {0,NULL}
+ 	};
+ 
+Index: openssl-SNAP-20081111/ssl/ssl.h
+===================================================================
+--- openssl-SNAP-20081111.orig/ssl/ssl.h
++++ openssl-SNAP-20081111/ssl/ssl.h
+@@ -355,6 +355,7 @@ extern "C" {
+  * 'struct ssl_st *' function parameters used to prototype callbacks
+  * in SSL_CTX. */
+ typedef struct ssl_st *ssl_crock_st;
++typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
+ 
+ /* used to hold info on the particular ciphers used */
+ typedef struct ssl_cipher_st
+@@ -378,6 +379,8 @@ typedef struct ssl_cipher_st
+ 
+ DECLARE_STACK_OF(SSL_CIPHER)
+ 
++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
++
+ /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
+ typedef struct ssl_method_st
+ 	{
+@@ -1145,6 +1148,13 @@ struct ssl_st
+ 	void *tlsext_opaque_prf_input;
+ 	size_t tlsext_opaque_prf_input_len;
+ 
++	/* TLS Session Ticket extension override */
++	TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
++
++	/* TLS pre-shared secret session resumption */
++	tls_session_secret_cb_fn tls_session_secret_cb;
++	void *tls_session_secret_cb_arg;
++
+ 	SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
+ #define session_ctx initial_ctx
+ #else
+@@ -1746,6 +1756,16 @@ void *SSL_COMP_get_compression_methods(v
+ int SSL_COMP_add_compression_method(int id,void *cm);
+ #endif
+ 
++/* NOTE: This function will be removed; it is only here for backwards
++ * compatibility for the API during testing. */
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len);
++
++/* TLS extensions functions */
++int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
++
++/* Pre-shared secret session resumption functions */
++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
++
+ /* BEGIN ERROR CODES */
+ /* The following lines are auto generated by the script mkerr.pl. Any changes
+  * made after this point may be overwritten when the script is next run.
+@@ -1948,6 +1968,7 @@ void ERR_load_SSL_strings(void);
+ #define SSL_F_TLS1_PRF					 284
+ #define SSL_F_TLS1_SETUP_KEY_BLOCK			 211
+ #define SSL_F_WRITE_PENDING				 212
++#define SSL_F_SSL_SET_SESSION_TICKET_EXT		 213
+ 
+ /* Reason codes. */
+ #define SSL_R_APP_DATA_IN_HANDSHAKE			 100
+Index: openssl-SNAP-20081111/ssl/ssl_sess.c
+===================================================================
+--- openssl-SNAP-20081111.orig/ssl/ssl_sess.c
++++ openssl-SNAP-20081111/ssl/ssl_sess.c
+@@ -834,6 +834,62 @@ long SSL_CTX_get_timeout(const SSL_CTX *
+ 	return(s->session_timeout);
+ 	}
+ 
++#ifndef OPENSSL_NO_TLSEXT
++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
++	STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
++	{
++	if (s == NULL) return(0);
++	s->tls_session_secret_cb = tls_session_secret_cb;
++	s->tls_session_secret_cb_arg = arg;
++	return(1);
++	}
++
++int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
++	{
++	if (s->version >= TLS1_VERSION)
++		{
++		if (s->tlsext_session_ticket)
++			{
++			OPENSSL_free(s->tlsext_session_ticket);
++			s->tlsext_session_ticket = NULL;
++			}
++
++		s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
++		if (!s->tlsext_session_ticket)
++			{
++			SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
++			return 0;
++			}
++
++		if (ext_data)
++			{
++			s->tlsext_session_ticket->length = ext_len;
++			s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
++			memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
++			}
++		else
++			{
++			s->tlsext_session_ticket->length = 0;
++			s->tlsext_session_ticket->data = NULL;
++			}
++
++		return 1;
++		}
++
++	return 0;
++	}
++
++/* NOTE: This function will be removed; it is only here for backwards
++ * compatibility for the API during testing. */
++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len)
++	{
++	if (ext_type != TLSEXT_TYPE_session_ticket)
++		return 0;
++
++	return SSL_set_session_ticket_ext(s, ext_data, ext_len);
++	}
++#endif /* OPENSSL_NO_TLSEXT */
++
+ typedef struct timeout_param_st
+ 	{
+ 	SSL_CTX *ctx;
+Index: openssl-SNAP-20081111/ssl/t1_lib.c
+===================================================================
+--- openssl-SNAP-20081111.orig/ssl/t1_lib.c
++++ openssl-SNAP-20081111/ssl/t1_lib.c
+@@ -154,6 +154,12 @@ int tls1_new(SSL *s)
+ 
+ void tls1_free(SSL *s)
+ 	{
++#ifndef OPENSSL_NO_TLSEXT
++	if (s->tlsext_session_ticket)
++		{
++		OPENSSL_free(s->tlsext_session_ticket);
++		}
++#endif /* OPENSSL_NO_TLSEXT */
+ 	ssl3_free(s);
+ 	}
+ 
+@@ -357,8 +363,23 @@ unsigned char *ssl_add_clienthello_tlsex
+ 		int ticklen;
+ 		if (s->session && s->session->tlsext_tick)
+ 			ticklen = s->session->tlsext_ticklen;
++		else if (s->session && s->tlsext_session_ticket &&
++			 s->tlsext_session_ticket->data)
++			{
++			ticklen = s->tlsext_session_ticket->length;
++			s->session->tlsext_tick = OPENSSL_malloc(ticklen);
++			if (!s->session->tlsext_tick)
++				return NULL;
++			memcpy(s->session->tlsext_tick,
++			       s->tlsext_session_ticket->data,
++			       ticklen);
++			s->session->tlsext_ticklen = ticklen;
++			}
+ 		else
+ 			ticklen = 0;
++		if (ticklen == 0 && s->tlsext_session_ticket &&
++		    s->tlsext_session_ticket->data == NULL)
++			goto skip_ext;
+ 		/* Check for enough room 2 for extension type, 2 for len
+  		 * rest for ticket
+   		 */
+@@ -371,6 +392,7 @@ unsigned char *ssl_add_clienthello_tlsex
+ 			ret += ticklen;
+ 			}
+ 		}
++		skip_ext:
+ 
+ #ifdef TLSEXT_TYPE_opaque_prf_input
+ 	if (s->s3->client_opaque_prf_input != NULL)
+@@ -1435,6 +1457,15 @@ int tls1_process_ticket(SSL *s, unsigned
+ 				s->tlsext_ticket_expected = 1;
+ 				return 0;	/* Cache miss */
+ 				}
++			if (s->tls_session_secret_cb)
++				{
++				/* Indicate cache miss here and instead of
++				 * generating the session from ticket now,
++				 * trigger abbreviated handshake based on
++				 * external mechanism to calculate the master
++				 * secret later. */
++				return 0;
++				}
+ 			return tls_decrypt_ticket(s, p, size, session_id, len,
+ 									ret);
+ 			}
+Index: openssl-SNAP-20081111/ssl/tls1.h
+===================================================================
+--- openssl-SNAP-20081111.orig/ssl/tls1.h
++++ openssl-SNAP-20081111/ssl/tls1.h
+@@ -512,6 +512,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
+ #define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"  /*master secret*/
+ #endif
+ 
++/* TLS Session Ticket extension struct */
++struct tls_session_ticket_ext_st
++	{
++	unsigned short length;
++	void *data;
++	};
++
+ #ifdef  __cplusplus
+ }
+ #endif
+Index: openssl-SNAP-20081111/util/ssleay.num
+===================================================================
+--- openssl-SNAP-20081111.orig/util/ssleay.num
++++ openssl-SNAP-20081111/util/ssleay.num
+@@ -254,3 +254,5 @@ PEM_read_bio_SSL_SESSION                
+ SSL_CTX_set_psk_server_callback         303	EXIST::FUNCTION:PSK
+ SSL_get_psk_identity                    304	EXIST::FUNCTION:PSK
+ PEM_write_SSL_SESSION                   305	EXIST:!WIN16:FUNCTION:
++SSL_set_session_ticket_ext		306	EXIST::FUNCTION:TLSEXT
++SSL_set_session_secret_cb		307	EXIST::FUNCTION:TLSEXT
diff --git a/contrib/wpa/src/Makefile b/contrib/wpa/src/Makefile
index bd1c160cd514..f47da7b5ac73 100644
--- a/contrib/wpa/src/Makefile
+++ b/contrib/wpa/src/Makefile
@@ -1,7 +1,7 @@
-SUBDIRS=common crypto drivers hlr_auc_gw eapol_supp eap_common eap_peer eap_server l2_packet radius rsn_supp tls utils wps
+SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet radius rsn_supp tls utils wps
 
 all:
-	@echo Nothing to be made.
+	for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
 
 clean:
 	for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
diff --git a/contrib/wpa/src/hlr_auc_gw/Makefile b/contrib/wpa/src/ap/Makefile
similarity index 65%
rename from contrib/wpa/src/hlr_auc_gw/Makefile
rename to contrib/wpa/src/ap/Makefile
index cffba620da04..9c41962fd7e1 100644
--- a/contrib/wpa/src/hlr_auc_gw/Makefile
+++ b/contrib/wpa/src/ap/Makefile
@@ -2,7 +2,6 @@ all:
 	@echo Nothing to be made.
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
 	rm -f *~ *.o *.d
 
 install:
diff --git a/contrib/wpa/hostapd/accounting.c b/contrib/wpa/src/ap/accounting.c
similarity index 96%
rename from contrib/wpa/hostapd/accounting.c
rename to contrib/wpa/src/ap/accounting.c
index ce71678af4e9..7939c680f580 100644
--- a/contrib/wpa/hostapd/accounting.c
+++ b/contrib/wpa/src/ap/accounting.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / RADIUS Accounting
- * Copyright (c) 2002-2008, Jouni Malinen 
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -12,15 +12,18 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#include "hostapd.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "drivers/driver.h"
 #include "radius/radius.h"
 #include "radius/radius_client.h"
-#include "eloop.h"
-#include "accounting.h"
+#include "hostapd.h"
 #include "ieee802_1x.h"
-#include "driver.h"
+#include "ap_config.h"
+#include "sta_info.h"
+#include "accounting.h"
 
 
 /* Default interval in seconds for polling TX/RX octets from the driver if
@@ -175,7 +178,6 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
 
  fail:
 	radius_msg_free(msg);
-	os_free(msg);
 	return NULL;
 }
 
@@ -184,7 +186,7 @@ static int accounting_sta_update_stats(struct hostapd_data *hapd,
 				       struct sta_info *sta,
 				       struct hostap_sta_driver_data *data)
 {
-	if (hostapd_read_sta_data(hapd, data, sta->addr))
+	if (hapd->drv.read_sta_data(hapd, data, sta->addr))
 		return -1;
 
 	if (sta->last_rx_bytes > data->rx_bytes)
@@ -247,7 +249,7 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
 	time(&sta->acct_session_start);
 	sta->last_rx_bytes = sta->last_tx_bytes = 0;
 	sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
-	hostapd_sta_clear_stats(hapd, sta->addr);
+	hapd->drv.sta_clear_stats(hapd, sta->addr);
 
 	if (!hapd->conf->radius->acct_server)
 		return;
@@ -364,7 +366,6 @@ static void accounting_sta_report(struct hostapd_data *hapd,
 
  fail:
 	radius_msg_free(msg);
-	os_free(msg);
 }
 
 
@@ -425,7 +426,7 @@ accounting_receive(struct radius_msg *msg, struct radius_msg *req,
 		   const u8 *shared_secret, size_t shared_secret_len,
 		   void *data)
 {
-	if (msg->hdr->code != RADIUS_CODE_ACCOUNTING_RESPONSE) {
+	if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_RESPONSE) {
 		printf("Unknown RADIUS message code\n");
 		return RADIUS_RX_UNKNOWN;
 	}
@@ -460,7 +461,6 @@ static void accounting_report_state(struct hostapd_data *hapd, int on)
 	{
 		printf("Could not add Acct-Terminate-Cause\n");
 		radius_msg_free(msg);
-		os_free(msg);
 		return;
 	}
 
@@ -497,14 +497,3 @@ void accounting_deinit(struct hostapd_data *hapd)
 {
 	accounting_report_state(hapd, 0);
 }
-
-
-int accounting_reconfig(struct hostapd_data *hapd,
-			struct hostapd_config *oldconf)
-{
-	if (!hapd->radius_client_reconfigured)
-		return 0;
-
-	accounting_deinit(hapd);
-	return accounting_init(hapd);
-}
diff --git a/contrib/wpa/hostapd/accounting.h b/contrib/wpa/src/ap/accounting.h
similarity index 64%
rename from contrib/wpa/hostapd/accounting.h
rename to contrib/wpa/src/ap/accounting.h
index 51e6b4d49870..f3d60f0155a6 100644
--- a/contrib/wpa/hostapd/accounting.h
+++ b/contrib/wpa/src/ap/accounting.h
@@ -15,12 +15,31 @@
 #ifndef ACCOUNTING_H
 #define ACCOUNTING_H
 
-void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta);
 void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta);
+#ifdef CONFIG_NO_ACCOUNTING
+static inline void accounting_sta_start(struct hostapd_data *hapd,
+					struct sta_info *sta)
+{
+}
+
+static inline void accounting_sta_stop(struct hostapd_data *hapd,
+				       struct sta_info *sta)
+{
+}
+
+static inline int accounting_init(struct hostapd_data *hapd)
+{
+	return 0;
+}
+
+static inline void accounting_deinit(struct hostapd_data *hapd)
+{
+}
+#else /* CONFIG_NO_ACCOUNTING */
+void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta);
 void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta);
 int accounting_init(struct hostapd_data *hapd);
 void accounting_deinit(struct hostapd_data *hapd);
-int accounting_reconfig(struct hostapd_data *hapd,
-			struct hostapd_config *oldconf);
+#endif /* CONFIG_NO_ACCOUNTING */
 
 #endif /* ACCOUNTING_H */
diff --git a/contrib/wpa/src/ap/ap_config.c b/contrib/wpa/src/ap/ap_config.c
new file mode 100644
index 000000000000..59969933e2f9
--- /dev/null
+++ b/contrib/wpa/src/ap/ap_config.c
@@ -0,0 +1,605 @@
+/*
+ * hostapd / Configuration helper functions
+ * Copyright (c) 2003-2009, Jouni Malinen 
+ *
+ * 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 "crypto/sha1.h"
+#include "radius/radius_client.h"
+#include "common/ieee802_11_defs.h"
+#include "common/eapol_common.h"
+#include "eap_common/eap_wsc_common.h"
+#include "eap_server/eap.h"
+#include "wpa_auth.h"
+#include "sta_info.h"
+#include "ap_config.h"
+
+
+static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
+{
+	struct hostapd_vlan *vlan, *prev;
+
+	vlan = bss->vlan;
+	prev = NULL;
+	while (vlan) {
+		prev = vlan;
+		vlan = vlan->next;
+		os_free(prev);
+	}
+
+	bss->vlan = NULL;
+}
+
+
+void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
+{
+	bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
+	bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
+	bss->logger_syslog = (unsigned int) -1;
+	bss->logger_stdout = (unsigned int) -1;
+
+	bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
+
+	bss->wep_rekeying_period = 300;
+	/* use key0 in individual key and key1 in broadcast key */
+	bss->broadcast_key_idx_min = 1;
+	bss->broadcast_key_idx_max = 2;
+	bss->eap_reauth_period = 3600;
+
+	bss->wpa_group_rekey = 600;
+	bss->wpa_gmk_rekey = 86400;
+	bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
+	bss->wpa_pairwise = WPA_CIPHER_TKIP;
+	bss->wpa_group = WPA_CIPHER_TKIP;
+	bss->rsn_pairwise = 0;
+
+	bss->max_num_sta = MAX_STA_COUNT;
+
+	bss->dtim_period = 2;
+
+	bss->radius_server_auth_port = 1812;
+	bss->ap_max_inactivity = AP_MAX_INACTIVITY;
+	bss->eapol_version = EAPOL_VERSION;
+
+	bss->max_listen_interval = 65535;
+
+#ifdef CONFIG_IEEE80211W
+	bss->assoc_sa_query_max_timeout = 1000;
+	bss->assoc_sa_query_retry_timeout = 201;
+#endif /* CONFIG_IEEE80211W */
+#ifdef EAP_SERVER_FAST
+	 /* both anonymous and authenticated provisioning */
+	bss->eap_fast_prov = 3;
+	bss->pac_key_lifetime = 7 * 24 * 60 * 60;
+	bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
+#endif /* EAP_SERVER_FAST */
+}
+
+
+struct hostapd_config * hostapd_config_defaults(void)
+{
+	struct hostapd_config *conf;
+	struct hostapd_bss_config *bss;
+	int i;
+	const int aCWmin = 4, aCWmax = 10;
+	const struct hostapd_wmm_ac_params ac_bk =
+		{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
+	const struct hostapd_wmm_ac_params ac_be =
+		{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
+	const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
+		{ aCWmin - 1, aCWmin, 2, 3000 / 32, 1 };
+	const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
+		{ aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 };
+
+	conf = os_zalloc(sizeof(*conf));
+	bss = os_zalloc(sizeof(*bss));
+	if (conf == NULL || bss == NULL) {
+		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
+			   "configuration data.");
+		os_free(conf);
+		os_free(bss);
+		return NULL;
+	}
+
+	bss->radius = os_zalloc(sizeof(*bss->radius));
+	if (bss->radius == NULL) {
+		os_free(conf);
+		os_free(bss);
+		return NULL;
+	}
+
+	hostapd_config_defaults_bss(bss);
+
+	conf->num_bss = 1;
+	conf->bss = bss;
+
+	conf->beacon_int = 100;
+	conf->rts_threshold = -1; /* use driver default: 2347 */
+	conf->fragm_threshold = -1; /* user driver default: 2346 */
+	conf->send_probe_response = 1;
+
+	for (i = 0; i < NUM_TX_QUEUES; i++)
+		conf->tx_queue[i].aifs = -1; /* use hw default */
+
+	conf->wmm_ac_params[0] = ac_be;
+	conf->wmm_ac_params[1] = ac_bk;
+	conf->wmm_ac_params[2] = ac_vi;
+	conf->wmm_ac_params[3] = ac_vo;
+
+	conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
+
+	return conf;
+}
+
+
+int hostapd_mac_comp(const void *a, const void *b)
+{
+	return os_memcmp(a, b, sizeof(macaddr));
+}
+
+
+int hostapd_mac_comp_empty(const void *a)
+{
+	macaddr empty = { 0 };
+	return os_memcmp(a, empty, sizeof(macaddr));
+}
+
+
+static int hostapd_config_read_wpa_psk(const char *fname,
+				       struct hostapd_ssid *ssid)
+{
+	FILE *f;
+	char buf[128], *pos;
+	int line = 0, ret = 0, len, ok;
+	u8 addr[ETH_ALEN];
+	struct hostapd_wpa_psk *psk;
+
+	if (!fname)
+		return 0;
+
+	f = fopen(fname, "r");
+	if (!f) {
+		wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname);
+		return -1;
+	}
+
+	while (fgets(buf, sizeof(buf), f)) {
+		line++;
+
+		if (buf[0] == '#')
+			continue;
+		pos = buf;
+		while (*pos != '\0') {
+			if (*pos == '\n') {
+				*pos = '\0';
+				break;
+			}
+			pos++;
+		}
+		if (buf[0] == '\0')
+			continue;
+
+		if (hwaddr_aton(buf, addr)) {
+			wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
+				   "line %d in '%s'", buf, line, fname);
+			ret = -1;
+			break;
+		}
+
+		psk = os_zalloc(sizeof(*psk));
+		if (psk == NULL) {
+			wpa_printf(MSG_ERROR, "WPA PSK allocation failed");
+			ret = -1;
+			break;
+		}
+		if (is_zero_ether_addr(addr))
+			psk->group = 1;
+		else
+			os_memcpy(psk->addr, addr, ETH_ALEN);
+
+		pos = buf + 17;
+		if (*pos == '\0') {
+			wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
+				   line, fname);
+			os_free(psk);
+			ret = -1;
+			break;
+		}
+		pos++;
+
+		ok = 0;
+		len = os_strlen(pos);
+		if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
+			ok = 1;
+		else if (len >= 8 && len < 64) {
+			pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
+				    4096, psk->psk, PMK_LEN);
+			ok = 1;
+		}
+		if (!ok) {
+			wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
+				   "'%s'", pos, line, fname);
+			os_free(psk);
+			ret = -1;
+			break;
+		}
+
+		psk->next = ssid->wpa_psk;
+		ssid->wpa_psk = psk;
+	}
+
+	fclose(f);
+
+	return ret;
+}
+
+
+static int hostapd_derive_psk(struct hostapd_ssid *ssid)
+{
+	ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
+	if (ssid->wpa_psk == NULL) {
+		wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
+		return -1;
+	}
+	wpa_hexdump_ascii(MSG_DEBUG, "SSID",
+			  (u8 *) ssid->ssid, ssid->ssid_len);
+	wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)",
+			      (u8 *) ssid->wpa_passphrase,
+			      os_strlen(ssid->wpa_passphrase));
+	pbkdf2_sha1(ssid->wpa_passphrase,
+		    ssid->ssid, ssid->ssid_len,
+		    4096, ssid->wpa_psk->psk, PMK_LEN);
+	wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)",
+			ssid->wpa_psk->psk, PMK_LEN);
+	return 0;
+}
+
+
+int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
+{
+	struct hostapd_ssid *ssid = &conf->ssid;
+
+	if (ssid->wpa_passphrase != NULL) {
+		if (ssid->wpa_psk != NULL) {
+			wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
+				   "instead of passphrase");
+		} else {
+			wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on "
+				   "passphrase");
+			if (hostapd_derive_psk(ssid) < 0)
+				return -1;
+		}
+		ssid->wpa_psk->group = 1;
+	}
+
+	if (ssid->wpa_psk_file) {
+		if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file,
+						&conf->ssid))
+			return -1;
+	}
+
+	return 0;
+}
+
+
+int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b)
+{
+	int i;
+
+	if (a->idx != b->idx || a->default_len != b->default_len)
+		return 1;
+	for (i = 0; i < NUM_WEP_KEYS; i++)
+		if (a->len[i] != b->len[i] ||
+		    os_memcmp(a->key[i], b->key[i], a->len[i]) != 0)
+			return 1;
+	return 0;
+}
+
+
+static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
+				       int num_servers)
+{
+	int i;
+
+	for (i = 0; i < num_servers; i++) {
+		os_free(servers[i].shared_secret);
+	}
+	os_free(servers);
+}
+
+
+static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
+{
+	os_free(user->identity);
+	os_free(user->password);
+	os_free(user);
+}
+
+
+static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
+{
+	int i;
+	for (i = 0; i < NUM_WEP_KEYS; i++) {
+		os_free(keys->key[i]);
+		keys->key[i] = NULL;
+	}
+}
+
+
+static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
+{
+	struct hostapd_wpa_psk *psk, *prev;
+	struct hostapd_eap_user *user, *prev_user;
+
+	if (conf == NULL)
+		return;
+
+	psk = conf->ssid.wpa_psk;
+	while (psk) {
+		prev = psk;
+		psk = psk->next;
+		os_free(prev);
+	}
+
+	os_free(conf->ssid.wpa_passphrase);
+	os_free(conf->ssid.wpa_psk_file);
+	hostapd_config_free_wep(&conf->ssid.wep);
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+	os_free(conf->ssid.vlan_tagged_interface);
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+
+	user = conf->eap_user;
+	while (user) {
+		prev_user = user;
+		user = user->next;
+		hostapd_config_free_eap_user(prev_user);
+	}
+
+	os_free(conf->dump_log_name);
+	os_free(conf->eap_req_id_text);
+	os_free(conf->accept_mac);
+	os_free(conf->deny_mac);
+	os_free(conf->nas_identifier);
+	hostapd_config_free_radius(conf->radius->auth_servers,
+				   conf->radius->num_auth_servers);
+	hostapd_config_free_radius(conf->radius->acct_servers,
+				   conf->radius->num_acct_servers);
+	os_free(conf->rsn_preauth_interfaces);
+	os_free(conf->ctrl_interface);
+	os_free(conf->ca_cert);
+	os_free(conf->server_cert);
+	os_free(conf->private_key);
+	os_free(conf->private_key_passwd);
+	os_free(conf->dh_file);
+	os_free(conf->pac_opaque_encr_key);
+	os_free(conf->eap_fast_a_id);
+	os_free(conf->eap_fast_a_id_info);
+	os_free(conf->eap_sim_db);
+	os_free(conf->radius_server_clients);
+	os_free(conf->test_socket);
+	os_free(conf->radius);
+	hostapd_config_free_vlan(conf);
+	if (conf->ssid.dyn_vlan_keys) {
+		struct hostapd_ssid *ssid = &conf->ssid;
+		size_t i;
+		for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
+			if (ssid->dyn_vlan_keys[i] == NULL)
+				continue;
+			hostapd_config_free_wep(ssid->dyn_vlan_keys[i]);
+			os_free(ssid->dyn_vlan_keys[i]);
+		}
+		os_free(ssid->dyn_vlan_keys);
+		ssid->dyn_vlan_keys = NULL;
+	}
+
+#ifdef CONFIG_IEEE80211R
+	{
+		struct ft_remote_r0kh *r0kh, *r0kh_prev;
+		struct ft_remote_r1kh *r1kh, *r1kh_prev;
+
+		r0kh = conf->r0kh_list;
+		conf->r0kh_list = NULL;
+		while (r0kh) {
+			r0kh_prev = r0kh;
+			r0kh = r0kh->next;
+			os_free(r0kh_prev);
+		}
+
+		r1kh = conf->r1kh_list;
+		conf->r1kh_list = NULL;
+		while (r1kh) {
+			r1kh_prev = r1kh;
+			r1kh = r1kh->next;
+			os_free(r1kh_prev);
+		}
+	}
+#endif /* CONFIG_IEEE80211R */
+
+#ifdef CONFIG_WPS
+	os_free(conf->wps_pin_requests);
+	os_free(conf->device_name);
+	os_free(conf->manufacturer);
+	os_free(conf->model_name);
+	os_free(conf->model_number);
+	os_free(conf->serial_number);
+	os_free(conf->device_type);
+	os_free(conf->config_methods);
+	os_free(conf->ap_pin);
+	os_free(conf->extra_cred);
+	os_free(conf->ap_settings);
+	os_free(conf->upnp_iface);
+	os_free(conf->friendly_name);
+	os_free(conf->manufacturer_url);
+	os_free(conf->model_description);
+	os_free(conf->model_url);
+	os_free(conf->upc);
+#endif /* CONFIG_WPS */
+}
+
+
+/**
+ * hostapd_config_free - Free hostapd configuration
+ * @conf: Configuration data from hostapd_config_read().
+ */
+void hostapd_config_free(struct hostapd_config *conf)
+{
+	size_t i;
+
+	if (conf == NULL)
+		return;
+
+	for (i = 0; i < conf->num_bss; i++)
+		hostapd_config_free_bss(&conf->bss[i]);
+	os_free(conf->bss);
+	os_free(conf->supported_rates);
+	os_free(conf->basic_rates);
+
+	os_free(conf);
+}
+
+
+/**
+ * hostapd_maclist_found - Find a MAC address from a list
+ * @list: MAC address list
+ * @num_entries: Number of addresses in the list
+ * @addr: Address to search for
+ * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed
+ * Returns: 1 if address is in the list or 0 if not.
+ *
+ * Perform a binary search for given MAC address from a pre-sorted list.
+ */
+int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
+			  const u8 *addr, int *vlan_id)
+{
+	int start, end, middle, res;
+
+	start = 0;
+	end = num_entries - 1;
+
+	while (start <= end) {
+		middle = (start + end) / 2;
+		res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
+		if (res == 0) {
+			if (vlan_id)
+				*vlan_id = list[middle].vlan_id;
+			return 1;
+		}
+		if (res < 0)
+			start = middle + 1;
+		else
+			end = middle - 1;
+	}
+
+	return 0;
+}
+
+
+int hostapd_rate_found(int *list, int rate)
+{
+	int i;
+
+	if (list == NULL)
+		return 0;
+
+	for (i = 0; list[i] >= 0; i++)
+		if (list[i] == rate)
+			return 1;
+
+	return 0;
+}
+
+
+const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
+{
+	struct hostapd_vlan *v = vlan;
+	while (v) {
+		if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD)
+			return v->ifname;
+		v = v->next;
+	}
+	return NULL;
+}
+
+
+const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
+			   const u8 *addr, const u8 *prev_psk)
+{
+	struct hostapd_wpa_psk *psk;
+	int next_ok = prev_psk == NULL;
+
+	for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
+		if (next_ok &&
+		    (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0))
+			return psk->psk;
+
+		if (psk->psk == prev_psk)
+			next_ok = 1;
+	}
+
+	return NULL;
+}
+
+
+const struct hostapd_eap_user *
+hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
+		     size_t identity_len, int phase2)
+{
+	struct hostapd_eap_user *user = conf->eap_user;
+
+#ifdef CONFIG_WPS
+	if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
+	    os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
+		static struct hostapd_eap_user wsc_enrollee;
+		os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
+		wsc_enrollee.methods[0].method = eap_server_get_type(
+			"WSC", &wsc_enrollee.methods[0].vendor);
+		return &wsc_enrollee;
+	}
+
+	if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
+	    os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
+		static struct hostapd_eap_user wsc_registrar;
+		os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
+		wsc_registrar.methods[0].method = eap_server_get_type(
+			"WSC", &wsc_registrar.methods[0].vendor);
+		wsc_registrar.password = (u8 *) conf->ap_pin;
+		wsc_registrar.password_len = conf->ap_pin ?
+			os_strlen(conf->ap_pin) : 0;
+		return &wsc_registrar;
+	}
+#endif /* CONFIG_WPS */
+
+	while (user) {
+		if (!phase2 && user->identity == NULL) {
+			/* Wildcard match */
+			break;
+		}
+
+		if (user->phase2 == !!phase2 && user->wildcard_prefix &&
+		    identity_len >= user->identity_len &&
+		    os_memcmp(user->identity, identity, user->identity_len) ==
+		    0) {
+			/* Wildcard prefix match */
+			break;
+		}
+
+		if (user->phase2 == !!phase2 &&
+		    user->identity_len == identity_len &&
+		    os_memcmp(user->identity, identity, identity_len) == 0)
+			break;
+		user = user->next;
+	}
+
+	return user;
+}
diff --git a/contrib/wpa/hostapd/config.h b/contrib/wpa/src/ap/ap_config.h
similarity index 90%
rename from contrib/wpa/hostapd/config.h
rename to contrib/wpa/src/ap/ap_config.h
index ea530d45d169..f509b5bbb197 100644
--- a/contrib/wpa/hostapd/config.h
+++ b/contrib/wpa/src/ap/ap_config.h
@@ -1,7 +1,6 @@
 /*
- * hostapd / Configuration file
- * Copyright (c) 2003-2007, Jouni Malinen 
- * Copyright (c) 2007-2008, Intel Corporation
+ * hostapd / Configuration definitions and helpers functions
+ * Copyright (c) 2003-2009, Jouni Malinen 
  *
  * 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
@@ -13,16 +12,15 @@
  * See README and COPYING for more details.
  */
 
-#ifndef CONFIG_H
-#define CONFIG_H
+#ifndef HOSTAPD_CONFIG_H
+#define HOSTAPD_CONFIG_H
 
-#include "defs.h"
+#include "common/defs.h"
 #include "ip_addr.h"
-#include "wpa_common.h"
+#include "common/wpa_common.h"
 
-#ifndef IFNAMSIZ
-#define IFNAMSIZ 16
-#endif
+#define MAX_STA_COUNT 2007
+#define MAX_VLAN_ID 4094
 
 typedef u8 macaddr[ETH_ALEN];
 
@@ -171,6 +169,7 @@ struct hostapd_bss_config {
 	struct hostapd_ip_addr own_ip_addr;
 	char *nas_identifier;
 	struct hostapd_radius_servers *radius;
+	int acct_interim_interval;
 
 	struct hostapd_ssid ssid;
 
@@ -198,6 +197,7 @@ struct hostapd_bss_config {
 	int num_accept_mac;
 	struct mac_acl_entry *deny_mac;
 	int num_deny_mac;
+	int wds_sta;
 
 	int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
 			* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
@@ -205,11 +205,7 @@ struct hostapd_bss_config {
 	int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
 	int wpa_key_mgmt;
 #ifdef CONFIG_IEEE80211W
-	enum {
-		NO_IEEE80211W = 0,
-		IEEE80211W_OPTIONAL = 1,
-		IEEE80211W_REQUIRED = 2
-	} ieee80211w;
+	enum mfp_options ieee80211w;
 	/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
 	unsigned int assoc_sa_query_max_timeout;
 	/* dot11AssociationSAQueryRetryTimeout (in TUs) */
@@ -238,7 +234,9 @@ struct hostapd_bss_config {
 #endif /* CONFIG_IEEE80211R */
 
 	char *ctrl_interface; /* directory for UNIX domain sockets */
+#ifndef CONFIG_NATIVE_WINDOWS
 	gid_t ctrl_interface_gid;
+#endif /* CONFIG_NATIVE_WINDOWS */
 	int ctrl_interface_gid_set;
 
 	char *ca_cert;
@@ -272,6 +270,7 @@ struct hostapd_bss_config {
 	int ignore_broadcast_ssid;
 
 	int wmm_enabled;
+	int wmm_uapsd;
 
 	struct hostapd_vlan *vlan, *vlan_tail;
 
@@ -316,14 +315,6 @@ struct hostapd_bss_config {
 };
 
 
-typedef enum {
-	HOSTAPD_MODE_IEEE80211B,
-	HOSTAPD_MODE_IEEE80211G,
-	HOSTAPD_MODE_IEEE80211A,
-	NUM_HOSTAPD_MODES
-} hostapd_hw_mode;
-
-
 /**
  * struct hostapd_config - Per-radio interface configuration
  */
@@ -336,7 +327,7 @@ struct hostapd_config {
 	int fragm_threshold;
 	u8 send_probe_response;
 	u8 channel;
-	hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
+	enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
 	enum {
 		LONG_PREAMBLE = 0,
 		SHORT_PREAMBLE = 1
@@ -353,9 +344,6 @@ struct hostapd_config {
 
 	const struct wpa_driver_ops *driver;
 
-	int passive_scan_interval; /* seconds, 0 = disabled */
-	int passive_scan_listen; /* usec */
-	int passive_scan_mode;
 	int ap_table_max_size;
 	int ap_table_expiration_time;
 
@@ -379,16 +367,8 @@ struct hostapd_config {
 	 */
 	struct hostapd_wmm_ac_params wmm_ac_params[4];
 
-	enum {
-		INTERNAL_BRIDGE_DO_NOT_CONTROL = -1,
-		INTERNAL_BRIDGE_DISABLED = 0,
-		INTERNAL_BRIDGE_ENABLED = 1
-	} bridge_packets;
-
-#ifdef CONFIG_IEEE80211N
 	int ht_op_mode_fixed;
 	u16 ht_capab;
-#endif /* CONFIG_IEEE80211N */
 	int ieee80211n;
 	int secondary_channel;
 };
@@ -396,7 +376,8 @@ struct hostapd_config {
 
 int hostapd_mac_comp(const void *a, const void *b);
 int hostapd_mac_comp_empty(const void *a);
-struct hostapd_config * hostapd_config_read(const char *fname);
+struct hostapd_config * hostapd_config_defaults(void);
+void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
 void hostapd_config_free(struct hostapd_config *conf);
 int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
 			  const u8 *addr, int *vlan_id);
@@ -412,4 +393,4 @@ const struct hostapd_eap_user *
 hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
 		     size_t identity_len, int phase2);
 
-#endif /* CONFIG_H */
+#endif /* HOSTAPD_CONFIG_H */
diff --git a/contrib/wpa/src/ap/ap_drv_ops.c b/contrib/wpa/src/ap/ap_drv_ops.c
new file mode 100644
index 000000000000..f264a3e407ff
--- /dev/null
+++ b/contrib/wpa/src/ap/ap_drv_ops.c
@@ -0,0 +1,621 @@
+/*
+ * hostapd - Driver operations
+ * Copyright (c) 2009-2010, Jouni Malinen 
+ *
+ * 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 "drivers/driver.h"
+#include "common/ieee802_11_defs.h"
+#include "hostapd.h"
+#include "ieee802_11.h"
+#include "sta_info.h"
+#include "ap_config.h"
+#include "ap_drv_ops.h"
+
+
+static int hostapd_sta_flags_to_drv(int flags)
+{
+	int res = 0;
+	if (flags & WLAN_STA_AUTHORIZED)
+		res |= WPA_STA_AUTHORIZED;
+	if (flags & WLAN_STA_WMM)
+		res |= WPA_STA_WMM;
+	if (flags & WLAN_STA_SHORT_PREAMBLE)
+		res |= WPA_STA_SHORT_PREAMBLE;
+	if (flags & WLAN_STA_MFP)
+		res |= WPA_STA_MFP;
+	return res;
+}
+
+
+static int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
+{
+	struct wpabuf *beacon, *proberesp;
+	int ret;
+
+	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
+		return 0;
+
+	beacon = hapd->wps_beacon_ie;
+	proberesp = hapd->wps_probe_resp_ie;
+
+	ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp);
+
+	return ret;
+}
+
+
+static int hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg,
+			   size_t len)
+{
+	if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
+		return 0;
+	return hapd->driver->send_mlme(hapd->drv_priv, msg, len);
+}
+
+
+static int hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr,
+			      const u8 *data, size_t data_len, int encrypt)
+{
+	if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
+		return 0;
+	return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
+					     data_len, encrypt,
+					     hapd->own_addr);
+}
+
+
+static int hostapd_set_authorized(struct hostapd_data *hapd,
+				  struct sta_info *sta, int authorized)
+{
+	if (authorized) {
+		return hostapd_sta_set_flags(hapd, sta->addr,
+					     hostapd_sta_flags_to_drv(
+						     sta->flags),
+					     WPA_STA_AUTHORIZED, ~0);
+	}
+
+	return hostapd_sta_set_flags(hapd, sta->addr,
+				     hostapd_sta_flags_to_drv(sta->flags),
+				     0, ~WPA_STA_AUTHORIZED);
+}
+
+
+static int hostapd_set_key(const char *ifname, struct hostapd_data *hapd,
+			   enum wpa_alg alg, const u8 *addr, int key_idx,
+			   int set_tx, const u8 *seq, size_t seq_len,
+			   const u8 *key, size_t key_len)
+{
+	if (hapd->driver == NULL || hapd->driver->set_key == NULL)
+		return 0;
+	return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
+				     key_idx, set_tx, seq, seq_len, key,
+				     key_len);
+}
+
+
+static int hostapd_read_sta_data(struct hostapd_data *hapd,
+				 struct hostap_sta_driver_data *data,
+				 const u8 *addr)
+{
+	if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
+		return -1;
+	return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
+}
+
+
+static int hostapd_sta_clear_stats(struct hostapd_data *hapd, const u8 *addr)
+{
+	if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
+		return 0;
+	return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
+}
+
+
+static int hostapd_set_sta_flags(struct hostapd_data *hapd,
+				 struct sta_info *sta)
+{
+	int set_flags, total_flags, flags_and, flags_or;
+	total_flags = hostapd_sta_flags_to_drv(sta->flags);
+	set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
+	if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
+	     sta->auth_alg == WLAN_AUTH_FT) &&
+	    sta->flags & WLAN_STA_AUTHORIZED)
+		set_flags |= WPA_STA_AUTHORIZED;
+	flags_or = total_flags & set_flags;
+	flags_and = total_flags | ~set_flags;
+	return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
+				     flags_or, flags_and);
+}
+
+
+static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd,
+				     const char *ifname, int enabled)
+{
+	struct wpa_bss_params params;
+	os_memset(¶ms, 0, sizeof(params));
+	params.ifname = ifname;
+	params.enabled = enabled;
+	if (enabled) {
+		params.wpa = hapd->conf->wpa;
+		params.ieee802_1x = hapd->conf->ieee802_1x;
+		params.wpa_group = hapd->conf->wpa_group;
+		params.wpa_pairwise = hapd->conf->wpa_pairwise;
+		params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
+		params.rsn_preauth = hapd->conf->rsn_preauth;
+	}
+	return hostapd_set_ieee8021x(hapd, ¶ms);
+}
+
+
+static int hostapd_set_radius_acl_auth(struct hostapd_data *hapd,
+				       const u8 *mac, int accepted,
+				       u32 session_timeout)
+{
+	if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
+		return 0;
+	return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
+						 session_timeout);
+}
+
+
+static int hostapd_set_radius_acl_expire(struct hostapd_data *hapd,
+					 const u8 *mac)
+{
+	if (hapd->driver == NULL ||
+	    hapd->driver->set_radius_acl_expire == NULL)
+		return 0;
+	return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
+}
+
+
+static int hostapd_set_bss_params(struct hostapd_data *hapd,
+				  int use_protection)
+{
+	int ret = 0;
+	int preamble;
+#ifdef CONFIG_IEEE80211N
+	u8 buf[60], *ht_capab, *ht_oper, *pos;
+
+	pos = buf;
+	ht_capab = pos;
+	pos = hostapd_eid_ht_capabilities(hapd, pos);
+	ht_oper = pos;
+	pos = hostapd_eid_ht_operation(hapd, pos);
+	if (pos > ht_oper && ht_oper > ht_capab &&
+	    hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1],
+				  ht_oper + 2, ht_oper[1])) {
+		wpa_printf(MSG_ERROR, "Could not set HT capabilities "
+			   "for kernel driver");
+		ret = -1;
+	}
+
+#endif /* CONFIG_IEEE80211N */
+
+	if (hostapd_set_cts_protect(hapd, use_protection)) {
+		wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel "
+			   "driver");
+		ret = -1;
+	}
+
+	if (hapd->iface->current_mode &&
+	    hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
+	    hostapd_set_short_slot_time(hapd,
+					hapd->iface->num_sta_no_short_slot_time
+					> 0 ? 0 : 1)) {
+		wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option "
+			   "in kernel driver");
+		ret = -1;
+	}
+
+	if (hapd->iface->num_sta_no_short_preamble == 0 &&
+	    hapd->iconf->preamble == SHORT_PREAMBLE)
+		preamble = SHORT_PREAMBLE;
+	else
+		preamble = LONG_PREAMBLE;
+	if (hostapd_set_preamble(hapd, preamble)) {
+		wpa_printf(MSG_ERROR, "Could not set preamble for kernel "
+			   "driver");
+		ret = -1;
+	}
+
+	return ret;
+}
+
+
+static int hostapd_set_beacon(struct hostapd_data *hapd,
+			      const u8 *head, size_t head_len,
+			      const u8 *tail, size_t tail_len, int dtim_period,
+			      int beacon_int)
+{
+	if (hapd->driver == NULL || hapd->driver->set_beacon == NULL)
+		return 0;
+	return hapd->driver->set_beacon(hapd->drv_priv,
+					head, head_len, tail, tail_len,
+					dtim_period, beacon_int);
+}
+
+
+static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
+{
+	char force_ifname[IFNAMSIZ];
+	u8 if_addr[ETH_ALEN];
+	return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, NULL,
+			      force_ifname, if_addr);
+}
+
+static int hostapd_vlan_if_remove(struct hostapd_data *hapd,
+				  const char *ifname)
+{
+	return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
+}
+
+
+static int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr,
+			       int aid, int val)
+{
+	if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
+		return 0;
+	return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val);
+}
+
+
+static int hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd,
+				const u8 *addr, int vlan_id)
+{
+	if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
+		return 0;
+	return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
+					  vlan_id);
+}
+
+
+static int hostapd_get_inact_sec(struct hostapd_data *hapd, const u8 *addr)
+{
+	if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
+		return 0;
+	return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
+}
+
+
+static int hostapd_sta_deauth(struct hostapd_data *hapd, const u8 *addr,
+			      int reason)
+{
+	if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
+		return 0;
+	return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
+					reason);
+}
+
+
+static int hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr,
+				int reason)
+{
+	if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
+		return 0;
+	return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
+					  reason);
+}
+
+
+static int hostapd_sta_add(struct hostapd_data *hapd,
+			   const u8 *addr, u16 aid, u16 capability,
+			   const u8 *supp_rates, size_t supp_rates_len,
+			   u16 listen_interval,
+			   const struct ieee80211_ht_capabilities *ht_capab)
+{
+	struct hostapd_sta_add_params params;
+
+	if (hapd->driver == NULL)
+		return 0;
+	if (hapd->driver->sta_add == NULL)
+		return 0;
+
+	os_memset(¶ms, 0, sizeof(params));
+	params.addr = addr;
+	params.aid = aid;
+	params.capability = capability;
+	params.supp_rates = supp_rates;
+	params.supp_rates_len = supp_rates_len;
+	params.listen_interval = listen_interval;
+	params.ht_capabilities = ht_capab;
+	return hapd->driver->sta_add(hapd->drv_priv, ¶ms);
+}
+
+
+static int hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr)
+{
+	if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
+		return 0;
+	return hapd->driver->sta_remove(hapd->drv_priv, addr);
+}
+
+
+static int hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled)
+{
+	if (hapd->driver == NULL ||
+	    hapd->driver->hapd_set_countermeasures == NULL)
+		return 0;
+	return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
+}
+
+
+void hostapd_set_driver_ops(struct hostapd_driver_ops *ops)
+{
+	ops->set_ap_wps_ie = hostapd_set_ap_wps_ie;
+	ops->send_mgmt_frame = hostapd_send_mgmt_frame;
+	ops->send_eapol = hostapd_send_eapol;
+	ops->set_authorized = hostapd_set_authorized;
+	ops->set_key = hostapd_set_key;
+	ops->read_sta_data = hostapd_read_sta_data;
+	ops->sta_clear_stats = hostapd_sta_clear_stats;
+	ops->set_sta_flags = hostapd_set_sta_flags;
+	ops->set_drv_ieee8021x = hostapd_set_drv_ieee8021x;
+	ops->set_radius_acl_auth = hostapd_set_radius_acl_auth;
+	ops->set_radius_acl_expire = hostapd_set_radius_acl_expire;
+	ops->set_bss_params = hostapd_set_bss_params;
+	ops->set_beacon = hostapd_set_beacon;
+	ops->vlan_if_add = hostapd_vlan_if_add;
+	ops->vlan_if_remove = hostapd_vlan_if_remove;
+	ops->set_wds_sta = hostapd_set_wds_sta;
+	ops->set_sta_vlan = hostapd_set_sta_vlan;
+	ops->get_inact_sec = hostapd_get_inact_sec;
+	ops->sta_deauth = hostapd_sta_deauth;
+	ops->sta_disassoc = hostapd_sta_disassoc;
+	ops->sta_add = hostapd_sta_add;
+	ops->sta_remove = hostapd_sta_remove;
+	ops->set_countermeasures = hostapd_set_countermeasures;
+}
+
+
+int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
+{
+	if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
+		return 0;
+	return hapd->driver->set_privacy(hapd->drv_priv, enabled);
+}
+
+
+int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
+			     size_t elem_len)
+{
+	if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
+		return 0;
+	return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len);
+}
+
+
+int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
+{
+	if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
+		return 0;
+	return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len);
+}
+
+
+int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
+{
+	if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
+		return 0;
+	return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len);
+}
+
+
+int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
+		   const char *ifname, const u8 *addr, void *bss_ctx,
+		   void **drv_priv, char *force_ifname, u8 *if_addr)
+{
+	if (hapd->driver == NULL || hapd->driver->if_add == NULL)
+		return -1;
+	return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
+				    bss_ctx, drv_priv, force_ifname, if_addr);
+}
+
+
+int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
+		      const char *ifname)
+{
+	if (hapd->driver == NULL || hapd->driver->if_remove == NULL)
+		return -1;
+	return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
+}
+
+
+int hostapd_set_ieee8021x(struct hostapd_data *hapd,
+			  struct wpa_bss_params *params)
+{
+	if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL)
+		return 0;
+	return hapd->driver->set_ieee8021x(hapd->drv_priv, params);
+}
+
+
+int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
+		       const u8 *addr, int idx, u8 *seq)
+{
+	if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL)
+		return 0;
+	return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx,
+					seq);
+}
+
+
+int hostapd_flush(struct hostapd_data *hapd)
+{
+	if (hapd->driver == NULL || hapd->driver->flush == NULL)
+		return 0;
+	return hapd->driver->flush(hapd->drv_priv);
+}
+
+
+int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq,
+		     int channel, int ht_enabled, int sec_channel_offset)
+{
+	struct hostapd_freq_params data;
+	if (hapd->driver == NULL)
+		return 0;
+	if (hapd->driver->set_freq == NULL)
+		return 0;
+	os_memset(&data, 0, sizeof(data));
+	data.mode = mode;
+	data.freq = freq;
+	data.channel = channel;
+	data.ht_enabled = ht_enabled;
+	data.sec_channel_offset = sec_channel_offset;
+	return hapd->driver->set_freq(hapd->drv_priv, &data);
+}
+
+int hostapd_set_rts(struct hostapd_data *hapd, int rts)
+{
+	if (hapd->driver == NULL || hapd->driver->set_rts == NULL)
+		return 0;
+	return hapd->driver->set_rts(hapd->drv_priv, rts);
+}
+
+
+int hostapd_set_frag(struct hostapd_data *hapd, int frag)
+{
+	if (hapd->driver == NULL || hapd->driver->set_frag == NULL)
+		return 0;
+	return hapd->driver->set_frag(hapd->drv_priv, frag);
+}
+
+
+int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
+			  int total_flags, int flags_or, int flags_and)
+{
+	if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
+		return 0;
+	return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
+					   flags_or, flags_and);
+}
+
+
+int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
+			  int *basic_rates, int mode)
+{
+	if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL)
+		return 0;
+	return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates,
+					   basic_rates, mode);
+}
+
+
+int hostapd_set_country(struct hostapd_data *hapd, const char *country)
+{
+	if (hapd->driver == NULL ||
+	    hapd->driver->set_country == NULL)
+		return 0;
+	return hapd->driver->set_country(hapd->drv_priv, country);
+}
+
+
+int hostapd_set_cts_protect(struct hostapd_data *hapd, int value)
+{
+	if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL)
+		return 0;
+	return hapd->driver->set_cts_protect(hapd->drv_priv, value);
+}
+
+
+int hostapd_set_preamble(struct hostapd_data *hapd, int value)
+{
+	if (hapd->driver == NULL || hapd->driver->set_preamble == NULL)
+		return 0;
+	return hapd->driver->set_preamble(hapd->drv_priv, value);
+}
+
+
+int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value)
+{
+	if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL)
+		return 0;
+	return hapd->driver->set_short_slot_time(hapd->drv_priv, value);
+}
+
+
+int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
+				int cw_min, int cw_max, int burst_time)
+{
+	if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL)
+		return 0;
+	return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs,
+						 cw_min, cw_max, burst_time);
+}
+
+
+int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
+			   const u8 *mask)
+{
+	if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL)
+		return 1;
+	return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask);
+}
+
+
+struct hostapd_hw_modes *
+hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
+			    u16 *flags)
+{
+	if (hapd->driver == NULL ||
+	    hapd->driver->get_hw_feature_data == NULL)
+		return NULL;
+	return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
+						 flags);
+}
+
+
+int hostapd_driver_commit(struct hostapd_data *hapd)
+{
+	if (hapd->driver == NULL || hapd->driver->commit == NULL)
+		return 0;
+	return hapd->driver->commit(hapd->drv_priv);
+}
+
+
+int hostapd_set_ht_params(struct hostapd_data *hapd,
+			  const u8 *ht_capab, size_t ht_capab_len,
+			  const u8 *ht_oper, size_t ht_oper_len)
+{
+	if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL ||
+	    ht_capab == NULL || ht_oper == NULL)
+		return 0;
+	return hapd->driver->set_ht_params(hapd->drv_priv,
+					   ht_capab, ht_capab_len,
+					   ht_oper, ht_oper_len);
+}
+
+
+int hostapd_drv_none(struct hostapd_data *hapd)
+{
+	return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
+}
+
+
+int hostapd_driver_scan(struct hostapd_data *hapd,
+			struct wpa_driver_scan_params *params)
+{
+	if (hapd->driver && hapd->driver->scan2)
+		return hapd->driver->scan2(hapd->drv_priv, params);
+	return -1;
+}
+
+
+struct wpa_scan_results * hostapd_driver_get_scan_results(
+	struct hostapd_data *hapd)
+{
+	if (hapd->driver && hapd->driver->get_scan_results2)
+		return hapd->driver->get_scan_results2(hapd->drv_priv);
+	return NULL;
+}
diff --git a/contrib/wpa/src/ap/ap_drv_ops.h b/contrib/wpa/src/ap/ap_drv_ops.h
new file mode 100644
index 000000000000..9b75d096a009
--- /dev/null
+++ b/contrib/wpa/src/ap/ap_drv_ops.h
@@ -0,0 +1,67 @@
+/*
+ * hostapd - Driver operations
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 AP_DRV_OPS
+#define AP_DRV_OPS
+
+enum wpa_driver_if_type;
+struct wpa_bss_params;
+struct wpa_driver_scan_params;
+
+void hostapd_set_driver_ops(struct hostapd_driver_ops *ops);
+int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
+int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
+			     size_t elem_len);
+int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len);
+int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len);
+int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
+		   const char *ifname, const u8 *addr, void *bss_ctx,
+		   void **drv_priv, char *force_ifname, u8 *if_addr);
+int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
+		      const char *ifname);
+int hostapd_set_ieee8021x(struct hostapd_data *hapd,
+			  struct wpa_bss_params *params);
+int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
+		       const u8 *addr, int idx, u8 *seq);
+int hostapd_flush(struct hostapd_data *hapd);
+int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq,
+		     int channel, int ht_enabled, int sec_channel_offset);
+int hostapd_set_rts(struct hostapd_data *hapd, int rts);
+int hostapd_set_frag(struct hostapd_data *hapd, int frag);
+int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
+			  int total_flags, int flags_or, int flags_and);
+int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates,
+			  int *basic_rates, int mode);
+int hostapd_set_country(struct hostapd_data *hapd, const char *country);
+int hostapd_set_cts_protect(struct hostapd_data *hapd, int value);
+int hostapd_set_preamble(struct hostapd_data *hapd, int value);
+int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value);
+int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
+				int cw_min, int cw_max, int burst_time);
+int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
+			   const u8 *mask);
+struct hostapd_hw_modes *
+hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
+			    u16 *flags);
+int hostapd_driver_commit(struct hostapd_data *hapd);
+int hostapd_set_ht_params(struct hostapd_data *hapd,
+			  const u8 *ht_capab, size_t ht_capab_len,
+			  const u8 *ht_oper, size_t ht_oper_len);
+int hostapd_drv_none(struct hostapd_data *hapd);
+int hostapd_driver_scan(struct hostapd_data *hapd,
+			struct wpa_driver_scan_params *params);
+struct wpa_scan_results * hostapd_driver_get_scan_results(
+	struct hostapd_data *hapd);
+
+#endif /* AP_DRV_OPS */
diff --git a/contrib/wpa/hostapd/ap_list.c b/contrib/wpa/src/ap/ap_list.c
similarity index 71%
rename from contrib/wpa/hostapd/ap_list.c
rename to contrib/wpa/src/ap/ap_list.c
index 4f217dc54121..5297dbf3bf5f 100644
--- a/contrib/wpa/hostapd/ap_list.c
+++ b/contrib/wpa/src/ap/ap_list.c
@@ -1,9 +1,8 @@
 /*
  * hostapd / AP table
- * Copyright (c) 2002-2003, Jouni Malinen 
+ * Copyright (c) 2002-2009, Jouni Malinen 
  * Copyright (c) 2003-2004, Instant802 Networks, Inc.
  * Copyright (c) 2006, Devicescape Software, Inc.
- * Copyright (c) 2007-2008, Intel Corporation
  *
  * 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
@@ -15,52 +14,19 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "drivers/driver.h"
 #include "hostapd.h"
+#include "ap_config.h"
 #include "ieee802_11.h"
-#include "eloop.h"
-#include "ap_list.h"
-#include "hw_features.h"
+#include "sta_info.h"
 #include "beacon.h"
-
-
-struct ieee80211_frame_info {
-	u32 version;
-	u32 length;
-	u64 mactime;
-	u64 hosttime;
-	u32 phytype;
-	u32 channel;
-	u32 datarate;
-	u32 antenna;
-	u32 priority;
-	u32 ssi_type;
-	u32 ssi_signal;
-	u32 ssi_noise;
-	u32 preamble;
-	u32 encoding;
-
-	/* Note: this structure is otherwise identical to capture format used
-	 * in linux-wlan-ng, but this additional field is used to provide meta
-	 * data about the frame to hostapd. This was the easiest method for
-	 * providing this information, but this might change in the future. */
-	u32 msg_type;
-} __attribute__ ((packed));
-
-
-enum ieee80211_phytype {
-	ieee80211_phytype_fhss_dot11_97  = 1,
-	ieee80211_phytype_dsss_dot11_97  = 2,
-	ieee80211_phytype_irbaseband     = 3,
-	ieee80211_phytype_dsss_dot11_b   = 4,
-	ieee80211_phytype_pbcc_dot11_b   = 5,
-	ieee80211_phytype_ofdm_dot11_g   = 6,
-	ieee80211_phytype_pbcc_dot11_g   = 7,
-	ieee80211_phytype_ofdm_dot11_a   = 8,
-	ieee80211_phytype_dsss_dot11_turbog = 255,
-	ieee80211_phytype_dsss_dot11_turbo = 256,
-};
+#include "ap_list.h"
 
 
 /* AP list is a double linked list with head->prev pointing to the end of the
@@ -69,29 +35,11 @@ enum ieee80211_phytype {
  * in this link will thus be the least recently used entry. */
 
 
-static void ap_list_new_ap(struct hostapd_iface *iface, struct ap_info *ap)
-{
-	wpa_printf(MSG_DEBUG, "New AP detected: " MACSTR, MAC2STR(ap->addr));
-
-	/* TODO: could send a notification message to an external program that
-	 * would then determine whether a rogue AP has been detected */
-}
-
-
-static void ap_list_expired_ap(struct hostapd_iface *iface, struct ap_info *ap)
-{
-	wpa_printf(MSG_DEBUG, "AP info expired: " MACSTR, MAC2STR(ap->addr));
-
-	/* TODO: could send a notification message to an external program */
-}
-
-
 static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap)
 {
 	int i;
 
 	if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G ||
-	    ap->phytype != ieee80211_phytype_pbcc_dot11_g ||
 	    iface->conf->channel != ap->channel)
 		return 0;
 
@@ -108,16 +56,7 @@ static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap)
 }
 
 
-#ifdef CONFIG_IEEE80211N
-static int ap_list_beacon_olbc_ht(struct hostapd_iface *iface,
-				  struct ap_info *ap)
-{
-	return !ap->ht_support;
-}
-#endif /* CONFIG_IEEE80211N */
-
-
-struct ap_info * ap_get_ap(struct hostapd_iface *iface, u8 *ap)
+struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *ap)
 {
 	struct ap_info *s;
 
@@ -257,7 +196,7 @@ int ap_ap_for_each(struct hostapd_iface *iface,
 }
 
 
-static struct ap_info * ap_ap_add(struct hostapd_iface *iface, u8 *addr)
+static struct ap_info * ap_ap_add(struct hostapd_iface *iface, const u8 *addr)
 {
 	struct ap_info *ap;
 
@@ -275,8 +214,6 @@ static struct ap_info * ap_ap_add(struct hostapd_iface *iface, u8 *addr)
 	if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) {
 		wpa_printf(MSG_DEBUG, "Removing the least recently used AP "
 			   MACSTR " from AP table", MAC2STR(ap->prev->addr));
-		if (iface->conf->passive_scan_interval > 0)
-			ap_list_expired_ap(iface, ap->prev);
 		ap_free_ap(iface, ap->prev);
 	}
 
@@ -285,7 +222,7 @@ static struct ap_info * ap_ap_add(struct hostapd_iface *iface, u8 *addr)
 
 
 void ap_list_process_beacon(struct hostapd_iface *iface,
-			    struct ieee80211_mgmt *mgmt,
+			    const struct ieee80211_mgmt *mgmt,
 			    struct ieee802_11_elems *elems,
 			    struct hostapd_frame_info *fi)
 {
@@ -357,15 +294,11 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
 	ap->num_beacons++;
 	time(&ap->last_beacon);
 	if (fi) {
-		ap->phytype = fi->phytype;
 		ap->ssi_signal = fi->ssi_signal;
 		ap->datarate = fi->datarate;
 	}
 
-	if (new_ap) {
-		if (iface->conf->passive_scan_interval > 0)
-			ap_list_new_ap(iface, ap);
-	} else if (ap != iface->ap_list) {
+	if (!new_ap && ap != iface->ap_list) {
 		/* move AP entry into the beginning of the list so that the
 		 * oldest entry is always in the end of the list */
 		ap_ap_list_del(iface, ap);
@@ -381,7 +314,7 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
 	}
 
 #ifdef CONFIG_IEEE80211N
-	if (!iface->olbc_ht && ap_list_beacon_olbc_ht(iface, ap)) {
+	if (!iface->olbc_ht && !ap->ht_support) {
 		iface->olbc_ht = 1;
 		hostapd_ht_operation_update(iface);
 		wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR
@@ -409,18 +342,12 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
 
 	time(&now);
 
-	/* FIX: it looks like jkm-Purina ended up in busy loop in this
-	 * function. Apparently, something can still cause a loop in the AP
-	 * list.. */
-
 	while (iface->ap_list) {
 		ap = iface->ap_list->prev;
 		if (ap->last_beacon + iface->conf->ap_table_expiration_time >=
 		    now)
 			break;
 
-		if (iface->conf->passive_scan_interval > 0)
-			ap_list_expired_ap(iface, ap);
 		ap_free_ap(iface, ap);
 	}
 
@@ -432,10 +359,8 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
 		while (ap && (olbc == 0 || olbc_ht == 0)) {
 			if (ap_list_beacon_olbc(iface, ap))
 				olbc = 1;
-#ifdef CONFIG_IEEE80211N
-			if (ap_list_beacon_olbc_ht(iface, ap))
+			if (!ap->ht_support)
 				olbc_ht = 1;
-#endif /* CONFIG_IEEE80211N */
 			ap = ap->next;
 		}
 		if (!olbc && iface->olbc) {
@@ -470,32 +395,3 @@ void ap_list_deinit(struct hostapd_iface *iface)
 	eloop_cancel_timeout(ap_list_timer, iface, NULL);
 	hostapd_free_aps(iface);
 }
-
-
-int ap_list_reconfig(struct hostapd_iface *iface,
-		     struct hostapd_config *oldconf)
-{
-	time_t now;
-	struct ap_info *ap;
-
-	if (iface->conf->ap_table_max_size == oldconf->ap_table_max_size &&
-	    iface->conf->ap_table_expiration_time ==
-	    oldconf->ap_table_expiration_time)
-		return 0;
-
-	time(&now);
-
-	while (iface->ap_list) {
-		ap = iface->ap_list->prev;
-		if (iface->num_ap <= iface->conf->ap_table_max_size &&
-		    ap->last_beacon + iface->conf->ap_table_expiration_time >=
-		    now)
-			break;
-
-		if (iface->conf->passive_scan_interval > 0)
-			ap_list_expired_ap(iface, iface->ap_list->prev);
-		ap_free_ap(iface, iface->ap_list->prev);
-	}
-
-	return 0;
-}
diff --git a/contrib/wpa/hostapd/ap_list.h b/contrib/wpa/src/ap/ap_list.h
similarity index 86%
rename from contrib/wpa/hostapd/ap_list.h
rename to contrib/wpa/src/ap/ap_list.h
index 93704f8bb612..f49f58b54e43 100644
--- a/contrib/wpa/hostapd/ap_list.h
+++ b/contrib/wpa/src/ap/ap_list.h
@@ -3,7 +3,6 @@
  * Copyright (c) 2002-2003, Jouni Malinen 
  * Copyright (c) 2003-2004, Instant802 Networks, Inc.
  * Copyright (c) 2006, Devicescape Software, Inc.
- * Copyright (c) 2007-2008, Intel Corporation
  *
  * 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
@@ -39,7 +38,6 @@ struct ap_info {
 	int wpa;
 	int erp; /* ERP Info or -1 if ERP info element not present */
 
-	int phytype; /* .11a / .11b / .11g / Atheros Turbo */
 	int channel;
 	int datarate; /* in 100 kbps */
 	int ssi_signal;
@@ -56,16 +54,25 @@ struct ap_info {
 struct ieee802_11_elems;
 struct hostapd_frame_info;
 
-struct ap_info * ap_get_ap(struct hostapd_iface *iface, u8 *sta);
+struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *sta);
 int ap_ap_for_each(struct hostapd_iface *iface,
 		   int (*func)(struct ap_info *s, void *data), void *data);
 void ap_list_process_beacon(struct hostapd_iface *iface,
-			    struct ieee80211_mgmt *mgmt,
+			    const struct ieee80211_mgmt *mgmt,
 			    struct ieee802_11_elems *elems,
 			    struct hostapd_frame_info *fi);
+#ifdef NEED_AP_MLME
 int ap_list_init(struct hostapd_iface *iface);
 void ap_list_deinit(struct hostapd_iface *iface);
-int ap_list_reconfig(struct hostapd_iface *iface,
-		     struct hostapd_config *oldconf);
+#else /* NEED_AP_MLME */
+static inline int ap_list_init(struct hostapd_iface *iface)
+{
+	return 0;
+}
+
+static inline void ap_list_deinit(struct hostapd_iface *iface)
+{
+}
+#endif /* NEED_AP_MLME */
 
 #endif /* AP_LIST_H */
diff --git a/contrib/wpa/hostapd/mlme.c b/contrib/wpa/src/ap/ap_mlme.c
similarity index 95%
rename from contrib/wpa/hostapd/mlme.c
rename to contrib/wpa/src/ap/ap_mlme.c
index d883931cf414..2b09b11e79c1 100644
--- a/contrib/wpa/hostapd/mlme.c
+++ b/contrib/wpa/src/ap/ap_mlme.c
@@ -14,14 +14,17 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#include "hostapd.h"
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
 #include "ieee802_11.h"
-#include "wpa.h"
-#include "mlme.h"
+#include "wpa_auth.h"
+#include "sta_info.h"
+#include "ap_mlme.h"
 
 
+#ifndef CONFIG_NO_HOSTAPD_LOGGER
 static const char * mlme_auth_alg_str(int alg)
 {
 	switch (alg) {
@@ -35,6 +38,7 @@ static const char * mlme_auth_alg_str(int alg)
 
 	return "unknown";
 }
+#endif /* CONFIG_NO_HOSTAPD_LOGGER */
 
 
 /**
diff --git a/contrib/wpa/hostapd/mlme.h b/contrib/wpa/src/ap/ap_mlme.h
similarity index 100%
rename from contrib/wpa/hostapd/mlme.h
rename to contrib/wpa/src/ap/ap_mlme.h
diff --git a/contrib/wpa/src/ap/authsrv.c b/contrib/wpa/src/ap/authsrv.c
new file mode 100644
index 000000000000..0ab0668acc56
--- /dev/null
+++ b/contrib/wpa/src/ap/authsrv.c
@@ -0,0 +1,216 @@
+/*
+ * Authentication server setup
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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 "crypto/tls.h"
+#include "eap_server/eap.h"
+#include "eap_server/eap_sim_db.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "radius/radius_server.h"
+#include "hostapd.h"
+#include "ap_config.h"
+#include "sta_info.h"
+#include "authsrv.h"
+
+
+#if defined(EAP_SERVER_SIM) || defined(EAP_SERVER_AKA)
+#define EAP_SIM_DB
+#endif /* EAP_SERVER_SIM || EAP_SERVER_AKA */
+
+
+#ifdef EAP_SIM_DB
+static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd,
+				 struct sta_info *sta, void *ctx)
+{
+	if (eapol_auth_eap_pending_cb(sta->eapol_sm, ctx) == 0)
+		return 1;
+	return 0;
+}
+
+
+static void hostapd_sim_db_cb(void *ctx, void *session_ctx)
+{
+	struct hostapd_data *hapd = ctx;
+	if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0) {
+#ifdef RADIUS_SERVER
+		radius_server_eap_pending_cb(hapd->radius_srv, session_ctx);
+#endif /* RADIUS_SERVER */
+	}
+}
+#endif /* EAP_SIM_DB */
+
+
+#ifdef RADIUS_SERVER
+
+static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
+				       size_t identity_len, int phase2,
+				       struct eap_user *user)
+{
+	const struct hostapd_eap_user *eap_user;
+	int i, count;
+
+	eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
+	if (eap_user == NULL)
+		return -1;
+
+	if (user == NULL)
+		return 0;
+
+	os_memset(user, 0, sizeof(*user));
+	count = EAP_USER_MAX_METHODS;
+	if (count > EAP_MAX_METHODS)
+		count = EAP_MAX_METHODS;
+	for (i = 0; i < count; i++) {
+		user->methods[i].vendor = eap_user->methods[i].vendor;
+		user->methods[i].method = eap_user->methods[i].method;
+	}
+
+	if (eap_user->password) {
+		user->password = os_malloc(eap_user->password_len);
+		if (user->password == NULL)
+			return -1;
+		os_memcpy(user->password, eap_user->password,
+			  eap_user->password_len);
+		user->password_len = eap_user->password_len;
+		user->password_hash = eap_user->password_hash;
+	}
+	user->force_version = eap_user->force_version;
+	user->ttls_auth = eap_user->ttls_auth;
+
+	return 0;
+}
+
+
+static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
+{
+	struct radius_server_conf srv;
+	struct hostapd_bss_config *conf = hapd->conf;
+	os_memset(&srv, 0, sizeof(srv));
+	srv.client_file = conf->radius_server_clients;
+	srv.auth_port = conf->radius_server_auth_port;
+	srv.conf_ctx = conf;
+	srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
+	srv.ssl_ctx = hapd->ssl_ctx;
+	srv.msg_ctx = hapd->msg_ctx;
+	srv.pac_opaque_encr_key = conf->pac_opaque_encr_key;
+	srv.eap_fast_a_id = conf->eap_fast_a_id;
+	srv.eap_fast_a_id_len = conf->eap_fast_a_id_len;
+	srv.eap_fast_a_id_info = conf->eap_fast_a_id_info;
+	srv.eap_fast_prov = conf->eap_fast_prov;
+	srv.pac_key_lifetime = conf->pac_key_lifetime;
+	srv.pac_key_refresh_time = conf->pac_key_refresh_time;
+	srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
+	srv.tnc = conf->tnc;
+	srv.wps = hapd->wps;
+	srv.ipv6 = conf->radius_server_ipv6;
+	srv.get_eap_user = hostapd_radius_get_eap_user;
+	srv.eap_req_id_text = conf->eap_req_id_text;
+	srv.eap_req_id_text_len = conf->eap_req_id_text_len;
+
+	hapd->radius_srv = radius_server_init(&srv);
+	if (hapd->radius_srv == NULL) {
+		wpa_printf(MSG_ERROR, "RADIUS server initialization failed.");
+		return -1;
+	}
+
+	return 0;
+}
+
+#endif /* RADIUS_SERVER */
+
+
+int authsrv_init(struct hostapd_data *hapd)
+{
+#ifdef EAP_TLS_FUNCS
+	if (hapd->conf->eap_server &&
+	    (hapd->conf->ca_cert || hapd->conf->server_cert ||
+	     hapd->conf->dh_file)) {
+		struct tls_connection_params params;
+
+		hapd->ssl_ctx = tls_init(NULL);
+		if (hapd->ssl_ctx == NULL) {
+			wpa_printf(MSG_ERROR, "Failed to initialize TLS");
+			authsrv_deinit(hapd);
+			return -1;
+		}
+
+		os_memset(¶ms, 0, sizeof(params));
+		params.ca_cert = hapd->conf->ca_cert;
+		params.client_cert = hapd->conf->server_cert;
+		params.private_key = hapd->conf->private_key;
+		params.private_key_passwd = hapd->conf->private_key_passwd;
+		params.dh_file = hapd->conf->dh_file;
+
+		if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) {
+			wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
+			authsrv_deinit(hapd);
+			return -1;
+		}
+
+		if (tls_global_set_verify(hapd->ssl_ctx,
+					  hapd->conf->check_crl)) {
+			wpa_printf(MSG_ERROR, "Failed to enable check_crl");
+			authsrv_deinit(hapd);
+			return -1;
+		}
+	}
+#endif /* EAP_TLS_FUNCS */
+
+#ifdef EAP_SIM_DB
+	if (hapd->conf->eap_sim_db) {
+		hapd->eap_sim_db_priv =
+			eap_sim_db_init(hapd->conf->eap_sim_db,
+					hostapd_sim_db_cb, hapd);
+		if (hapd->eap_sim_db_priv == NULL) {
+			wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM "
+				   "database interface");
+			authsrv_deinit(hapd);
+			return -1;
+		}
+	}
+#endif /* EAP_SIM_DB */
+
+#ifdef RADIUS_SERVER
+	if (hapd->conf->radius_server_clients &&
+	    hostapd_setup_radius_srv(hapd))
+		return -1;
+#endif /* RADIUS_SERVER */
+
+	return 0;
+}
+
+
+void authsrv_deinit(struct hostapd_data *hapd)
+{
+#ifdef RADIUS_SERVER
+	radius_server_deinit(hapd->radius_srv);
+	hapd->radius_srv = NULL;
+#endif /* RADIUS_SERVER */
+
+#ifdef EAP_TLS_FUNCS
+	if (hapd->ssl_ctx) {
+		tls_deinit(hapd->ssl_ctx);
+		hapd->ssl_ctx = NULL;
+	}
+#endif /* EAP_TLS_FUNCS */
+
+#ifdef EAP_SIM_DB
+	if (hapd->eap_sim_db_priv) {
+		eap_sim_db_deinit(hapd->eap_sim_db_priv);
+		hapd->eap_sim_db_priv = NULL;
+	}
+#endif /* EAP_SIM_DB */
+}
diff --git a/contrib/wpa/src/ap/authsrv.h b/contrib/wpa/src/ap/authsrv.h
new file mode 100644
index 000000000000..be3051ebfa2e
--- /dev/null
+++ b/contrib/wpa/src/ap/authsrv.h
@@ -0,0 +1,21 @@
+/*
+ * Authentication server setup
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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 AUTHSRV_H
+#define AUTHSRV_H
+
+int authsrv_init(struct hostapd_data *hapd);
+void authsrv_deinit(struct hostapd_data *hapd);
+
+#endif /* AUTHSRV_H */
diff --git a/contrib/wpa/hostapd/beacon.c b/contrib/wpa/src/ap/beacon.c
similarity index 80%
rename from contrib/wpa/hostapd/beacon.c
rename to contrib/wpa/src/ap/beacon.c
index 1f82d9cb7238..004cc8a5f336 100644
--- a/contrib/wpa/hostapd/beacon.c
+++ b/contrib/wpa/src/ap/beacon.c
@@ -2,8 +2,7 @@
  * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
  * Copyright (c) 2002-2004, Instant802 Networks, Inc.
  * Copyright (c) 2005-2006, Devicescape Software, Inc.
- * Copyright (c) 2008, Jouni Malinen 
- * Copyright (c) 2007-2008, Intel Corporation
+ * Copyright (c) 2008-2009, Jouni Malinen 
  *
  * 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
@@ -15,19 +14,21 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
 #ifndef CONFIG_NATIVE_WINDOWS
 
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "drivers/driver.h"
 #include "hostapd.h"
 #include "ieee802_11.h"
-#include "wpa.h"
-#include "wme.h"
-#include "beacon.h"
-#include "hw_features.h"
-#include "driver.h"
+#include "wpa_auth.h"
+#include "wmm.h"
+#include "ap_config.h"
 #include "sta_info.h"
-#include "wps_hostapd.h"
+#include "beacon.h"
 
 
 static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
@@ -56,7 +57,8 @@ static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
 		}
 		break;
 	}
-	if (hapd->iface->num_sta_no_short_preamble > 0)
+	if (hapd->iface->num_sta_no_short_preamble > 0 ||
+	    hapd->iconf->preamble == LONG_PREAMBLE)
 		erp |= ERP_INFO_BARKER_PREAMBLE_MODE;
 
 	return erp;
@@ -191,20 +193,26 @@ static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len,
 }
 
 
-void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
-		      size_t len)
+void handle_probe_req(struct hostapd_data *hapd,
+		      const struct ieee80211_mgmt *mgmt, size_t len)
 {
 	struct ieee80211_mgmt *resp;
 	struct ieee802_11_elems elems;
 	char *ssid;
-	u8 *pos, *epos, *ie;
+	u8 *pos, *epos;
+	const u8 *ie;
 	size_t ssid_len, ie_len;
 	struct sta_info *sta = NULL;
+	size_t buflen;
+	size_t i;
 
 	ie = mgmt->u.probe_req.variable;
 	ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
 
-	hostapd_wps_probe_req_rx(hapd, mgmt->sa, ie, ie_len);
+	for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
+		if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
+					    mgmt->sa, ie, ie_len) > 0)
+			return;
 
 	if (!hapd->iconf->send_probe_response)
 		return;
@@ -258,7 +266,12 @@ void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
 	/* TODO: verify that supp_rates contains at least one matching rate
 	 * with AP configuration */
 #define MAX_PROBERESP_LEN 768
-	resp = os_zalloc(MAX_PROBERESP_LEN);
+	buflen = MAX_PROBERESP_LEN;
+#ifdef CONFIG_WPS
+	if (hapd->wps_probe_resp_ie)
+		buflen += wpabuf_len(hapd->wps_probe_resp_ie);
+#endif /* CONFIG_WPS */
+	resp = os_zalloc(buflen);
 	if (resp == NULL)
 		return;
 	epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
@@ -296,23 +309,26 @@ void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
 	/* Extended supported rates */
 	pos = hostapd_eid_ext_supp_rates(hapd, pos);
 
+	/* RSN, MDIE, WPA */
 	pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta);
 
+#ifdef CONFIG_IEEE80211N
+	pos = hostapd_eid_ht_capabilities(hapd, pos);
+	pos = hostapd_eid_ht_operation(hapd, pos);
+#endif /* CONFIG_IEEE80211N */
+
 	/* Wi-Fi Alliance WMM */
 	pos = hostapd_eid_wmm(hapd, pos);
 
-	pos = hostapd_eid_ht_capabilities_info(hapd, pos);
-	pos = hostapd_eid_ht_operation(hapd, pos);
-
 #ifdef CONFIG_WPS
 	if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
-		os_memcpy(pos, hapd->wps_probe_resp_ie,
-			  hapd->wps_probe_resp_ie_len);
-		pos += hapd->wps_probe_resp_ie_len;
+		os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
+			  wpabuf_len(hapd->wps_probe_resp_ie));
+		pos += wpabuf_len(hapd->wps_probe_resp_ie);
 	}
 #endif /* CONFIG_WPS */
 
-	if (hostapd_send_mgmt_frame(hapd, resp, pos - (u8 *) resp, 0) < 0)
+	if (hapd->drv.send_mgmt_frame(hapd, resp, pos - (u8 *) resp) < 0)
 		perror("handle_probe_req: send");
 
 	os_free(resp);
@@ -327,16 +343,18 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
 {
 	struct ieee80211_mgmt *head;
 	u8 *pos, *tail, *tailpos;
-	int preamble;
 	u16 capab_info;
 	size_t head_len, tail_len;
-	int cts_protection = ((ieee802_11_erp_info(hapd) &
-			      ERP_INFO_USE_PROTECTION) ? 1 : 0);
 
 #define BEACON_HEAD_BUF_SIZE 256
 #define BEACON_TAIL_BUF_SIZE 512
 	head = os_zalloc(BEACON_HEAD_BUF_SIZE);
-	tailpos = tail = os_malloc(BEACON_TAIL_BUF_SIZE);
+	tail_len = BEACON_TAIL_BUF_SIZE;
+#ifdef CONFIG_WPS
+	if (hapd->conf->wps_state && hapd->wps_beacon_ie)
+		tail_len += wpabuf_len(hapd->wps_beacon_ie);
+#endif /* CONFIG_WPS */
+	tailpos = tail = os_malloc(tail_len);
 	if (head == NULL || tail == NULL) {
 		wpa_printf(MSG_ERROR, "Failed to set beacon data");
 		os_free(head);
@@ -392,68 +410,39 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
 	/* Extended supported rates */
 	tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
 
+	/* RSN, MDIE, WPA */
 	tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
 				  tailpos, NULL);
 
+#ifdef CONFIG_IEEE80211N
+	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+#endif /* CONFIG_IEEE80211N */
+
 	/* Wi-Fi Alliance WMM */
 	tailpos = hostapd_eid_wmm(hapd, tailpos);
 
-#ifdef CONFIG_IEEE80211N
-	if (hapd->iconf->ieee80211n) {
-		u8 *ht_capab, *ht_oper;
-		ht_capab = tailpos;
-		tailpos = hostapd_eid_ht_capabilities_info(hapd, tailpos);
-
-		ht_oper = tailpos;
-		tailpos = hostapd_eid_ht_operation(hapd, tailpos);
-
-		if (tailpos > ht_oper && ht_oper > ht_capab &&
-		    hostapd_set_ht_params(hapd->conf->iface, hapd,
-					  ht_capab + 2, ht_capab[1],
-					  ht_oper + 2, ht_oper[1])) {
-			wpa_printf(MSG_ERROR, "Could not set HT capabilities "
-				   "for kernel driver");
-		}
-	}
-#endif /* CONFIG_IEEE80211N */
-
 #ifdef CONFIG_WPS
 	if (hapd->conf->wps_state && hapd->wps_beacon_ie) {
-		os_memcpy(tailpos, hapd->wps_beacon_ie,
-			  hapd->wps_beacon_ie_len);
-		tailpos += hapd->wps_beacon_ie_len;
+		os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie),
+			  wpabuf_len(hapd->wps_beacon_ie));
+		tailpos += wpabuf_len(hapd->wps_beacon_ie);
 	}
 #endif /* CONFIG_WPS */
 
 	tail_len = tailpos > tail ? tailpos - tail : 0;
 
-	if (hostapd_set_beacon(hapd->conf->iface, hapd, (u8 *) head, head_len,
-			       tail, tail_len))
-		wpa_printf(MSG_ERROR, "Failed to set beacon head/tail");
+	if (hapd->drv.set_beacon(hapd, (u8 *) head, head_len,
+				 tail, tail_len, hapd->conf->dtim_period,
+				 hapd->iconf->beacon_int))
+		wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM "
+			   "period");
 
 	os_free(tail);
 	os_free(head);
 
-	if (hostapd_set_cts_protect(hapd, cts_protection))
-		wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel "
-			   "driver");
-
-	if (hapd->iface->current_mode &&
-	    hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
-	    hostapd_set_short_slot_time(hapd,
-					hapd->iface->num_sta_no_short_slot_time
-					> 0 ? 0 : 1))
-		wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option "
-			   "in kernel driver");
-
-	if (hapd->iface->num_sta_no_short_preamble == 0 &&
-	    hapd->iconf->preamble == SHORT_PREAMBLE)
-		preamble = SHORT_PREAMBLE;
-	else
-		preamble = LONG_PREAMBLE;
-	if (hostapd_set_preamble(hapd, preamble))
-		wpa_printf(MSG_ERROR, "Could not set preamble for kernel "
-			   "driver");
+	hapd->drv.set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) &
+					  ERP_INFO_USE_PROTECTION));
 }
 
 
diff --git a/contrib/wpa/hostapd/beacon.h b/contrib/wpa/src/ap/beacon.h
similarity index 66%
rename from contrib/wpa/hostapd/beacon.h
rename to contrib/wpa/src/ap/beacon.h
index 18e0da2e89f6..c1510e194254 100644
--- a/contrib/wpa/hostapd/beacon.h
+++ b/contrib/wpa/src/ap/beacon.h
@@ -16,9 +16,21 @@
 #ifndef BEACON_H
 #define BEACON_H
 
-void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
-		      size_t len);
+struct ieee80211_mgmt;
+
+void handle_probe_req(struct hostapd_data *hapd,
+		      const struct ieee80211_mgmt *mgmt, size_t len);
+#ifdef NEED_AP_MLME
 void ieee802_11_set_beacon(struct hostapd_data *hapd);
 void ieee802_11_set_beacons(struct hostapd_iface *iface);
+#else /* NEED_AP_MLME */
+static inline void ieee802_11_set_beacon(struct hostapd_data *hapd)
+{
+}
+
+static inline void ieee802_11_set_beacons(struct hostapd_iface *iface)
+{
+}
+#endif /* NEED_AP_MLME */
 
 #endif /* BEACON_H */
diff --git a/contrib/wpa/src/ap/ctrl_iface_ap.c b/contrib/wpa/src/ap/ctrl_iface_ap.c
new file mode 100644
index 000000000000..e50b0a70ca95
--- /dev/null
+++ b/contrib/wpa/src/ap/ctrl_iface_ap.c
@@ -0,0 +1,104 @@
+/*
+ * Control interface for shared AP commands
+ * Copyright (c) 2004-2009, Jouni Malinen 
+ *
+ * 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 "hostapd.h"
+#include "ieee802_1x.h"
+#include "wpa_auth.h"
+#include "ieee802_11.h"
+#include "sta_info.h"
+#include "wps_hostapd.h"
+#include "ctrl_iface_ap.h"
+
+
+static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
+				      struct sta_info *sta,
+				      char *buf, size_t buflen)
+{
+	int len, res, ret;
+
+	if (sta == NULL) {
+		ret = os_snprintf(buf, buflen, "FAIL\n");
+		if (ret < 0 || (size_t) ret >= buflen)
+			return 0;
+		return ret;
+	}
+
+	len = 0;
+	ret = os_snprintf(buf + len, buflen - len, MACSTR "\n",
+			  MAC2STR(sta->addr));
+	if (ret < 0 || (size_t) ret >= buflen - len)
+		return len;
+	len += ret;
+
+	res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
+	if (res >= 0)
+		len += res;
+	res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len);
+	if (res >= 0)
+		len += res;
+	res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
+	if (res >= 0)
+		len += res;
+	res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len,
+				      buflen - len);
+	if (res >= 0)
+		len += res;
+
+	return len;
+}
+
+
+int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
+				 char *buf, size_t buflen)
+{
+	return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen);
+}
+
+
+int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
+			   char *buf, size_t buflen)
+{
+	u8 addr[ETH_ALEN];
+	int ret;
+
+	if (hwaddr_aton(txtaddr, addr)) {
+		ret = os_snprintf(buf, buflen, "FAIL\n");
+		if (ret < 0 || (size_t) ret >= buflen)
+			return 0;
+		return ret;
+	}
+	return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr),
+					  buf, buflen);
+}
+
+
+int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
+				char *buf, size_t buflen)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+	int ret;
+
+	if (hwaddr_aton(txtaddr, addr) ||
+	    (sta = ap_get_sta(hapd, addr)) == NULL) {
+		ret = os_snprintf(buf, buflen, "FAIL\n");
+		if (ret < 0 || (size_t) ret >= buflen)
+			return 0;
+		return ret;
+	}		
+	return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
+}
diff --git a/contrib/wpa/src/ap/ctrl_iface_ap.h b/contrib/wpa/src/ap/ctrl_iface_ap.h
new file mode 100644
index 000000000000..8690beaad455
--- /dev/null
+++ b/contrib/wpa/src/ap/ctrl_iface_ap.h
@@ -0,0 +1,25 @@
+/*
+ * Control interface for shared AP commands
+ * Copyright (c) 2004-2009, Jouni Malinen 
+ *
+ * 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_AP_H
+#define CTRL_IFACE_AP_H
+
+int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
+				 char *buf, size_t buflen);
+int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
+			   char *buf, size_t buflen);
+int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
+				char *buf, size_t buflen);
+
+#endif /* CTRL_IFACE_AP_H */
diff --git a/contrib/wpa/src/ap/drv_callbacks.c b/contrib/wpa/src/ap/drv_callbacks.c
new file mode 100644
index 000000000000..26ef5845abfd
--- /dev/null
+++ b/contrib/wpa/src/ap/drv_callbacks.c
@@ -0,0 +1,457 @@
+/*
+ * hostapd / Callback functions for driver wrappers
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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.h"
+#include "drivers/driver.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "common/wpa_ctrl.h"
+#include "hostapd.h"
+#include "ieee802_11.h"
+#include "sta_info.h"
+#include "accounting.h"
+#include "tkip_countermeasures.h"
+#include "iapp.h"
+#include "ieee802_1x.h"
+#include "wpa_auth.h"
+#include "wmm.h"
+#include "wps_hostapd.h"
+#include "ap_config.h"
+
+
+int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
+			const u8 *ie, size_t ielen)
+{
+	struct sta_info *sta;
+	int new_assoc, res;
+	struct ieee802_11_elems elems;
+
+	if (addr == NULL) {
+		/*
+		 * This could potentially happen with unexpected event from the
+		 * driver wrapper. This was seen at least in one case where the
+		 * driver ended up being set to station mode while hostapd was
+		 * running, so better make sure we stop processing such an
+		 * event here.
+		 */
+		wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with "
+			   "no address");
+		return -1;
+	}
+
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+		       HOSTAPD_LEVEL_INFO, "associated");
+
+	ieee802_11_parse_elems(ie, ielen, &elems, 0);
+	if (elems.wps_ie) {
+		ie = elems.wps_ie - 2;
+		ielen = elems.wps_ie_len + 2;
+		wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
+	} else if (elems.rsn_ie) {
+		ie = elems.rsn_ie - 2;
+		ielen = elems.rsn_ie_len + 2;
+		wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
+	} else if (elems.wpa_ie) {
+		ie = elems.wpa_ie - 2;
+		ielen = elems.wpa_ie_len + 2;
+		wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
+	} else {
+		ie = NULL;
+		ielen = 0;
+		wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in "
+			   "(Re)AssocReq");
+	}
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta) {
+		accounting_sta_stop(hapd, sta);
+	} else {
+		sta = ap_sta_add(hapd, addr);
+		if (sta == NULL)
+			return -1;
+	}
+	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
+
+	if (hapd->conf->wpa) {
+		if (ie == NULL || ielen == 0) {
+			if (hapd->conf->wps_state) {
+				wpa_printf(MSG_DEBUG, "STA did not include "
+					   "WPA/RSN IE in (Re)Association "
+					   "Request - possible WPS use");
+				sta->flags |= WLAN_STA_MAYBE_WPS;
+				goto skip_wpa_check;
+			}
+
+			wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
+			return -1;
+		}
+		if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
+		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
+			sta->flags |= WLAN_STA_WPS;
+			goto skip_wpa_check;
+		}
+
+		if (sta->wpa_sm == NULL)
+			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
+							sta->addr);
+		if (sta->wpa_sm == NULL) {
+			wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
+				   "machine");
+			return -1;
+		}
+		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
+					  ie, ielen, NULL, 0);
+		if (res != WPA_IE_OK) {
+			int resp;
+			wpa_printf(MSG_DEBUG, "WPA/RSN information element "
+				   "rejected? (res %u)", res);
+			wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
+			if (res == WPA_INVALID_GROUP)
+				resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
+			else if (res == WPA_INVALID_PAIRWISE)
+				resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
+			else if (res == WPA_INVALID_AKMP)
+				resp = WLAN_REASON_AKMP_NOT_VALID;
+#ifdef CONFIG_IEEE80211W
+			else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
+				resp = WLAN_REASON_INVALID_IE;
+			else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
+				resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
+#endif /* CONFIG_IEEE80211W */
+			else
+				resp = WLAN_REASON_INVALID_IE;
+			hapd->drv.sta_disassoc(hapd, sta->addr, resp);
+			ap_free_sta(hapd, sta);
+			return -1;
+		}
+	} else if (hapd->conf->wps_state) {
+		if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
+		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
+			sta->flags |= WLAN_STA_WPS;
+		} else
+			sta->flags |= WLAN_STA_MAYBE_WPS;
+	}
+skip_wpa_check:
+
+	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
+	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
+	wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
+
+	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
+
+	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
+
+	return 0;
+}
+
+
+void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
+{
+	struct sta_info *sta;
+
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+		       HOSTAPD_LEVEL_INFO, "disassociated");
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta == NULL) {
+		wpa_printf(MSG_DEBUG, "Disassociation notification for "
+			   "unknown STA " MACSTR, MAC2STR(addr));
+		return;
+	}
+
+	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
+		MAC2STR(sta->addr));
+	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
+	sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
+	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
+	ap_free_sta(hapd, sta);
+}
+
+
+#ifdef HOSTAPD
+
+#ifdef NEED_AP_MLME
+
+static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len)
+{
+	u16 fc, type, stype;
+
+	/*
+	 * PS-Poll frames are 16 bytes. All other frames are
+	 * 24 bytes or longer.
+	 */
+	if (len < 16)
+		return NULL;
+
+	fc = le_to_host16(hdr->frame_control);
+	type = WLAN_FC_GET_TYPE(fc);
+	stype = WLAN_FC_GET_STYPE(fc);
+
+	switch (type) {
+	case WLAN_FC_TYPE_DATA:
+		if (len < 24)
+			return NULL;
+		switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
+		case WLAN_FC_FROMDS | WLAN_FC_TODS:
+		case WLAN_FC_TODS:
+			return hdr->addr1;
+		case WLAN_FC_FROMDS:
+			return hdr->addr2;
+		default:
+			return NULL;
+		}
+	case WLAN_FC_TYPE_CTRL:
+		if (stype != WLAN_FC_STYPE_PSPOLL)
+			return NULL;
+		return hdr->addr1;
+	case WLAN_FC_TYPE_MGMT:
+		return hdr->addr3;
+	default:
+		return NULL;
+	}
+}
+
+
+#define HAPD_BROADCAST ((struct hostapd_data *) -1)
+
+static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
+					    const u8 *bssid)
+{
+	size_t i;
+
+	if (bssid == NULL)
+		return NULL;
+	if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
+	    bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
+		return HAPD_BROADCAST;
+
+	for (i = 0; i < iface->num_bss; i++) {
+		if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
+			return iface->bss[i];
+	}
+
+	return NULL;
+}
+
+
+static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
+					const u8 *frame, size_t len)
+{
+	const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame;
+	u16 fc = le_to_host16(hdr->frame_control);
+	hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
+	if (hapd == NULL || hapd == HAPD_BROADCAST)
+		return;
+
+	ieee802_11_rx_from_unknown(hapd, hdr->addr2,
+				   (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
+				   (WLAN_FC_TODS | WLAN_FC_FROMDS));
+}
+
+
+static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
+{
+	struct hostapd_iface *iface = hapd->iface;
+	const struct ieee80211_hdr *hdr;
+	const u8 *bssid;
+	struct hostapd_frame_info fi;
+
+	hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
+	bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
+	if (bssid == NULL)
+		return;
+
+	hapd = get_hapd_bssid(iface, bssid);
+	if (hapd == NULL) {
+		u16 fc;
+		fc = le_to_host16(hdr->frame_control);
+
+		/*
+		 * Drop frames to unknown BSSIDs except for Beacon frames which
+		 * could be used to update neighbor information.
+		 */
+		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
+		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
+			hapd = iface->bss[0];
+		else
+			return;
+	}
+
+	os_memset(&fi, 0, sizeof(fi));
+	fi.datarate = rx_mgmt->datarate;
+	fi.ssi_signal = rx_mgmt->ssi_signal;
+
+	if (hapd == HAPD_BROADCAST) {
+		size_t i;
+		for (i = 0; i < iface->num_bss; i++)
+			ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
+					rx_mgmt->frame_len, &fi);
+	} else
+		ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi);
+}
+
+
+static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
+			       size_t len, u16 stype, int ok)
+{
+	struct ieee80211_hdr *hdr;
+	hdr = (struct ieee80211_hdr *) buf;
+	hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
+	if (hapd == NULL || hapd == HAPD_BROADCAST)
+		return;
+	ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
+}
+
+#endif /* NEED_AP_MLME */
+
+
+static int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa,
+				const u8 *ie, size_t ie_len)
+{
+	size_t i;
+	int ret = 0;
+
+	for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
+		if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
+					    sa, ie, ie_len) > 0) {
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+
+static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
+{
+	struct sta_info *sta = ap_get_sta(hapd, addr);
+	if (sta)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
+		   " - adding a new STA", MAC2STR(addr));
+	sta = ap_sta_add(hapd, addr);
+	if (sta) {
+		hostapd_new_assoc_sta(hapd, sta, 0);
+	} else {
+		wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
+			   MAC2STR(addr));
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
+				   const u8 *data, size_t data_len)
+{
+	struct hostapd_iface *iface = hapd->iface;
+	size_t j;
+
+	for (j = 0; j < iface->num_bss; j++) {
+		if (ap_get_sta(iface->bss[j], src)) {
+			hapd = iface->bss[j];
+			break;
+		}
+	}
+
+	ieee802_1x_receive(hapd, src, data, data_len);
+}
+
+
+void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
+			  union wpa_event_data *data)
+{
+	struct hostapd_data *hapd = ctx;
+
+	switch (event) {
+	case EVENT_MICHAEL_MIC_FAILURE:
+		michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
+		break;
+	case EVENT_SCAN_RESULTS:
+		if (hapd->iface->scan_cb)
+			hapd->iface->scan_cb(hapd->iface);
+		break;
+#ifdef CONFIG_IEEE80211R
+	case EVENT_FT_RRB_RX:
+		wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src,
+			      data->ft_rrb_rx.data, data->ft_rrb_rx.data_len);
+		break;
+#endif /* CONFIG_IEEE80211R */
+	case EVENT_WPS_BUTTON_PUSHED:
+		hostapd_wps_button_pushed(hapd);
+		break;
+#ifdef NEED_AP_MLME
+	case EVENT_TX_STATUS:
+		switch (data->tx_status.type) {
+		case WLAN_FC_TYPE_MGMT:
+			hostapd_mgmt_tx_cb(hapd, data->tx_status.data,
+					   data->tx_status.data_len,
+					   data->tx_status.stype,
+					   data->tx_status.ack);
+			break;
+		case WLAN_FC_TYPE_DATA:
+			hostapd_tx_status(hapd, data->tx_status.dst,
+					  data->tx_status.data,
+					  data->tx_status.data_len,
+					  data->tx_status.ack);
+			break;
+		}
+		break;
+	case EVENT_RX_FROM_UNKNOWN:
+		hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame,
+					    data->rx_from_unknown.len);
+		break;
+	case EVENT_RX_MGMT:
+		hostapd_mgmt_rx(hapd, &data->rx_mgmt);
+		break;
+#endif /* NEED_AP_MLME */
+	case EVENT_RX_PROBE_REQ:
+		hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
+				     data->rx_probe_req.ie,
+				     data->rx_probe_req.ie_len);
+		break;
+	case EVENT_NEW_STA:
+		hostapd_event_new_sta(hapd, data->new_sta.addr);
+		break;
+	case EVENT_EAPOL_RX:
+		hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
+				       data->eapol_rx.data,
+				       data->eapol_rx.data_len);
+		break;
+	case EVENT_ASSOC:
+		hostapd_notif_assoc(hapd, data->assoc_info.addr,
+				    data->assoc_info.req_ies,
+				    data->assoc_info.req_ies_len);
+		break;
+	case EVENT_DISASSOC:
+		if (data)
+			hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
+		break;
+	case EVENT_DEAUTH:
+		if (data)
+			hostapd_notif_disassoc(hapd, data->deauth_info.addr);
+		break;
+	default:
+		wpa_printf(MSG_DEBUG, "Unknown event %d", event);
+		break;
+	}
+}
+
+#endif /* HOSTAPD */
diff --git a/contrib/wpa/src/ap/hostapd.c b/contrib/wpa/src/ap/hostapd.c
new file mode 100644
index 000000000000..841f9c59c46b
--- /dev/null
+++ b/contrib/wpa/src/ap/hostapd.c
@@ -0,0 +1,887 @@
+/*
+ * hostapd / Initialization and configuration
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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 "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
+#include "radius/radius_client.h"
+#include "drivers/driver.h"
+#include "hostapd.h"
+#include "authsrv.h"
+#include "sta_info.h"
+#include "accounting.h"
+#include "ap_list.h"
+#include "beacon.h"
+#include "iapp.h"
+#include "ieee802_1x.h"
+#include "ieee802_11_auth.h"
+#include "vlan_init.h"
+#include "wpa_auth.h"
+#include "wps_hostapd.h"
+#include "hw_features.h"
+#include "wpa_auth_glue.h"
+#include "ap_drv_ops.h"
+#include "ap_config.h"
+
+
+static int hostapd_flush_old_stations(struct hostapd_data *hapd);
+static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
+
+extern int wpa_debug_level;
+
+
+int hostapd_reload_config(struct hostapd_iface *iface)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+	struct hostapd_config *newconf, *oldconf;
+	size_t j;
+
+	if (iface->config_read_cb == NULL)
+		return -1;
+	newconf = iface->config_read_cb(iface->config_fname);
+	if (newconf == NULL)
+		return -1;
+
+	/*
+	 * Deauthenticate all stations since the new configuration may not
+	 * allow them to use the BSS anymore.
+	 */
+	for (j = 0; j < iface->num_bss; j++)
+		hostapd_flush_old_stations(iface->bss[j]);
+
+#ifndef CONFIG_NO_RADIUS
+	/* TODO: update dynamic data based on changed configuration
+	 * items (e.g., open/close sockets, etc.) */
+	radius_client_flush(hapd->radius, 0);
+#endif /* CONFIG_NO_RADIUS */
+
+	oldconf = hapd->iconf;
+	hapd->iconf = newconf;
+	hapd->conf = &newconf->bss[0];
+	iface->conf = newconf;
+
+	if (hostapd_setup_wpa_psk(hapd->conf)) {
+		wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
+			   "after reloading configuration");
+	}
+
+	if (hapd->conf->ieee802_1x || hapd->conf->wpa)
+		hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 1);
+	else
+		hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
+
+	if (hapd->conf->wpa && hapd->wpa_auth == NULL)
+		hostapd_setup_wpa(hapd);
+	else if (hapd->conf->wpa) {
+		const u8 *wpa_ie;
+		size_t wpa_ie_len;
+		hostapd_reconfig_wpa(hapd);
+		wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
+		if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len))
+			wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
+				   "the kernel driver.");
+	} else if (hapd->wpa_auth) {
+		wpa_deinit(hapd->wpa_auth);
+		hapd->wpa_auth = NULL;
+		hostapd_set_privacy(hapd, 0);
+		hostapd_setup_encryption(hapd->conf->iface, hapd);
+		hostapd_set_generic_elem(hapd, (u8 *) "", 0);
+	}
+
+	ieee802_11_set_beacon(hapd);
+	hostapd_update_wps(hapd);
+
+	if (hapd->conf->ssid.ssid_set &&
+	    hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid,
+			     hapd->conf->ssid.ssid_len)) {
+		wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
+		/* try to continue */
+	}
+
+	hostapd_config_free(oldconf);
+
+	wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
+
+	return 0;
+}
+
+
+static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
+					      char *ifname)
+{
+	int i;
+
+	for (i = 0; i < NUM_WEP_KEYS; i++) {
+		if (hapd->drv.set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
+				      i == 0 ? 1 : 0, NULL, 0, NULL, 0)) {
+			wpa_printf(MSG_DEBUG, "Failed to clear default "
+				   "encryption keys (ifname=%s keyidx=%d)",
+				   ifname, i);
+		}
+	}
+#ifdef CONFIG_IEEE80211W
+	if (hapd->conf->ieee80211w) {
+		for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
+			if (hapd->drv.set_key(ifname, hapd, WPA_ALG_NONE, NULL,
+					      i, i == 0 ? 1 : 0, NULL, 0,
+					      NULL, 0)) {
+				wpa_printf(MSG_DEBUG, "Failed to clear "
+					   "default mgmt encryption keys "
+					   "(ifname=%s keyidx=%d)", ifname, i);
+			}
+		}
+	}
+#endif /* CONFIG_IEEE80211W */
+}
+
+
+static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd)
+{
+	hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface);
+	return 0;
+}
+
+
+static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
+{
+	int errors = 0, idx;
+	struct hostapd_ssid *ssid = &hapd->conf->ssid;
+
+	idx = ssid->wep.idx;
+	if (ssid->wep.default_len &&
+	    hapd->drv.set_key(hapd->conf->iface,
+			      hapd, WPA_ALG_WEP, NULL, idx,
+			      idx == ssid->wep.idx,
+			      NULL, 0, ssid->wep.key[idx],
+			      ssid->wep.len[idx])) {
+		wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
+		errors++;
+	}
+
+	if (ssid->dyn_vlan_keys) {
+		size_t i;
+		for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) {
+			const char *ifname;
+			struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i];
+			if (key == NULL)
+				continue;
+			ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan,
+							    i);
+			if (ifname == NULL)
+				continue;
+
+			idx = key->idx;
+			if (hapd->drv.set_key(ifname, hapd, WPA_ALG_WEP, NULL,
+					      idx, idx == key->idx, NULL, 0,
+					      key->key[idx], key->len[idx])) {
+				wpa_printf(MSG_WARNING, "Could not set "
+					   "dynamic VLAN WEP encryption.");
+				errors++;
+			}
+		}
+	}
+
+	return errors;
+}
+
+/**
+ * hostapd_cleanup - Per-BSS cleanup (deinitialization)
+ * @hapd: Pointer to BSS data
+ *
+ * This function is used to free all per-BSS data structures and resources.
+ * This gets called in a loop for each BSS between calls to
+ * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface
+ * is deinitialized. Most of the modules that are initialized in
+ * hostapd_setup_bss() are deinitialized here.
+ */
+static void hostapd_cleanup(struct hostapd_data *hapd)
+{
+	if (hapd->iface->ctrl_iface_deinit)
+		hapd->iface->ctrl_iface_deinit(hapd);
+
+	iapp_deinit(hapd->iapp);
+	hapd->iapp = NULL;
+	accounting_deinit(hapd);
+	hostapd_deinit_wpa(hapd);
+	vlan_deinit(hapd);
+	hostapd_acl_deinit(hapd);
+#ifndef CONFIG_NO_RADIUS
+	radius_client_deinit(hapd->radius);
+	hapd->radius = NULL;
+#endif /* CONFIG_NO_RADIUS */
+
+	hostapd_deinit_wps(hapd);
+
+	authsrv_deinit(hapd);
+
+	if (hapd->interface_added &&
+	    hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
+		wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
+			   hapd->conf->iface);
+	}
+
+	os_free(hapd->probereq_cb);
+	hapd->probereq_cb = NULL;
+}
+
+
+/**
+ * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup
+ * @iface: Pointer to interface data
+ *
+ * This function is called before per-BSS data structures are deinitialized
+ * with hostapd_cleanup().
+ */
+static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
+{
+}
+
+
+/**
+ * hostapd_cleanup_iface - Complete per-interface cleanup
+ * @iface: Pointer to interface data
+ *
+ * This function is called after per-BSS data structures are deinitialized
+ * with hostapd_cleanup().
+ */
+static void hostapd_cleanup_iface(struct hostapd_iface *iface)
+{
+	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
+	iface->hw_features = NULL;
+	os_free(iface->current_rates);
+	iface->current_rates = NULL;
+	ap_list_deinit(iface);
+	hostapd_config_free(iface->conf);
+	iface->conf = NULL;
+
+	os_free(iface->config_fname);
+	os_free(iface->bss);
+	os_free(iface);
+}
+
+
+static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
+{
+	int i;
+
+	hostapd_broadcast_wep_set(hapd);
+
+	if (hapd->conf->ssid.wep.default_len) {
+		hostapd_set_privacy(hapd, 1);
+		return 0;
+	}
+
+	for (i = 0; i < 4; i++) {
+		if (hapd->conf->ssid.wep.key[i] &&
+		    hapd->drv.set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
+				      i == hapd->conf->ssid.wep.idx, NULL, 0,
+				      hapd->conf->ssid.wep.key[i],
+				      hapd->conf->ssid.wep.len[i])) {
+			wpa_printf(MSG_WARNING, "Could not set WEP "
+				   "encryption.");
+			return -1;
+		}
+		if (hapd->conf->ssid.wep.key[i] &&
+		    i == hapd->conf->ssid.wep.idx)
+			hostapd_set_privacy(hapd, 1);
+	}
+
+	return 0;
+}
+
+
+static int hostapd_flush_old_stations(struct hostapd_data *hapd)
+{
+	int ret = 0;
+
+	if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "Flushing old station entries");
+	if (hostapd_flush(hapd)) {
+		wpa_printf(MSG_WARNING, "Could not connect to kernel driver.");
+		ret = -1;
+	}
+	wpa_printf(MSG_DEBUG, "Deauthenticate all stations");
+
+	/* New Prism2.5/3 STA firmware versions seem to have issues with this
+	 * broadcast deauth frame. This gets the firmware in odd state where
+	 * nothing works correctly, so let's skip sending this for the hostap
+	 * driver. */
+	if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") != 0) {
+		u8 addr[ETH_ALEN];
+		os_memset(addr, 0xff, ETH_ALEN);
+		hapd->drv.sta_deauth(hapd, addr,
+				     WLAN_REASON_PREV_AUTH_NOT_VALID);
+	}
+
+	return ret;
+}
+
+
+/**
+ * hostapd_validate_bssid_configuration - Validate BSSID configuration
+ * @iface: Pointer to interface data
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to validate that the configured BSSIDs are valid.
+ */
+static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
+{
+	u8 mask[ETH_ALEN] = { 0 };
+	struct hostapd_data *hapd = iface->bss[0];
+	unsigned int i = iface->conf->num_bss, bits = 0, j;
+	int res;
+	int auto_addr = 0;
+
+	if (hostapd_drv_none(hapd))
+		return 0;
+
+	/* Generate BSSID mask that is large enough to cover the BSSIDs. */
+
+	/* Determine the bits necessary to cover the number of BSSIDs. */
+	for (i--; i; i >>= 1)
+		bits++;
+
+	/* Determine the bits necessary to any configured BSSIDs,
+	   if they are higher than the number of BSSIDs. */
+	for (j = 0; j < iface->conf->num_bss; j++) {
+		if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) {
+			if (j)
+				auto_addr++;
+			continue;
+		}
+
+		for (i = 0; i < ETH_ALEN; i++) {
+			mask[i] |=
+				iface->conf->bss[j].bssid[i] ^
+				hapd->own_addr[i];
+		}
+	}
+
+	if (!auto_addr)
+		goto skip_mask_ext;
+
+	for (i = 0; i < ETH_ALEN && mask[i] == 0; i++)
+		;
+	j = 0;
+	if (i < ETH_ALEN) {
+		j = (5 - i) * 8;
+
+		while (mask[i] != 0) {
+			mask[i] >>= 1;
+			j++;
+		}
+	}
+
+	if (bits < j)
+		bits = j;
+
+	if (bits > 40) {
+		wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)",
+			   bits);
+		return -1;
+	}
+
+	os_memset(mask, 0xff, ETH_ALEN);
+	j = bits / 8;
+	for (i = 5; i > 5 - j; i--)
+		mask[i] = 0;
+	j = bits % 8;
+	while (j--)
+		mask[i] <<= 1;
+
+skip_mask_ext:
+	wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
+		   (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
+
+	res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask);
+	if (res == 0)
+		return 0;
+
+	if (res < 0) {
+		wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask "
+			   MACSTR " for start address " MACSTR ".",
+			   MAC2STR(mask), MAC2STR(hapd->own_addr));
+		return -1;
+	}
+
+	if (!auto_addr)
+		return 0;
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) {
+			wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR
+				   " for start address " MACSTR ".",
+				   MAC2STR(mask), MAC2STR(hapd->own_addr));
+			wpa_printf(MSG_ERROR, "Start address must be the "
+				   "first address in the block (i.e., addr "
+				   "AND mask == addr).");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+
+static int mac_in_conf(struct hostapd_config *conf, const void *a)
+{
+	size_t i;
+
+	for (i = 0; i < conf->num_bss; i++) {
+		if (hostapd_mac_comp(conf->bss[i].bssid, a) == 0) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+
+
+
+/**
+ * hostapd_setup_bss - Per-BSS setup (initialization)
+ * @hapd: Pointer to BSS data
+ * @first: Whether this BSS is the first BSS of an interface
+ *
+ * This function is used to initialize all per-BSS data structures and
+ * resources. This gets called in a loop for each BSS when an interface is
+ * initialized. Most of the modules that are initialized here will be
+ * deinitialized in hostapd_cleanup().
+ */
+static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+{
+	struct hostapd_bss_config *conf = hapd->conf;
+	u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
+	int ssid_len, set_ssid;
+	char force_ifname[IFNAMSIZ];
+	u8 if_addr[ETH_ALEN];
+
+	if (!first) {
+		if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
+			/* Allocate the next available BSSID. */
+			do {
+				inc_byte_array(hapd->own_addr, ETH_ALEN);
+			} while (mac_in_conf(hapd->iconf, hapd->own_addr));
+		} else {
+			/* Allocate the configured BSSID. */
+			os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN);
+
+			if (hostapd_mac_comp(hapd->own_addr,
+					     hapd->iface->bss[0]->own_addr) ==
+			    0) {
+				wpa_printf(MSG_ERROR, "BSS '%s' may not have "
+					   "BSSID set to the MAC address of "
+					   "the radio", hapd->conf->iface);
+				return -1;
+			}
+		}
+
+		hapd->interface_added = 1;
+		if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
+				   hapd->conf->iface, hapd->own_addr, hapd,
+				   &hapd->drv_priv, force_ifname, if_addr)) {
+			wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
+				   MACSTR ")", MAC2STR(hapd->own_addr));
+			return -1;
+		}
+	}
+
+	hostapd_flush_old_stations(hapd);
+	hostapd_set_privacy(hapd, 0);
+
+	hostapd_broadcast_wep_clear(hapd);
+	if (hostapd_setup_encryption(hapd->conf->iface, hapd))
+		return -1;
+
+	/*
+	 * Fetch the SSID from the system and use it or,
+	 * if one was specified in the config file, verify they
+	 * match.
+	 */
+	ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid));
+	if (ssid_len < 0) {
+		wpa_printf(MSG_ERROR, "Could not read SSID from system");
+		return -1;
+	}
+	if (conf->ssid.ssid_set) {
+		/*
+		 * If SSID is specified in the config file and it differs
+		 * from what is being used then force installation of the
+		 * new SSID.
+		 */
+		set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len ||
+			    os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0);
+	} else {
+		/*
+		 * No SSID in the config file; just use the one we got
+		 * from the system.
+		 */
+		set_ssid = 0;
+		conf->ssid.ssid_len = ssid_len;
+		os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
+		conf->ssid.ssid[conf->ssid.ssid_len] = '\0';
+	}
+
+	if (!hostapd_drv_none(hapd)) {
+		wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
+			   " and ssid '%s'",
+			   hapd->conf->iface, MAC2STR(hapd->own_addr),
+			   hapd->conf->ssid.ssid);
+	}
+
+	if (hostapd_setup_wpa_psk(conf)) {
+		wpa_printf(MSG_ERROR, "WPA-PSK setup failed.");
+		return -1;
+	}
+
+	/* Set SSID for the kernel driver (to be used in beacon and probe
+	 * response frames) */
+	if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid.ssid,
+					 conf->ssid.ssid_len)) {
+		wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
+		return -1;
+	}
+
+	if (wpa_debug_level == MSG_MSGDUMP)
+		conf->radius->msg_dumps = 1;
+#ifndef CONFIG_NO_RADIUS
+	hapd->radius = radius_client_init(hapd, conf->radius);
+	if (hapd->radius == NULL) {
+		wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
+		return -1;
+	}
+#endif /* CONFIG_NO_RADIUS */
+
+	if (hostapd_acl_init(hapd)) {
+		wpa_printf(MSG_ERROR, "ACL initialization failed.");
+		return -1;
+	}
+	if (hostapd_init_wps(hapd, conf))
+		return -1;
+
+	if (authsrv_init(hapd) < 0)
+		return -1;
+
+	if (ieee802_1x_init(hapd)) {
+		wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed.");
+		return -1;
+	}
+
+	if (hapd->conf->wpa && hostapd_setup_wpa(hapd))
+		return -1;
+
+	if (accounting_init(hapd)) {
+		wpa_printf(MSG_ERROR, "Accounting initialization failed.");
+		return -1;
+	}
+
+	if (hapd->conf->ieee802_11f &&
+	    (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) {
+		wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
+			   "failed.");
+		return -1;
+	}
+
+	if (hapd->iface->ctrl_iface_init &&
+	    hapd->iface->ctrl_iface_init(hapd)) {
+		wpa_printf(MSG_ERROR, "Failed to setup control interface");
+		return -1;
+	}
+
+	if (!hostapd_drv_none(hapd) && vlan_init(hapd)) {
+		wpa_printf(MSG_ERROR, "VLAN initialization failed.");
+		return -1;
+	}
+
+	ieee802_11_set_beacon(hapd);
+
+	return 0;
+}
+
+
+static void hostapd_tx_queue_params(struct hostapd_iface *iface)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+	int i;
+	struct hostapd_tx_queue_params *p;
+
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		p = &iface->conf->tx_queue[i];
+
+		if (!p->configured)
+			continue;
+
+		if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin,
+						p->cwmax, p->burst)) {
+			wpa_printf(MSG_DEBUG, "Failed to set TX queue "
+				   "parameters for queue %d.", i);
+			/* Continue anyway */
+		}
+	}
+}
+
+
+static int setup_interface(struct hostapd_iface *iface)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+	size_t i;
+	char country[4];
+
+	/*
+	 * Make sure that all BSSes get configured with a pointer to the same
+	 * driver interface.
+	 */
+	for (i = 1; i < iface->num_bss; i++) {
+		iface->bss[i]->driver = hapd->driver;
+		iface->bss[i]->drv_priv = hapd->drv_priv;
+	}
+
+	if (hostapd_validate_bssid_configuration(iface))
+		return -1;
+
+	if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
+		os_memcpy(country, hapd->iconf->country, 3);
+		country[3] = '\0';
+		if (hostapd_set_country(hapd, country) < 0) {
+			wpa_printf(MSG_ERROR, "Failed to set country code");
+			return -1;
+		}
+	}
+
+	if (hostapd_get_hw_features(iface)) {
+		/* Not all drivers support this yet, so continue without hw
+		 * feature data. */
+	} else {
+		int ret = hostapd_select_hw_mode(iface);
+		if (ret < 0) {
+			wpa_printf(MSG_ERROR, "Could not select hw_mode and "
+				   "channel. (%d)", ret);
+			return -1;
+		}
+		ret = hostapd_check_ht_capab(iface);
+		if (ret < 0)
+			return -1;
+		if (ret == 1) {
+			wpa_printf(MSG_DEBUG, "Interface initialization will "
+				   "be completed in a callback");
+			return 0;
+		}
+	}
+	return hostapd_setup_interface_complete(iface, 0);
+}
+
+
+int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+	size_t j;
+	u8 *prev_addr;
+
+	if (err) {
+		wpa_printf(MSG_ERROR, "Interface initialization failed");
+		eloop_terminate();
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "Completing interface initialization");
+	if (hapd->iconf->channel) {
+		iface->freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel);
+		wpa_printf(MSG_DEBUG, "Mode: %s  Channel: %d  "
+			   "Frequency: %d MHz",
+			   hostapd_hw_mode_txt(hapd->iconf->hw_mode),
+			   hapd->iconf->channel, iface->freq);
+
+		if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
+				     hapd->iconf->channel,
+				     hapd->iconf->ieee80211n,
+				     hapd->iconf->secondary_channel)) {
+			wpa_printf(MSG_ERROR, "Could not set channel for "
+				   "kernel driver");
+			return -1;
+		}
+	}
+
+	if (hapd->iconf->rts_threshold > -1 &&
+	    hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
+		wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
+			   "kernel driver");
+		return -1;
+	}
+
+	if (hapd->iconf->fragm_threshold > -1 &&
+	    hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {
+		wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
+			   "for kernel driver");
+		return -1;
+	}
+
+	prev_addr = hapd->own_addr;
+
+	for (j = 0; j < iface->num_bss; j++) {
+		hapd = iface->bss[j];
+		if (j)
+			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+		if (hostapd_setup_bss(hapd, j == 0))
+			return -1;
+		if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
+			prev_addr = hapd->own_addr;
+	}
+
+	hostapd_tx_queue_params(iface);
+
+	ap_list_init(iface);
+
+	if (hostapd_driver_commit(hapd) < 0) {
+		wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
+			   "configuration", __func__);
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
+		   iface->bss[0]->conf->iface);
+
+	return 0;
+}
+
+
+/**
+ * hostapd_setup_interface - Setup of an interface
+ * @iface: Pointer to interface data.
+ * Returns: 0 on success, -1 on failure
+ *
+ * Initializes the driver interface, validates the configuration,
+ * and sets driver parameters based on the configuration.
+ * Flushes old stations, sets the channel, encryption,
+ * beacons, and WDS links based on the configuration.
+ */
+int hostapd_setup_interface(struct hostapd_iface *iface)
+{
+	int ret;
+
+	ret = setup_interface(iface);
+	if (ret) {
+		wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
+			   iface->bss[0]->conf->iface);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/**
+ * hostapd_alloc_bss_data - Allocate and initialize per-BSS data
+ * @hapd_iface: Pointer to interface data
+ * @conf: Pointer to per-interface configuration
+ * @bss: Pointer to per-BSS configuration for this BSS
+ * Returns: Pointer to allocated BSS data
+ *
+ * This function is used to allocate per-BSS data structure. This data will be
+ * freed after hostapd_cleanup() is called for it during interface
+ * deinitialization.
+ */
+struct hostapd_data *
+hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
+		       struct hostapd_config *conf,
+		       struct hostapd_bss_config *bss)
+{
+	struct hostapd_data *hapd;
+
+	hapd = os_zalloc(sizeof(*hapd));
+	if (hapd == NULL)
+		return NULL;
+
+	hostapd_set_driver_ops(&hapd->drv);
+	hapd->new_assoc_sta_cb = hostapd_new_assoc_sta;
+	hapd->iconf = conf;
+	hapd->conf = bss;
+	hapd->iface = hapd_iface;
+	hapd->driver = hapd->iconf->driver;
+
+	return hapd;
+}
+
+
+void hostapd_interface_deinit(struct hostapd_iface *iface)
+{
+	size_t j;
+
+	if (iface == NULL)
+		return;
+
+	hostapd_cleanup_iface_pre(iface);
+	for (j = 0; j < iface->num_bss; j++) {
+		struct hostapd_data *hapd = iface->bss[j];
+		hostapd_free_stas(hapd);
+		hostapd_flush_old_stations(hapd);
+		hostapd_cleanup(hapd);
+	}
+}
+
+
+void hostapd_interface_free(struct hostapd_iface *iface)
+{
+	size_t j;
+	for (j = 0; j < iface->num_bss; j++)
+		os_free(iface->bss[j]);
+	hostapd_cleanup_iface(iface);
+}
+
+
+/**
+ * hostapd_new_assoc_sta - Notify that a new station associated with the AP
+ * @hapd: Pointer to BSS data
+ * @sta: Pointer to the associated STA data
+ * @reassoc: 1 to indicate this was a re-association; 0 = first association
+ *
+ * This function will be called whenever a station associates with the AP. It
+ * can be called from ieee802_11.c for drivers that export MLME to hostapd and
+ * from drv_callbacks.c based on driver events for drivers that take care of
+ * management frames (IEEE 802.11 authentication and association) internally.
+ */
+void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
+			   int reassoc)
+{
+	if (hapd->tkip_countermeasures) {
+		hapd->drv.sta_deauth(hapd, sta->addr,
+				     WLAN_REASON_MICHAEL_MIC_FAILURE);
+		return;
+	}
+
+	hostapd_prune_associations(hapd, sta->addr);
+
+	/* IEEE 802.11F (IAPP) */
+	if (hapd->conf->ieee802_11f)
+		iapp_new_station(hapd->iapp, sta);
+
+	/* Start accounting here, if IEEE 802.1X and WPA are not used.
+	 * IEEE 802.1X/WPA code will start accounting after the station has
+	 * been authorized. */
+	if (!hapd->conf->ieee802_1x && !hapd->conf->wpa)
+		accounting_sta_start(hapd, sta);
+
+	/* Start IEEE 802.1X authentication process for new stations */
+	ieee802_1x_new_station(hapd, sta);
+	if (reassoc) {
+		if (sta->auth_alg != WLAN_AUTH_FT &&
+		    !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
+			wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
+	} else
+		wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
+}
diff --git a/contrib/wpa/src/ap/hostapd.h b/contrib/wpa/src/ap/hostapd.h
new file mode 100644
index 000000000000..d0d67c8228a4
--- /dev/null
+++ b/contrib/wpa/src/ap/hostapd.h
@@ -0,0 +1,276 @@
+/*
+ * hostapd / Initialization and configuration
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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 HOSTAPD_H
+#define HOSTAPD_H
+
+#include "common/defs.h"
+
+struct wpa_driver_ops;
+struct wpa_ctrl_dst;
+struct radius_server_data;
+struct upnp_wps_device_sm;
+struct hapd_interfaces;
+struct hostapd_data;
+struct sta_info;
+struct hostap_sta_driver_data;
+struct ieee80211_ht_capabilities;
+struct full_dynamic_vlan;
+
+struct hostapd_probereq_cb {
+	int (*cb)(void *ctx, const u8 *sa, const u8 *ie, size_t ie_len);
+	void *ctx;
+};
+
+#define HOSTAPD_RATE_BASIC 0x00000001
+
+struct hostapd_rate_data {
+	int rate; /* rate in 100 kbps */
+	int flags; /* HOSTAPD_RATE_ flags */
+};
+
+struct hostapd_frame_info {
+	u32 channel;
+	u32 datarate;
+	u32 ssi_signal;
+};
+
+
+struct hostapd_driver_ops {
+	int (*set_ap_wps_ie)(struct hostapd_data *hapd);
+	int (*send_mgmt_frame)(struct hostapd_data *hapd, const void *msg,
+			       size_t len);
+	int (*send_eapol)(struct hostapd_data *hapd, const u8 *addr,
+			  const u8 *data, size_t data_len, int encrypt);
+	int (*set_authorized)(struct hostapd_data *hapd, struct sta_info *sta,
+			      int authorized);
+	int (*set_key)(const char *ifname, struct hostapd_data *hapd,
+		       enum wpa_alg alg, const u8 *addr, int key_idx,
+		       int set_tx, const u8 *seq, size_t seq_len,
+		       const u8 *key, size_t key_len);
+	int (*read_sta_data)(struct hostapd_data *hapd,
+			     struct hostap_sta_driver_data *data,
+			     const u8 *addr);
+	int (*sta_clear_stats)(struct hostapd_data *hapd, const u8 *addr);
+	int (*set_sta_flags)(struct hostapd_data *hapd, struct sta_info *sta);
+	int (*set_drv_ieee8021x)(struct hostapd_data *hapd, const char *ifname,
+				 int enabled);
+	int (*set_radius_acl_auth)(struct hostapd_data *hapd,
+				   const u8 *mac, int accepted,
+				   u32 session_timeout);
+	int (*set_radius_acl_expire)(struct hostapd_data *hapd,
+				     const u8 *mac);
+	int (*set_bss_params)(struct hostapd_data *hapd, int use_protection);
+	int (*set_beacon)(struct hostapd_data *hapd,
+			  const u8 *head, size_t head_len,
+			  const u8 *tail, size_t tail_len, int dtim_period,
+			  int beacon_int);
+	int (*vlan_if_add)(struct hostapd_data *hapd, const char *ifname);
+	int (*vlan_if_remove)(struct hostapd_data *hapd, const char *ifname);
+	int (*set_wds_sta)(struct hostapd_data *hapd, const u8 *addr, int aid,
+			   int val);
+	int (*set_sta_vlan)(const char *ifname, struct hostapd_data *hapd,
+			    const u8 *addr, int vlan_id);
+	int (*get_inact_sec)(struct hostapd_data *hapd, const u8 *addr);
+	int (*sta_deauth)(struct hostapd_data *hapd, const u8 *addr,
+			  int reason);
+	int (*sta_disassoc)(struct hostapd_data *hapd, const u8 *addr,
+			    int reason);
+	int (*sta_add)(struct hostapd_data *hapd,
+		       const u8 *addr, u16 aid, u16 capability,
+		       const u8 *supp_rates, size_t supp_rates_len,
+		       u16 listen_interval,
+		       const struct ieee80211_ht_capabilities *ht_capab);
+	int (*sta_remove)(struct hostapd_data *hapd, const u8 *addr);
+	int (*set_countermeasures)(struct hostapd_data *hapd, int enabled);
+};
+
+/**
+ * struct hostapd_data - hostapd per-BSS data structure
+ */
+struct hostapd_data {
+	struct hostapd_iface *iface;
+	struct hostapd_config *iconf;
+	struct hostapd_bss_config *conf;
+	int interface_added; /* virtual interface added for this BSS */
+
+	u8 own_addr[ETH_ALEN];
+
+	int num_sta; /* number of entries in sta_list */
+	struct sta_info *sta_list; /* STA info list head */
+#define STA_HASH_SIZE 256
+#define STA_HASH(sta) (sta[5])
+	struct sta_info *sta_hash[STA_HASH_SIZE];
+
+	/*
+	 * Bitfield for indicating which AIDs are allocated. Only AID values
+	 * 1-2007 are used and as such, the bit at index 0 corresponds to AID
+	 * 1.
+	 */
+#define AID_WORDS ((2008 + 31) / 32)
+	u32 sta_aid[AID_WORDS];
+
+	const struct wpa_driver_ops *driver;
+	void *drv_priv;
+	struct hostapd_driver_ops drv;
+
+	void (*new_assoc_sta_cb)(struct hostapd_data *hapd,
+				 struct sta_info *sta, int reassoc);
+
+	void *msg_ctx; /* ctx for wpa_msg() calls */
+
+	struct radius_client_data *radius;
+	u32 acct_session_id_hi, acct_session_id_lo;
+
+	struct iapp_data *iapp;
+
+	struct hostapd_cached_radius_acl *acl_cache;
+	struct hostapd_acl_query_data *acl_queries;
+
+	struct wpa_authenticator *wpa_auth;
+	struct eapol_authenticator *eapol_auth;
+
+	struct rsn_preauth_interface *preauth_iface;
+	time_t michael_mic_failure;
+	int michael_mic_failures;
+	int tkip_countermeasures;
+
+	int ctrl_sock;
+	struct wpa_ctrl_dst *ctrl_dst;
+
+	void *ssl_ctx;
+	void *eap_sim_db_priv;
+	struct radius_server_data *radius_srv;
+
+	int parameter_set_count;
+
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+	struct full_dynamic_vlan *full_dynamic_vlan;
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+
+	struct l2_packet_data *l2;
+	struct wps_context *wps;
+
+	struct wpabuf *wps_beacon_ie;
+	struct wpabuf *wps_probe_resp_ie;
+#ifdef CONFIG_WPS
+	unsigned int ap_pin_failures;
+	struct upnp_wps_device_sm *wps_upnp;
+	unsigned int ap_pin_lockout_time;
+#endif /* CONFIG_WPS */
+
+	struct hostapd_probereq_cb *probereq_cb;
+	size_t num_probereq_cb;
+
+	void (*public_action_cb)(void *ctx, const u8 *buf, size_t len,
+				 int freq);
+	void *public_action_cb_ctx;
+
+	void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr,
+				   const u8 *uuid_e);
+	void *wps_reg_success_cb_ctx;
+};
+
+
+/**
+ * struct hostapd_iface - hostapd per-interface data structure
+ */
+struct hostapd_iface {
+	struct hapd_interfaces *interfaces;
+	void *owner;
+	int (*reload_config)(struct hostapd_iface *iface);
+	struct hostapd_config * (*config_read_cb)(const char *config_fname);
+	char *config_fname;
+	struct hostapd_config *conf;
+
+	size_t num_bss;
+	struct hostapd_data **bss;
+
+	int num_ap; /* number of entries in ap_list */
+	struct ap_info *ap_list; /* AP info list head */
+	struct ap_info *ap_hash[STA_HASH_SIZE];
+	struct ap_info *ap_iter_list;
+
+	struct hostapd_hw_modes *hw_features;
+	int num_hw_features;
+	struct hostapd_hw_modes *current_mode;
+	/* Rates that are currently used (i.e., filtered copy of
+	 * current_mode->channels */
+	int num_rates;
+	struct hostapd_rate_data *current_rates;
+	int freq;
+
+	u16 hw_flags;
+
+	/* Number of associated Non-ERP stations (i.e., stations using 802.11b
+	 * in 802.11g BSS) */
+	int num_sta_non_erp;
+
+	/* Number of associated stations that do not support Short Slot Time */
+	int num_sta_no_short_slot_time;
+
+	/* Number of associated stations that do not support Short Preamble */
+	int num_sta_no_short_preamble;
+
+	int olbc; /* Overlapping Legacy BSS Condition */
+
+	/* Number of HT associated stations that do not support greenfield */
+	int num_sta_ht_no_gf;
+
+	/* Number of associated non-HT stations */
+	int num_sta_no_ht;
+
+	/* Number of HT associated stations 20 MHz */
+	int num_sta_ht_20mhz;
+
+	/* Overlapping BSS information */
+	int olbc_ht;
+
+	u16 ht_op_mode;
+	void (*scan_cb)(struct hostapd_iface *iface);
+
+	int (*ctrl_iface_init)(struct hostapd_data *hapd);
+	void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
+
+	int (*for_each_interface)(struct hapd_interfaces *interfaces,
+				  int (*cb)(struct hostapd_iface *iface,
+					    void *ctx), void *ctx);
+};
+
+/* hostapd.c */
+int hostapd_reload_config(struct hostapd_iface *iface);
+struct hostapd_data *
+hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
+		       struct hostapd_config *conf,
+		       struct hostapd_bss_config *bss);
+int hostapd_setup_interface(struct hostapd_iface *iface);
+int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
+void hostapd_interface_deinit(struct hostapd_iface *iface);
+void hostapd_interface_free(struct hostapd_iface *iface);
+void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
+			   int reassoc);
+
+/* utils.c */
+int hostapd_register_probereq_cb(struct hostapd_data *hapd,
+				 int (*cb)(void *ctx, const u8 *sa,
+					   const u8 *ie, size_t ie_len),
+				 void *ctx);
+void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
+
+/* drv_callbacks.c (TODO: move to somewhere else?) */
+int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
+			const u8 *ie, size_t ielen);
+void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
+
+#endif /* HOSTAPD_H */
diff --git a/contrib/wpa/hostapd/hw_features.c b/contrib/wpa/src/ap/hw_features.c
similarity index 63%
rename from contrib/wpa/hostapd/hw_features.c
rename to contrib/wpa/src/ap/hw_features.c
index 1d6299e625ed..0159c725180e 100644
--- a/contrib/wpa/hostapd/hw_features.c
+++ b/contrib/wpa/src/ap/hw_features.c
@@ -2,7 +2,7 @@
  * hostapd / Hardware feature query and different modes
  * Copyright 2002-2003, Instant802 Networks, Inc.
  * Copyright 2005-2006, Devicescape Software, Inc.
- * Copyright (c) 2008, Jouni Malinen 
+ * Copyright (c) 2008-2009, Jouni Malinen 
  *
  * 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
@@ -14,12 +14,17 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "drivers/driver.h"
 #include "hostapd.h"
+#include "ap_config.h"
+#include "ap_drv_ops.h"
 #include "hw_features.h"
-#include "driver.h"
-#include "config.h"
 
 
 void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@@ -131,7 +136,7 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd,
 	hapd->iface->num_rates = 0;
 
 	hapd->iface->current_rates =
-		os_malloc(mode->num_rates * sizeof(struct hostapd_rate_data));
+		os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data));
 	if (!hapd->iface->current_rates) {
 		wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
 			   "table.");
@@ -143,17 +148,15 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd,
 
 		if (hapd->iconf->supported_rates &&
 		    !hostapd_rate_found(hapd->iconf->supported_rates,
-					mode->rates[i].rate))
+					mode->rates[i]))
 			continue;
 
 		rate = &hapd->iface->current_rates[hapd->iface->num_rates];
-		os_memcpy(rate, &mode->rates[i],
-			  sizeof(struct hostapd_rate_data));
+		rate->rate = mode->rates[i];
 		if (hostapd_rate_found(basic_rates, rate->rate)) {
 			rate->flags |= HOSTAPD_RATE_BASIC;
 			num_basic_rates++;
-		} else
-			rate->flags &= ~HOSTAPD_RATE_BASIC;
+		}
 		wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
 			   hapd->iface->num_rates, rate->rate, rate->flags);
 		hapd->iface->num_rates++;
@@ -236,6 +239,245 @@ static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
 }
 
 
+static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
+{
+	if (iface->conf->secondary_channel > 0) {
+		iface->conf->channel += 4;
+		iface->conf->secondary_channel = -1;
+	} else {
+		iface->conf->channel -= 4;
+		iface->conf->secondary_channel = 1;
+	}
+}
+
+
+static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss,
+					int *pri_chan, int *sec_chan)
+{
+	struct ieee80211_ht_operation *oper;
+	struct ieee802_11_elems elems;
+
+	*pri_chan = *sec_chan = 0;
+
+	ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
+	if (elems.ht_operation &&
+	    elems.ht_operation_len >= sizeof(*oper)) {
+		oper = (struct ieee80211_ht_operation *) elems.ht_operation;
+		*pri_chan = oper->control_chan;
+		if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) {
+			if (oper->ht_param &
+			    HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
+				*sec_chan = *pri_chan + 4;
+			else if (oper->ht_param &
+				 HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
+				*sec_chan = *pri_chan - 4;
+		}
+	}
+}
+
+
+static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
+				     struct wpa_scan_results *scan_res)
+{
+	int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss;
+	int bss_pri_chan, bss_sec_chan;
+	size_t i;
+	int match;
+
+	pri_chan = iface->conf->channel;
+	sec_chan = iface->conf->secondary_channel * 4;
+	pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan);
+	if (iface->conf->secondary_channel > 0)
+		sec_freq = pri_freq + 20;
+	else
+		sec_freq = pri_freq - 20;
+
+	/*
+	 * Switch PRI/SEC channels if Beacons were detected on selected SEC
+	 * channel, but not on selected PRI channel.
+	 */
+	pri_bss = sec_bss = 0;
+	for (i = 0; i < scan_res->num; i++) {
+		struct wpa_scan_res *bss = scan_res->res[i];
+		if (bss->freq == pri_freq)
+			pri_bss++;
+		else if (bss->freq == sec_freq)
+			sec_bss++;
+	}
+	if (sec_bss && !pri_bss) {
+		wpa_printf(MSG_INFO, "Switch own primary and secondary "
+			   "channel to get secondary channel with no Beacons "
+			   "from other BSSes");
+		ieee80211n_switch_pri_sec(iface);
+	}
+
+	/*
+	 * Match PRI/SEC channel with any existing HT40 BSS on the same
+	 * channels that we are about to use (if already mixed order in
+	 * existing BSSes, use own preference).
+	 */
+	match = 0;
+	for (i = 0; i < scan_res->num; i++) {
+		struct wpa_scan_res *bss = scan_res->res[i];
+		ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
+		if (pri_chan == bss_pri_chan &&
+		    sec_chan == bss_sec_chan) {
+			match = 1;
+			break;
+		}
+	}
+	if (!match) {
+		for (i = 0; i < scan_res->num; i++) {
+			struct wpa_scan_res *bss = scan_res->res[i];
+			ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan,
+						    &bss_sec_chan);
+			if (pri_chan == bss_sec_chan &&
+			    sec_chan == bss_pri_chan) {
+				wpa_printf(MSG_INFO, "Switch own primary and "
+					   "secondary channel due to BSS "
+					   "overlap with " MACSTR,
+					   MAC2STR(bss->bssid));
+				ieee80211n_switch_pri_sec(iface);
+				break;
+			}
+		}
+	}
+
+	return 1;
+}
+
+
+static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
+				      struct wpa_scan_results *scan_res)
+{
+	int pri_freq, sec_freq;
+	int affected_start, affected_end;
+	size_t i;
+
+	pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
+	if (iface->conf->secondary_channel > 0)
+		sec_freq = pri_freq + 20;
+	else
+		sec_freq = pri_freq - 20;
+	affected_start = (pri_freq + sec_freq) / 2 - 25;
+	affected_end = (pri_freq + sec_freq) / 2 + 25;
+	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
+		   affected_start, affected_end);
+	for (i = 0; i < scan_res->num; i++) {
+		struct wpa_scan_res *bss = scan_res->res[i];
+		int pri = bss->freq;
+		int sec = pri;
+		int sec_chan, pri_chan;
+
+		ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan);
+
+		if (sec_chan) {
+			if (sec_chan < pri_chan)
+				sec = pri - 20;
+			else
+				sec = pri + 20;
+		}
+
+		if ((pri < affected_start || pri > affected_end) &&
+		    (sec < affected_start || sec > affected_end))
+			continue; /* not within affected channel range */
+
+		wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
+			   " freq=%d pri=%d sec=%d",
+			   MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
+
+		if (sec_chan) {
+			if (pri_freq != pri || sec_freq != sec) {
+				wpa_printf(MSG_DEBUG, "40 MHz pri/sec "
+					   "mismatch with BSS " MACSTR
+					   " <%d,%d> (chan=%d%c) vs. <%d,%d>",
+					   MAC2STR(bss->bssid),
+					   pri, sec, pri_chan,
+					   sec > pri ? '+' : '-',
+					   pri_freq, sec_freq);
+				return 0;
+			}
+		}
+
+		/* TODO: 40 MHz intolerant */
+	}
+
+	return 1;
+}
+
+
+static void wpa_scan_results_free(struct wpa_scan_results *res)
+{
+	size_t i;
+
+	if (res == NULL)
+		return;
+
+	for (i = 0; i < res->num; i++)
+		os_free(res->res[i]);
+	os_free(res->res);
+	os_free(res);
+}
+
+
+static void ieee80211n_check_scan(struct hostapd_iface *iface)
+{
+	struct wpa_scan_results *scan_res;
+	int oper40;
+
+	/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
+	 * allowed per IEEE 802.11n/D7.0, 11.14.3.2 */
+
+	iface->scan_cb = NULL;
+
+	scan_res = hostapd_driver_get_scan_results(iface->bss[0]);
+	if (scan_res == NULL) {
+		hostapd_setup_interface_complete(iface, 1);
+		return;
+	}
+
+	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
+		oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
+	else
+		oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
+	wpa_scan_results_free(scan_res);
+
+	if (!oper40) {
+		wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
+			   "channel pri=%d sec=%d based on overlapping BSSes",
+			   iface->conf->channel,
+			   iface->conf->channel +
+			   iface->conf->secondary_channel * 4);
+		iface->conf->secondary_channel = 0;
+		iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+	}
+
+	hostapd_setup_interface_complete(iface, 0);
+}
+
+
+static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
+{
+	struct wpa_driver_scan_params params;
+
+	if (!iface->conf->secondary_channel)
+		return 0; /* HT40 not used */
+
+	wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
+		   "40 MHz channel");
+	os_memset(¶ms, 0, sizeof(params));
+	/* TODO: scan only the needed frequency */
+	if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) {
+		wpa_printf(MSG_ERROR, "Failed to request a scan of "
+			   "neighboring BSSes");
+		return -1;
+	}
+
+	iface->scan_cb = ieee80211n_check_scan;
+	return 1;
+}
+
+
 static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
 {
 	u16 hw = iface->current_mode->ht_capab;
@@ -335,9 +577,27 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
 
 	return 1;
 }
+
 #endif /* CONFIG_IEEE80211N */
 
 
+int hostapd_check_ht_capab(struct hostapd_iface *iface)
+{
+#ifdef CONFIG_IEEE80211N
+	int ret;
+	ret = ieee80211n_check_40mhz(iface);
+	if (ret)
+		return ret;
+	if (!ieee80211n_allowed_ht40_channel_pair(iface))
+		return -1;
+	if (!ieee80211n_supported_ht_capab(iface))
+		return -1;
+#endif /* CONFIG_IEEE80211N */
+
+	return 0;
+}
+
+
 /**
  * hostapd_select_hw_mode - Select the hardware mode
  * @iface: Pointer to interface data.
@@ -348,7 +608,7 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
  */
 int hostapd_select_hw_mode(struct hostapd_iface *iface)
 {
-	int i, j, ok, ret;
+	int i, j, ok;
 
 	if (iface->num_hw_features < 1)
 		return -1;
@@ -356,7 +616,7 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
 	iface->current_mode = NULL;
 	for (i = 0; i < iface->num_hw_features; i++) {
 		struct hostapd_hw_modes *mode = &iface->hw_features[i];
-		if (mode->mode == (int) iface->conf->hw_mode) {
+		if (mode->mode == iface->conf->hw_mode) {
 			iface->current_mode = mode;
 			break;
 		}
@@ -408,13 +668,6 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
 		return -1;
 	}
 
-#ifdef CONFIG_IEEE80211N
-	if (!ieee80211n_allowed_ht40_channel_pair(iface))
-		return -1;
-	if (!ieee80211n_supported_ht_capab(iface))
-		return -1;
-#endif /* CONFIG_IEEE80211N */
-
 	if (hostapd_prepare_rates(iface->bss[0], iface->current_mode)) {
 		wpa_printf(MSG_ERROR, "Failed to prepare rates table.");
 		hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
@@ -423,23 +676,7 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
 		return -1;
 	}
 
-	ret = hostapd_passive_scan(iface->bss[0], 0,
-				   iface->conf->passive_scan_mode,
-				   iface->conf->passive_scan_interval,
-				   iface->conf->passive_scan_listen,
-				   NULL, NULL);
-	if (ret) {
-		if (ret == -1) {
-			wpa_printf(MSG_DEBUG, "Passive scanning not "
-				   "supported");
-		} else {
-			wpa_printf(MSG_ERROR, "Could not set passive "
-				   "scanning: %s", strerror(ret));
-		}
-		ret = 0;
-	}
-
-	return ret;
+	return 0;
 }
 
 
diff --git a/contrib/wpa/hostapd/hw_features.h b/contrib/wpa/src/ap/hw_features.h
similarity index 50%
rename from contrib/wpa/hostapd/hw_features.h
rename to contrib/wpa/src/ap/hw_features.h
index 7d43c89b6696..0295549fe1d3 100644
--- a/contrib/wpa/hostapd/hw_features.h
+++ b/contrib/wpa/src/ap/hw_features.h
@@ -16,41 +16,7 @@
 #ifndef HW_FEATURES_H
 #define HW_FEATURES_H
 
-#define HOSTAPD_CHAN_DISABLED 0x00000001
-#define HOSTAPD_CHAN_PASSIVE_SCAN 0x00000002
-#define HOSTAPD_CHAN_NO_IBSS 0x00000004
-#define HOSTAPD_CHAN_RADAR 0x00000008
-
-struct hostapd_channel_data {
-	short chan; /* channel number (IEEE 802.11) */
-	short freq; /* frequency in MHz */
-	int flag; /* flag for hostapd use (HOSTAPD_CHAN_*) */
-	u8 max_tx_power; /* maximum transmit power in dBm */
-};
-
-#define HOSTAPD_RATE_ERP 0x00000001
-#define HOSTAPD_RATE_BASIC 0x00000002
-#define HOSTAPD_RATE_PREAMBLE2 0x00000004
-#define HOSTAPD_RATE_SUPPORTED 0x00000010
-#define HOSTAPD_RATE_OFDM 0x00000020
-#define HOSTAPD_RATE_CCK 0x00000040
-#define HOSTAPD_RATE_MANDATORY 0x00000100
-
-struct hostapd_rate_data {
-	int rate; /* rate in 100 kbps */
-	int flags; /* HOSTAPD_RATE_ flags */
-};
-
-struct hostapd_hw_modes {
-	int mode;
-	int num_channels;
-	struct hostapd_channel_data *channels;
-	int num_rates;
-	struct hostapd_rate_data *rates;
-	u16 ht_capab;
-};
-
-
+#ifdef NEED_AP_MLME
 void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
 			      size_t num_hw_features);
 int hostapd_get_hw_features(struct hostapd_iface *iface);
@@ -58,5 +24,39 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface);
 const char * hostapd_hw_mode_txt(int mode);
 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
+int hostapd_check_ht_capab(struct hostapd_iface *iface);
+#else /* NEED_AP_MLME */
+static inline void
+hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
+			 size_t num_hw_features)
+{
+}
+
+static inline int hostapd_get_hw_features(struct hostapd_iface *iface)
+{
+	return -1;
+}
+
+static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
+{
+	return -1;
+}
+
+static inline const char * hostapd_hw_mode_txt(int mode)
+{
+	return NULL;
+}
+
+static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
+{
+	return -1;
+}
+
+static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
+{
+	return 0;
+}
+
+#endif /* NEED_AP_MLME */
 
 #endif /* HW_FEATURES_H */
diff --git a/contrib/wpa/hostapd/iapp.c b/contrib/wpa/src/ap/iapp.c
similarity index 95%
rename from contrib/wpa/hostapd/iapp.c
rename to contrib/wpa/src/ap/iapp.c
index 6d6dba8f7b9a..115d91e8ce30 100644
--- a/contrib/wpa/hostapd/iapp.c
+++ b/contrib/wpa/src/ap/iapp.c
@@ -37,7 +37,7 @@
  * - IEEE 802.11 context transfer
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 #include 
 #include 
 #ifdef USE_KERNEL_HEADERS
@@ -46,11 +46,14 @@
 #include 
 #endif /* USE_KERNEL_HEADERS */
 
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
 #include "hostapd.h"
+#include "ap_config.h"
 #include "ieee802_11.h"
-#include "iapp.h"
-#include "eloop.h"
 #include "sta_info.h"
+#include "iapp.h"
 
 
 #define IAPP_MULTICAST "224.0.1.178"
@@ -304,10 +307,7 @@ static void iapp_process_add_notify(struct iapp_data *iapp,
 	hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
 		       HOSTAPD_LEVEL_DEBUG,
 		       "Removing STA due to IAPP ADD-notify");
-	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED);
-	eloop_cancel_timeout(ap_handle_timer, iapp->hapd, sta);
-	eloop_register_timeout(0, 0, ap_handle_timer, iapp->hapd, sta);
-	sta->timeout_next = STA_REMOVE;
+	ap_sta_disconnect(iapp->hapd, sta, NULL, 0);
 }
 
 
@@ -533,21 +533,3 @@ void iapp_deinit(struct iapp_data *iapp)
 	}
 	os_free(iapp);
 }
-
-int iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf,
-		  struct hostapd_bss_config *oldbss)
-{
-	if (hapd->conf->ieee802_11f != oldbss->ieee802_11f ||
-	    os_strcmp(hapd->conf->iapp_iface, oldbss->iapp_iface) != 0) {
-		iapp_deinit(hapd->iapp);
-		hapd->iapp = NULL;
-
-		if (hapd->conf->ieee802_11f) {
-			hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface);
-			if (hapd->iapp == NULL)
-				return -1;
-		}
-	}
-
-	return 0;
-}
diff --git a/contrib/wpa/hostapd/iapp.h b/contrib/wpa/src/ap/iapp.h
similarity index 79%
rename from contrib/wpa/hostapd/iapp.h
rename to contrib/wpa/src/ap/iapp.h
index 86de59256043..5fc01cb70355 100644
--- a/contrib/wpa/hostapd/iapp.h
+++ b/contrib/wpa/src/ap/iapp.h
@@ -22,8 +22,6 @@ struct iapp_data;
 void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta);
 struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface);
 void iapp_deinit(struct iapp_data *iapp);
-int iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf,
-		  struct hostapd_bss_config *oldbss);
 
 #else /* CONFIG_IAPP */
 
@@ -42,13 +40,6 @@ static inline void iapp_deinit(struct iapp_data *iapp)
 {
 }
 
-static inline int
-iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf,
-	      struct hostapd_bss_config *oldbss)
-{
-	return 0;
-}
-
 #endif /* CONFIG_IAPP */
 
 #endif /* IAPP_H */
diff --git a/contrib/wpa/hostapd/ieee802_11.c b/contrib/wpa/src/ap/ieee802_11.c
similarity index 68%
rename from contrib/wpa/hostapd/ieee802_11.c
rename to contrib/wpa/src/ap/ieee802_11.c
index 70491b4fa22e..3375aa2a3cf8 100644
--- a/contrib/wpa/hostapd/ieee802_11.c
+++ b/contrib/wpa/src/ap/ieee802_11.c
@@ -1,7 +1,6 @@
 /*
  * hostapd / IEEE 802.11 Management
- * Copyright (c) 2002-2008, Jouni Malinen 
- * Copyright (c) 2007-2008, Intel Corporation
+ * Copyright (c) 2002-2010, Jouni Malinen 
  *
  * 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
@@ -13,29 +12,32 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
 #ifndef CONFIG_NATIVE_WINDOWS
 
-#include 
-
-#include "eloop.h"
-#include "hostapd.h"
-#include "ieee802_11.h"
-#include "beacon.h"
-#include "hw_features.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "crypto/crypto.h"
+#include "drivers/driver.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "common/wpa_ctrl.h"
 #include "radius/radius.h"
 #include "radius/radius_client.h"
+#include "wps/wps.h"
+#include "hostapd.h"
+#include "beacon.h"
 #include "ieee802_11_auth.h"
 #include "sta_info.h"
-#include "rc4.h"
 #include "ieee802_1x.h"
-#include "wpa.h"
-#include "wme.h"
+#include "wpa_auth.h"
+#include "wmm.h"
 #include "ap_list.h"
 #include "accounting.h"
-#include "driver.h"
-#include "mlme.h"
+#include "ap_config.h"
+#include "ap_mlme.h"
+#include "ieee802_11.h"
 
 
 u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
@@ -100,153 +102,6 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
 }
 
 
-u8 * hostapd_eid_ht_capabilities_info(struct hostapd_data *hapd, u8 *eid)
-{
-#ifdef CONFIG_IEEE80211N
-	struct ieee80211_ht_capability *cap;
-	u8 *pos = eid;
-
-	if (!hapd->iconf->ieee80211n)
-		return eid;
-
-	*pos++ = WLAN_EID_HT_CAP;
-	*pos++ = sizeof(*cap);
-
-	cap = (struct ieee80211_ht_capability *) pos;
-	os_memset(cap, 0, sizeof(*cap));
-	SET_2BIT_U8(&cap->mac_ht_params_info,
-		    MAC_HT_PARAM_INFO_MAX_RX_AMPDU_FACTOR_OFFSET,
-		    MAX_RX_AMPDU_FACTOR_64KB);
-
-	cap->capabilities_info = host_to_le16(hapd->iconf->ht_capab);
-
-	cap->supported_mcs_set[0] = 0xff;
-	cap->supported_mcs_set[1] = 0xff;
-
- 	pos += sizeof(*cap);
-
-	return pos;
-#else /* CONFIG_IEEE80211N */
-	return eid;
-#endif /* CONFIG_IEEE80211N */
-}
-
-
-u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
-{
-#ifdef CONFIG_IEEE80211N
-	struct ieee80211_ht_operation *oper;
-	u8 *pos = eid;
-
-	if (!hapd->iconf->ieee80211n)
-		return eid;
-
-	*pos++ = WLAN_EID_HT_OPERATION;
-	*pos++ = sizeof(*oper);
-
-	oper = (struct ieee80211_ht_operation *) pos;
-	os_memset(oper, 0, sizeof(*oper));
-
-	oper->control_chan = hapd->iconf->channel;
-	oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
-	if (hapd->iconf->secondary_channel == 1)
-		oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
-			HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
-	if (hapd->iconf->secondary_channel == -1)
-		oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
-			HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
-
-	pos += sizeof(*oper);
-
-	return pos;
-#else /* CONFIG_IEEE80211N */
-	return eid;
-#endif /* CONFIG_IEEE80211N */
-}
-
-
-#ifdef CONFIG_IEEE80211N
-
-/*
-op_mode
-Set to 0 (HT pure) under the followign conditions
-	- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
-	- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
-Set to 1 (HT non-member protection) if there may be non-HT STAs
-	in both the primary and the secondary channel
-Set to 2 if only HT STAs are associated in BSS,
-	however and at least one 20 MHz HT STA is associated
-Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
-	(currently non-GF HT station is considered as non-HT STA also)
-*/
-int hostapd_ht_operation_update(struct hostapd_iface *iface)
-{
-	u16 cur_op_mode, new_op_mode;
-	int op_mode_changes = 0;
-
-	if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
-		return 0;
-
-	wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X",
-		   __func__, iface->ht_op_mode);
-
-	if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
-	    && iface->num_sta_ht_no_gf) {
-		iface->ht_op_mode |=
-			HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
-		op_mode_changes++;
-	} else if ((iface->ht_op_mode &
-		    HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
-		   iface->num_sta_ht_no_gf == 0) {
-		iface->ht_op_mode &=
-			~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
-		op_mode_changes++;
-	}
-
-	if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
-	    (iface->num_sta_no_ht || iface->olbc_ht)) {
-		iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
-		op_mode_changes++;
-	} else if ((iface->ht_op_mode &
-		    HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
-		   (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) {
-		iface->ht_op_mode &=
-			~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
-		op_mode_changes++;
-	}
-
-	/* Note: currently we switch to the MIXED op mode if HT non-greenfield
-	 * station is associated. Probably it's a theoretical case, since
-	 * it looks like all known HT STAs support greenfield.
-	 */
-	new_op_mode = 0;
-	if (iface->num_sta_no_ht ||
-	    (iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
-		new_op_mode = OP_MODE_MIXED;
-	else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
-		 && iface->num_sta_ht_20mhz)
-		new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
-	else if (iface->olbc_ht)
-		new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
-	else
-		new_op_mode = OP_MODE_PURE;
-
-	cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
-	if (cur_op_mode != new_op_mode) {
-		iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
-		iface->ht_op_mode |= new_op_mode;
-		op_mode_changes++;
-	}
-
-	wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d",
-		   __func__, iface->ht_op_mode, op_mode_changes);
-
-	return op_mode_changes;
-}
-
-#endif /* CONFIG_IEEE80211N */
-
-
 u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
 			   int probe)
 {
@@ -336,34 +191,9 @@ void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len)
 }
 
 
-/**
- * ieee802_11_send_deauth - Send Deauthentication frame
- * @hapd: hostapd BSS data
- * @addr: Address of the destination STA
- * @reason: Reason code for Deauthentication
- */
-void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason)
-{
-	struct ieee80211_mgmt mgmt;
-
-	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
-		       HOSTAPD_LEVEL_DEBUG,
-		       "deauthenticate - reason %d", reason);
-	os_memset(&mgmt, 0, sizeof(mgmt));
-	mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
-					  WLAN_FC_STYPE_DEAUTH);
-	os_memcpy(mgmt.da, addr, ETH_ALEN);
-	os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
-	os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
-	mgmt.u.deauth.reason_code = host_to_le16(reason);
-	if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN +
-				    sizeof(mgmt.u.deauth), 0) < 0)
-		perror("ieee802_11_send_deauth: send");
-}
-
-
 static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
-			   u16 auth_transaction, u8 *challenge, int iswep)
+			   u16 auth_transaction, const u8 *challenge,
+			   int iswep)
 {
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_DEBUG,
@@ -452,7 +282,7 @@ static void send_auth_reply(struct hostapd_data *hapd,
 		   " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)",
 		   MAC2STR(dst), auth_alg, auth_transaction,
 		   resp, (unsigned long) ies_len);
-	if (hostapd_send_mgmt_frame(hapd, reply, rlen, 0) < 0)
+	if (hapd->drv.send_mgmt_frame(hapd, reply, rlen) < 0)
 		perror("send_auth_reply: send");
 
 	os_free(buf);
@@ -485,15 +315,15 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
 #endif /* CONFIG_IEEE80211R */
 
 
-static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
-			size_t len)
+static void handle_auth(struct hostapd_data *hapd,
+			const struct ieee80211_mgmt *mgmt, size_t len)
 {
 	u16 auth_alg, auth_transaction, status_code;
 	u16 resp = WLAN_STATUS_SUCCESS;
 	struct sta_info *sta = NULL;
 	int res;
 	u16 fc;
-	u8 *challenge = NULL;
+	const u8 *challenge = NULL;
 	u32 session_timeout, acct_interim_interval;
 	int vlan_id = 0;
 	u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
@@ -601,8 +431,7 @@ static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
 	sta->flags &= ~WLAN_STA_PREAUTH;
 	ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
 
-	if (hapd->conf->radius->acct_interim_interval == 0 &&
-	    acct_interim_interval)
+	if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
 		sta->acct_interim_interval = acct_interim_interval;
 	if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
 		ap_sta_session_timeout(hapd, sta, session_timeout);
@@ -665,18 +494,388 @@ static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
 }
 
 
+static int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	int i, j = 32, aid;
+
+	/* get a unique AID */
+	if (sta->aid > 0) {
+		wpa_printf(MSG_DEBUG, "  old AID %d", sta->aid);
+		return 0;
+	}
+
+	for (i = 0; i < AID_WORDS; i++) {
+		if (hapd->sta_aid[i] == (u32) -1)
+			continue;
+		for (j = 0; j < 32; j++) {
+			if (!(hapd->sta_aid[i] & BIT(j)))
+				break;
+		}
+		if (j < 32)
+			break;
+	}
+	if (j == 32)
+		return -1;
+	aid = i * 32 + j + 1;
+	if (aid > 2007)
+		return -1;
+
+	sta->aid = aid;
+	hapd->sta_aid[i] |= BIT(j);
+	wpa_printf(MSG_DEBUG, "  new AID %d", sta->aid);
+	return 0;
+}
+
+
+static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
+		      const u8 *ssid_ie, size_t ssid_ie_len)
+{
+	if (ssid_ie == NULL)
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+
+	if (ssid_ie_len != hapd->conf->ssid.ssid_len ||
+	    os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) {
+		char ssid_txt[33];
+		ieee802_11_print_ssid(ssid_txt, ssid_ie, ssid_ie_len);
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_INFO,
+			       "Station tried to associate with unknown SSID "
+			       "'%s'", ssid_txt);
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+
+static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
+		     const u8 *wmm_ie, size_t wmm_ie_len)
+{
+	sta->flags &= ~WLAN_STA_WMM;
+	if (wmm_ie && hapd->conf->wmm_enabled) {
+		if (hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len))
+			hostapd_logger(hapd, sta->addr,
+				       HOSTAPD_MODULE_WPA,
+				       HOSTAPD_LEVEL_DEBUG,
+				       "invalid WMM element in association "
+				       "request");
+		else
+			sta->flags |= WLAN_STA_WMM;
+	}
+	return WLAN_STATUS_SUCCESS;
+}
+
+
+static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
+			   struct ieee802_11_elems *elems)
+{
+	if (!elems->supp_rates) {
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_DEBUG,
+			       "No supported rates element in AssocReq");
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	}
+
+	if (elems->supp_rates_len > sizeof(sta->supported_rates)) {
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_DEBUG,
+			       "Invalid supported rates element length %d",
+			       elems->supp_rates_len);
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	}
+
+	os_memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
+	os_memcpy(sta->supported_rates, elems->supp_rates,
+		  elems->supp_rates_len);
+	sta->supported_rates_len = elems->supp_rates_len;
+
+	if (elems->ext_supp_rates) {
+		if (elems->supp_rates_len + elems->ext_supp_rates_len >
+		    sizeof(sta->supported_rates)) {
+			hostapd_logger(hapd, sta->addr,
+				       HOSTAPD_MODULE_IEEE80211,
+				       HOSTAPD_LEVEL_DEBUG,
+				       "Invalid supported rates element length"
+				       " %d+%d", elems->supp_rates_len,
+				       elems->ext_supp_rates_len);
+			return WLAN_STATUS_UNSPECIFIED_FAILURE;
+		}
+
+		os_memcpy(sta->supported_rates + elems->supp_rates_len,
+			  elems->ext_supp_rates, elems->ext_supp_rates_len);
+		sta->supported_rates_len += elems->ext_supp_rates_len;
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+
+static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
+			   const u8 *ies, size_t ies_len, int reassoc)
+{
+	struct ieee802_11_elems elems;
+	u16 resp;
+	const u8 *wpa_ie;
+	size_t wpa_ie_len;
+
+	if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_INFO, "Station sent an invalid "
+			       "association request");
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	}
+
+	resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len);
+	if (resp != WLAN_STATUS_SUCCESS)
+		return resp;
+	resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len);
+	if (resp != WLAN_STATUS_SUCCESS)
+		return resp;
+	resp = copy_supp_rates(hapd, sta, &elems);
+	if (resp != WLAN_STATUS_SUCCESS)
+		return resp;
+#ifdef CONFIG_IEEE80211N
+	resp = copy_sta_ht_capab(sta, elems.ht_capabilities,
+				 elems.ht_capabilities_len);
+	if (resp != WLAN_STATUS_SUCCESS)
+		return resp;
+#endif /* CONFIG_IEEE80211N */
+
+	if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
+		wpa_ie = elems.rsn_ie;
+		wpa_ie_len = elems.rsn_ie_len;
+	} else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
+		   elems.wpa_ie) {
+		wpa_ie = elems.wpa_ie;
+		wpa_ie_len = elems.wpa_ie_len;
+	} else {
+		wpa_ie = NULL;
+		wpa_ie_len = 0;
+	}
+
+#ifdef CONFIG_WPS
+	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
+	if (hapd->conf->wps_state && elems.wps_ie) {
+		wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
+			   "Request - assume WPS is used");
+		sta->flags |= WLAN_STA_WPS;
+		wpabuf_free(sta->wps_ie);
+		sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
+							  WPS_IE_VENDOR_TYPE);
+		wpa_ie = NULL;
+		wpa_ie_len = 0;
+	} else if (hapd->conf->wps_state && wpa_ie == NULL) {
+		wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in "
+			   "(Re)Association Request - possible WPS use");
+		sta->flags |= WLAN_STA_MAYBE_WPS;
+	} else
+#endif /* CONFIG_WPS */
+	if (hapd->conf->wpa && wpa_ie == NULL) {
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_INFO,
+			       "No WPA/RSN IE in association request");
+		return WLAN_STATUS_INVALID_IE;
+	}
+
+	if (hapd->conf->wpa && wpa_ie) {
+		int res;
+		wpa_ie -= 2;
+		wpa_ie_len += 2;
+		if (sta->wpa_sm == NULL)
+			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
+							sta->addr);
+		if (sta->wpa_sm == NULL) {
+			wpa_printf(MSG_WARNING, "Failed to initialize WPA "
+				   "state machine");
+			return WLAN_STATUS_UNSPECIFIED_FAILURE;
+		}
+		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
+					  wpa_ie, wpa_ie_len,
+					  elems.mdie, elems.mdie_len);
+		if (res == WPA_INVALID_GROUP)
+			resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
+		else if (res == WPA_INVALID_PAIRWISE)
+			resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
+		else if (res == WPA_INVALID_AKMP)
+			resp = WLAN_STATUS_AKMP_NOT_VALID;
+		else if (res == WPA_ALLOC_FAIL)
+			resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+#ifdef CONFIG_IEEE80211W
+		else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
+			resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
+		else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
+			resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
+#endif /* CONFIG_IEEE80211W */
+		else if (res == WPA_INVALID_MDIE)
+			resp = WLAN_STATUS_INVALID_MDIE;
+		else if (res != WPA_IE_OK)
+			resp = WLAN_STATUS_INVALID_IE;
+		if (resp != WLAN_STATUS_SUCCESS)
+			return resp;
+#ifdef CONFIG_IEEE80211W
+		if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
+		    sta->sa_query_count > 0)
+			ap_check_sa_query_timeout(hapd, sta);
+		if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
+		    (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
+			/*
+			 * STA has already been associated with MFP and SA
+			 * Query timeout has not been reached. Reject the
+			 * association attempt temporarily and start SA Query,
+			 * if one is not pending.
+			 */
+
+			if (sta->sa_query_count == 0)
+				ap_sta_start_sa_query(hapd, sta);
+
+			return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
+		}
+
+		if (wpa_auth_uses_mfp(sta->wpa_sm))
+			sta->flags |= WLAN_STA_MFP;
+		else
+			sta->flags &= ~WLAN_STA_MFP;
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_IEEE80211R
+		if (sta->auth_alg == WLAN_AUTH_FT) {
+			if (!reassoc) {
+				wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
+					   "to use association (not "
+					   "re-association) with FT auth_alg",
+					   MAC2STR(sta->addr));
+				return WLAN_STATUS_UNSPECIFIED_FAILURE;
+			}
+
+			resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies,
+						       ies_len);
+			if (resp != WLAN_STATUS_SUCCESS)
+				return resp;
+		}
+#endif /* CONFIG_IEEE80211R */
+
+#ifdef CONFIG_IEEE80211N
+		if ((sta->flags & WLAN_STA_HT) &&
+		    wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
+			hostapd_logger(hapd, sta->addr,
+				       HOSTAPD_MODULE_IEEE80211,
+				       HOSTAPD_LEVEL_INFO,
+				       "Station tried to use TKIP with HT "
+				       "association");
+			return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
+		}
+#endif /* CONFIG_IEEE80211N */
+	} else
+		wpa_auth_sta_no_wpa(sta->wpa_sm);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+
+static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
+			u16 reason_code)
+{
+	int send_len;
+	struct ieee80211_mgmt reply;
+
+	os_memset(&reply, 0, sizeof(reply));
+	reply.frame_control =
+		IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH);
+	os_memcpy(reply.da, addr, ETH_ALEN);
+	os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN);
+
+	send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
+	reply.u.deauth.reason_code = host_to_le16(reason_code);
+
+	if (hapd->drv.send_mgmt_frame(hapd, &reply, send_len) < 0)
+		wpa_printf(MSG_INFO, "Failed to send deauth: %s",
+			   strerror(errno));
+}
+
+
+static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
+			    u16 status_code, int reassoc, const u8 *ies,
+			    size_t ies_len)
+{
+	int send_len;
+	u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
+	struct ieee80211_mgmt *reply;
+	u8 *p;
+
+	os_memset(buf, 0, sizeof(buf));
+	reply = (struct ieee80211_mgmt *) buf;
+	reply->frame_control =
+		IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+			     (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
+			      WLAN_FC_STYPE_ASSOC_RESP));
+	os_memcpy(reply->da, sta->addr, ETH_ALEN);
+	os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN);
+
+	send_len = IEEE80211_HDRLEN;
+	send_len += sizeof(reply->u.assoc_resp);
+	reply->u.assoc_resp.capab_info =
+		host_to_le16(hostapd_own_capab_info(hapd, sta, 0));
+	reply->u.assoc_resp.status_code = host_to_le16(status_code);
+	reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0)
+					       | BIT(14) | BIT(15));
+	/* Supported rates */
+	p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
+	/* Extended supported rates */
+	p = hostapd_eid_ext_supp_rates(hapd, p);
+
+#ifdef CONFIG_IEEE80211R
+	if (status_code == WLAN_STATUS_SUCCESS) {
+		/* IEEE 802.11r: Mobility Domain Information, Fast BSS
+		 * Transition Information, RSN, [RIC Response] */
+		p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
+						buf + sizeof(buf) - p,
+						sta->auth_alg, ies, ies_len);
+	}
+#endif /* CONFIG_IEEE80211R */
+
+#ifdef CONFIG_IEEE80211W
+	if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
+		p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_IEEE80211N
+	p = hostapd_eid_ht_capabilities(hapd, p);
+	p = hostapd_eid_ht_operation(hapd, p);
+#endif /* CONFIG_IEEE80211N */
+
+	if (sta->flags & WLAN_STA_WMM)
+		p = hostapd_eid_wmm(hapd, p);
+
+#ifdef CONFIG_WPS
+	if (sta->flags & WLAN_STA_WPS) {
+		struct wpabuf *wps = wps_build_assoc_resp_ie();
+		if (wps) {
+			os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps));
+			p += wpabuf_len(wps);
+			wpabuf_free(wps);
+		}
+	}
+#endif /* CONFIG_WPS */
+
+	send_len += p - reply->u.assoc_resp.variable;
+
+	if (hapd->drv.send_mgmt_frame(hapd, reply, send_len) < 0)
+		wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
+			   strerror(errno));
+}
+
+
 static void handle_assoc(struct hostapd_data *hapd,
-			 struct ieee80211_mgmt *mgmt, size_t len, int reassoc)
+			 const struct ieee80211_mgmt *mgmt, size_t len,
+			 int reassoc)
 {
 	u16 capab_info, listen_interval;
 	u16 resp = WLAN_STATUS_SUCCESS;
-	u8 *pos, *wpa_ie;
-	size_t wpa_ie_len;
-	int send_deauth = 0, send_len, left, i;
+	const u8 *pos;
+	int left, i;
 	struct sta_info *sta;
-	struct ieee802_11_elems elems;
-	u8 buf[sizeof(struct ieee80211_mgmt) + 512];
-	struct ieee80211_mgmt *reply;
 
 	if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
 				      sizeof(mgmt->u.assoc_req))) {
@@ -717,15 +916,15 @@ static void handle_assoc(struct hostapd_data *hapd,
 	} else
 #endif /* CONFIG_IEEE80211R */
 	if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
-		printf("STA " MACSTR " trying to associate before "
-		       "authentication\n", MAC2STR(mgmt->sa));
-		if (sta) {
-			printf("  sta: addr=" MACSTR " aid=%d flags=0x%04x\n",
-			       MAC2STR(sta->addr), sta->aid, sta->flags);
-		}
-		send_deauth = 1;
-		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
-		goto fail;
+		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_INFO, "Station tried to "
+			       "associate before authentication "
+			       "(aid=%d flags=0x%x)",
+			       sta ? sta->aid : -1,
+			       sta ? sta->flags : 0);
+		send_deauth(hapd, mgmt->sa,
+			    WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
+		return;
 	}
 
 	if (hapd->tkip_countermeasures) {
@@ -742,225 +941,21 @@ static void handle_assoc(struct hostapd_data *hapd,
 		goto fail;
 	}
 
-	sta->capability = capab_info;
-	sta->listen_interval = listen_interval;
-
 	/* followed by SSID and Supported rates; and HT capabilities if 802.11n
 	 * is used */
-	if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
-	    !elems.ssid) {
-		printf("STA " MACSTR " sent invalid association request\n",
-		       MAC2STR(sta->addr));
-		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+	resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
+	if (resp != WLAN_STATUS_SUCCESS)
 		goto fail;
-	}
 
-	if (elems.ssid_len != hapd->conf->ssid.ssid_len ||
-	    os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) != 0)
-	{
-		char ssid_txt[33];
-		ieee802_11_print_ssid(ssid_txt, elems.ssid, elems.ssid_len);
-		printf("Station " MACSTR " tried to associate with "
-		       "unknown SSID '%s'\n", MAC2STR(sta->addr), ssid_txt);
-		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
-		goto fail;
-	}
-
-	sta->flags &= ~WLAN_STA_WMM;
-	if (elems.wmm && hapd->conf->wmm_enabled) {
-		if (hostapd_eid_wmm_valid(hapd, elems.wmm, elems.wmm_len))
-			hostapd_logger(hapd, sta->addr,
-				       HOSTAPD_MODULE_WPA,
-				       HOSTAPD_LEVEL_DEBUG,
-				       "invalid WMM element in association "
-				       "request");
-		else
-			sta->flags |= WLAN_STA_WMM;
-	}
-
-	if (!elems.supp_rates) {
+	if (hostapd_get_aid(hapd, sta) < 0) {
 		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
-			       HOSTAPD_LEVEL_DEBUG,
-			       "No supported rates element in AssocReq");
-		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			       HOSTAPD_LEVEL_INFO, "No room for more AIDs");
+		resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
 		goto fail;
 	}
 
-	if (elems.supp_rates_len > sizeof(sta->supported_rates)) {
-		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
-			       HOSTAPD_LEVEL_DEBUG,
-			       "Invalid supported rates element length %d",
-			       elems.supp_rates_len);
-		resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
-		goto fail;
-	}
-
-	os_memset(sta->supported_rates, 0, sizeof(sta->supported_rates));
-	os_memcpy(sta->supported_rates, elems.supp_rates,
-		  elems.supp_rates_len);
-	sta->supported_rates_len = elems.supp_rates_len;
-
-	if (elems.ext_supp_rates) {
-		if (elems.supp_rates_len + elems.ext_supp_rates_len >
-		    sizeof(sta->supported_rates)) {
-			hostapd_logger(hapd, mgmt->sa,
-				       HOSTAPD_MODULE_IEEE80211,
-				       HOSTAPD_LEVEL_DEBUG,
-				       "Invalid supported rates element length"
-				       " %d+%d", elems.supp_rates_len,
-				       elems.ext_supp_rates_len);
-			resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
-			goto fail;
-		}
-
-		os_memcpy(sta->supported_rates + elems.supp_rates_len,
-			  elems.ext_supp_rates, elems.ext_supp_rates_len);
-		sta->supported_rates_len += elems.ext_supp_rates_len;
-	}
-
-#ifdef CONFIG_IEEE80211N
-	/* save HT capabilities in the sta object */
-	os_memset(&sta->ht_capabilities, 0, sizeof(sta->ht_capabilities));
-	if (elems.ht_capabilities &&
-	    elems.ht_capabilities_len >=
-	    sizeof(struct ieee80211_ht_capability)) {
-		sta->flags |= WLAN_STA_HT;
-		sta->ht_capabilities.id = WLAN_EID_HT_CAP;
-		sta->ht_capabilities.length =
-			sizeof(struct ieee80211_ht_capability);
-		os_memcpy(&sta->ht_capabilities.data,
-			  elems.ht_capabilities,
-			  sizeof(struct ieee80211_ht_capability));
-	} else
-		sta->flags &= ~WLAN_STA_HT;
-#endif /* CONFIG_IEEE80211N */
-
-	if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
-		wpa_ie = elems.rsn_ie;
-		wpa_ie_len = elems.rsn_ie_len;
-	} else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
-		   elems.wpa_ie) {
-		wpa_ie = elems.wpa_ie;
-		wpa_ie_len = elems.wpa_ie_len;
-	} else {
-		wpa_ie = NULL;
-		wpa_ie_len = 0;
-	}
-#ifdef CONFIG_WPS
-	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
-	if (hapd->conf->wps_state && wpa_ie == NULL) {
-		if (elems.wps_ie) {
-			wpa_printf(MSG_DEBUG, "STA included WPS IE in "
-				   "(Re)Association Request - assume WPS is "
-				   "used");
-			sta->flags |= WLAN_STA_WPS;
-			wpabuf_free(sta->wps_ie);
-			sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4,
-							elems.wps_ie_len - 4);
-		} else {
-			wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE "
-				   "in (Re)Association Request - possible WPS "
-				   "use");
-			sta->flags |= WLAN_STA_MAYBE_WPS;
-		}
-	} else
-#endif /* CONFIG_WPS */
-	if (hapd->conf->wpa && wpa_ie == NULL) {
-		printf("STA " MACSTR ": No WPA/RSN IE in association "
-		       "request\n", MAC2STR(sta->addr));
-		resp = WLAN_STATUS_INVALID_IE;
-		goto fail;
-	}
-
-	if (hapd->conf->wpa && wpa_ie) {
-		int res;
-		wpa_ie -= 2;
-		wpa_ie_len += 2;
-		if (sta->wpa_sm == NULL)
-			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
-							sta->addr);
-		if (sta->wpa_sm == NULL) {
-			printf("Failed to initialize WPA state machine\n");
-			resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
-			goto fail;
-		}
-		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
-					  wpa_ie, wpa_ie_len,
-					  elems.mdie, elems.mdie_len);
-		if (res == WPA_INVALID_GROUP)
-			resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
-		else if (res == WPA_INVALID_PAIRWISE)
-			resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
-		else if (res == WPA_INVALID_AKMP)
-			resp = WLAN_STATUS_AKMP_NOT_VALID;
-		else if (res == WPA_ALLOC_FAIL)
-			resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
-#ifdef CONFIG_IEEE80211W
-		else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
-			resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
-		else if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
-			resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
-#endif /* CONFIG_IEEE80211W */
-		else if (res == WPA_INVALID_MDIE)
-			resp = WLAN_STATUS_INVALID_MDIE;
-		else if (res != WPA_IE_OK)
-			resp = WLAN_STATUS_INVALID_IE;
-		if (resp != WLAN_STATUS_SUCCESS)
-			goto fail;
-#ifdef CONFIG_IEEE80211W
-		if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
-		    sta->sa_query_count > 0)
-			ap_check_sa_query_timeout(hapd, sta);
-		if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
-		    (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
-			/*
-			 * STA has already been associated with MFP and SA
-			 * Query timeout has not been reached. Reject the
-			 * association attempt temporarily and start SA Query,
-			 * if one is not pending.
-			 */
-
-			if (sta->sa_query_count == 0)
-				ap_sta_start_sa_query(hapd, sta);
-
-			resp = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
-			goto fail;
-		}
-
-		if (wpa_auth_uses_mfp(sta->wpa_sm))
-			sta->flags |= WLAN_STA_MFP;
-		else
-			sta->flags &= ~WLAN_STA_MFP;
-#endif /* CONFIG_IEEE80211W */
-
-#ifdef CONFIG_IEEE80211R
-		if (sta->auth_alg == WLAN_AUTH_FT) {
-			if (!reassoc) {
-				wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
-					   "to use association (not "
-					   "re-association) with FT auth_alg",
-					   MAC2STR(sta->addr));
-				resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
-				goto fail;
-			}
-
-			resp = wpa_ft_validate_reassoc(sta->wpa_sm, pos, left);
-			if (resp != WLAN_STATUS_SUCCESS)
-				goto fail;
-		}
-#endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_IEEE80211N
-		if ((sta->flags & WLAN_STA_HT) &&
-		    wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
-			wpa_printf(MSG_DEBUG, "HT: " MACSTR " tried to "
-				   "use TKIP with HT association",
-				   MAC2STR(sta->addr));
-			resp = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
-			goto fail;
-		}
-#endif /* CONFIG_IEEE80211N */
-	} else
-		wpa_auth_sta_no_wpa(sta->wpa_sm);
+	sta->capability = capab_info;
+	sta->listen_interval = listen_interval;
 
 	if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
 		sta->flags |= WLAN_STA_NONERP;
@@ -1002,66 +997,9 @@ static void handle_assoc(struct hostapd_data *hapd,
 	}
 
 #ifdef CONFIG_IEEE80211N
-	if (sta->flags & WLAN_STA_HT) {
-		u16 ht_capab = le_to_host16(
-			sta->ht_capabilities.data.capabilities_info);
-		wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities "
-			   "Info: 0x%04x", MAC2STR(sta->addr), ht_capab);
-		if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) {
-			if (!sta->no_ht_gf_set) {
-				sta->no_ht_gf_set = 1;
-				hapd->iface->num_sta_ht_no_gf++;
-			}
-			wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no "
-				   "greenfield, num of non-gf stations %d",
-				   __func__, MAC2STR(sta->addr),
-				   hapd->iface->num_sta_ht_no_gf);
-		}
-		if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) {
-			if (!sta->ht_20mhz_set) {
-				sta->ht_20mhz_set = 1;
-				hapd->iface->num_sta_ht_20mhz++;
-			}
-			wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, "
-				   "num of 20MHz HT STAs %d",
-				   __func__, MAC2STR(sta->addr),
-				   hapd->iface->num_sta_ht_20mhz);
-		}
-	} else {
-		if (!sta->no_ht_set) {
-			sta->no_ht_set = 1;
-			hapd->iface->num_sta_no_ht++;
-		}
-		if (hapd->iconf->ieee80211n) {
-			wpa_printf(MSG_DEBUG, "%s STA " MACSTR
-				   " - no HT, num of non-HT stations %d",
-				   __func__, MAC2STR(sta->addr),
-				   hapd->iface->num_sta_no_ht);
-		}
-	}
-
-	if (hostapd_ht_operation_update(hapd->iface) > 0)
-		ieee802_11_set_beacons(hapd->iface);
+	update_ht_state(hapd, sta);
 #endif /* CONFIG_IEEE80211N */
 
-	/* get a unique AID */
-	if (sta->aid > 0) {
-		wpa_printf(MSG_DEBUG, "  old AID %d", sta->aid);
-	} else {
-		for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++)
-			if (hapd->sta_aid[sta->aid - 1] == NULL)
-				break;
-		if (sta->aid > MAX_AID_TABLE_SIZE) {
-			sta->aid = 0;
-			resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
-			wpa_printf(MSG_ERROR, "  no room for more AIDs");
-			goto fail;
-		} else {
-			hapd->sta_aid[sta->aid - 1] = sta;
-			wpa_printf(MSG_DEBUG, "  new AID %d", sta->aid);
-		}
-	}
-
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_DEBUG,
 		       "association OK (aid %d)", sta->aid);
@@ -1097,64 +1035,12 @@ static void handle_assoc(struct hostapd_data *hapd,
 	sta->timeout_next = STA_NULLFUNC;
 
  fail:
-	os_memset(buf, 0, sizeof(buf));
-	reply = (struct ieee80211_mgmt *) buf;
-	reply->frame_control =
-		IEEE80211_FC(WLAN_FC_TYPE_MGMT,
-			     (send_deauth ? WLAN_FC_STYPE_DEAUTH :
-			      (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
-			       WLAN_FC_STYPE_ASSOC_RESP)));
-	os_memcpy(reply->da, mgmt->sa, ETH_ALEN);
-	os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
-	os_memcpy(reply->bssid, mgmt->bssid, ETH_ALEN);
-
-	send_len = IEEE80211_HDRLEN;
-	if (send_deauth) {
-		send_len += sizeof(reply->u.deauth);
-		reply->u.deauth.reason_code = host_to_le16(resp);
-	} else {
-		u8 *p;
-		send_len += sizeof(reply->u.assoc_resp);
-		reply->u.assoc_resp.capab_info =
-			host_to_le16(hostapd_own_capab_info(hapd, sta, 0));
-		reply->u.assoc_resp.status_code = host_to_le16(resp);
-		reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0)
-						       | BIT(14) | BIT(15));
-		/* Supported rates */
-		p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
-		/* Extended supported rates */
-		p = hostapd_eid_ext_supp_rates(hapd, p);
-		if (sta->flags & WLAN_STA_WMM)
-			p = hostapd_eid_wmm(hapd, p);
-
-		p = hostapd_eid_ht_capabilities_info(hapd, p);
-		p = hostapd_eid_ht_operation(hapd, p);
-
-#ifdef CONFIG_IEEE80211R
-		if (resp == WLAN_STATUS_SUCCESS) {
-			/* IEEE 802.11r: Mobility Domain Information, Fast BSS
-			 * Transition Information, RSN */
-			p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
-							buf + sizeof(buf) - p,
-							sta->auth_alg);
-		}
-#endif /* CONFIG_IEEE80211R */
-
-#ifdef CONFIG_IEEE80211W
-		if (resp == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
-			p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
-#endif /* CONFIG_IEEE80211W */
-
-		send_len += p - reply->u.assoc_resp.variable;
-	}
-
-	if (hostapd_send_mgmt_frame(hapd, reply, send_len, 0) < 0)
-		perror("handle_assoc: send");
+	send_assoc_resp(hapd, sta, resp, reassoc, pos, left);
 }
 
 
 static void handle_disassoc(struct hostapd_data *hapd,
-			    struct ieee80211_mgmt *mgmt, size_t len)
+			    const struct ieee80211_mgmt *mgmt, size_t len)
 {
 	struct sta_info *sta;
 
@@ -1176,6 +1062,8 @@ static void handle_disassoc(struct hostapd_data *hapd,
 	}
 
 	sta->flags &= ~WLAN_STA_ASSOC;
+	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
+		MAC2STR(sta->addr));
 	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_INFO, "disassociated");
@@ -1185,7 +1073,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
 	 * authenticated. */
 	accounting_sta_stop(hapd, sta);
 	ieee802_1x_free_station(sta);
-	hostapd_sta_remove(hapd, sta->addr);
+	hapd->drv.sta_remove(hapd, sta->addr);
 
 	if (sta->timeout_next == STA_NULLFUNC ||
 	    sta->timeout_next == STA_DISASSOC) {
@@ -1201,7 +1089,7 @@ static void handle_disassoc(struct hostapd_data *hapd,
 
 
 static void handle_deauth(struct hostapd_data *hapd,
-			  struct ieee80211_mgmt *mgmt, size_t len)
+			  const struct ieee80211_mgmt *mgmt, size_t len)
 {
 	struct sta_info *sta;
 
@@ -1224,6 +1112,8 @@ static void handle_deauth(struct hostapd_data *hapd,
 	}
 
 	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
+		MAC2STR(sta->addr));
 	wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_DEBUG, "deauthenticated");
@@ -1236,7 +1126,7 @@ static void handle_deauth(struct hostapd_data *hapd,
 
 
 static void handle_beacon(struct hostapd_data *hapd,
-			  struct ieee80211_mgmt *mgmt, size_t len,
+			  const struct ieee80211_mgmt *mgmt, size_t len,
 			  struct hostapd_frame_info *fi)
 {
 	struct ieee802_11_elems elems;
@@ -1281,16 +1171,57 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
 	os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
 		  WLAN_SA_QUERY_TR_ID_LEN);
 	end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
-	if (hostapd_send_mgmt_frame(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0)
+	if (hapd->drv.send_mgmt_frame(hapd, &mgmt, end - (u8 *) &mgmt) < 0)
 		perror("ieee802_11_send_sa_query_req: send");
 }
 
 
-static void hostapd_sa_query_action(struct hostapd_data *hapd,
-				    struct ieee80211_mgmt *mgmt, size_t len)
+static void hostapd_sa_query_request(struct hostapd_data *hapd,
+				     const struct ieee80211_mgmt *mgmt)
 {
 	struct sta_info *sta;
+	struct ieee80211_mgmt resp;
 	u8 *end;
+
+	wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
+		   MACSTR, MAC2STR(mgmt->sa));
+	wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
+		    mgmt->u.action.u.sa_query_resp.trans_id,
+		    WLAN_SA_QUERY_TR_ID_LEN);
+
+	sta = ap_get_sta(hapd, mgmt->sa);
+	if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
+		wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request "
+			   "from unassociated STA " MACSTR, MAC2STR(mgmt->sa));
+		return;
+	}
+
+	wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
+		   MACSTR, MAC2STR(mgmt->sa));
+
+	os_memset(&resp, 0, sizeof(resp));
+	resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+					  WLAN_FC_STYPE_ACTION);
+	os_memcpy(resp.da, mgmt->sa, ETH_ALEN);
+	os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN);
+	resp.u.action.category = WLAN_ACTION_SA_QUERY;
+	resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
+	os_memcpy(resp.u.action.u.sa_query_req.trans_id,
+		  mgmt->u.action.u.sa_query_req.trans_id,
+		  WLAN_SA_QUERY_TR_ID_LEN);
+	end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
+	if (hapd->drv.send_mgmt_frame(hapd, &resp, end - (u8 *) &resp) < 0)
+		perror("hostapd_sa_query_request: send");
+}
+
+
+static void hostapd_sa_query_action(struct hostapd_data *hapd,
+				    const struct ieee80211_mgmt *mgmt,
+				    size_t len)
+{
+	struct sta_info *sta;
+	const u8 *end;
 	int i;
 
 	end = mgmt->u.action.u.sa_query_resp.trans_id +
@@ -1301,6 +1232,11 @@ static void hostapd_sa_query_action(struct hostapd_data *hapd,
 		return;
 	}
 
+	if (mgmt->u.action.u.sa_query_resp.action == WLAN_SA_QUERY_REQUEST) {
+		hostapd_sa_query_request(hapd, mgmt);
+		return;
+	}
+
 	if (mgmt->u.action.u.sa_query_resp.action != WLAN_SA_QUERY_RESPONSE) {
 		wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
 			   "Action %d", mgmt->u.action.u.sa_query_resp.action);
@@ -1352,7 +1288,7 @@ static int robust_action_frame(u8 category)
 
 
 static void handle_action(struct hostapd_data *hapd,
-			  struct ieee80211_mgmt *mgmt, size_t len)
+			  const struct ieee80211_mgmt *mgmt, size_t len)
 {
 	struct sta_info *sta;
 
@@ -1403,6 +1339,14 @@ static void handle_action(struct hostapd_data *hapd,
 		hostapd_sa_query_action(hapd, mgmt, len);
 		return;
 #endif /* CONFIG_IEEE80211W */
+	case WLAN_ACTION_PUBLIC:
+		if (hapd->public_action_cb) {
+			hapd->public_action_cb(hapd->public_action_cb_ctx,
+					       (u8 *) mgmt, len,
+					       hapd->iface->freq);
+			return;
+		}
+		break;
 	}
 
 	hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
@@ -1412,6 +1356,8 @@ static void handle_action(struct hostapd_data *hapd,
 		       mgmt->u.action.category);
 	if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) &&
 	    !(mgmt->sa[0] & 0x01)) {
+		struct ieee80211_mgmt *resp;
+
 		/*
 		 * IEEE 802.11-REVma/D9.0 - 7.3.1.11
 		 * Return the Action frame to the source without change
@@ -1419,12 +1365,17 @@ static void handle_action(struct hostapd_data *hapd,
 		 */
 		wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
 			   "frame back to sender");
-		os_memcpy(mgmt->da, mgmt->sa, ETH_ALEN);
-		os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
-		os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
-		mgmt->u.action.category |= 0x80;
+		resp = os_malloc(len);
+		if (resp == NULL)
+			return;
+		os_memcpy(resp, mgmt, len);
+		os_memcpy(resp->da, resp->sa, ETH_ALEN);
+		os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
+		os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
+		resp->u.action.category |= 0x80;
 
-		hostapd_send_mgmt_frame(hapd, mgmt, len, 0);
+		hapd->drv.send_mgmt_frame(hapd, resp, len);
+		os_free(resp);
 	}
 }
 
@@ -1435,7 +1386,6 @@ static void handle_action(struct hostapd_data *hapd,
  * sent to)
  * @buf: management frame data (starting from IEEE 802.11 header)
  * @len: length of frame data in octets
- * @stype: management frame subtype from frame control field
  * @fi: meta data about received frame (signal level, etc.)
  *
  * Process all incoming IEEE 802.11 management frames. This will be called for
@@ -1443,20 +1393,22 @@ static void handle_action(struct hostapd_data *hapd,
  * addition, it can be called to re-inserted pending frames (e.g., when using
  * external RADIUS server as an MAC ACL).
  */
-void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype,
+void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
 		     struct hostapd_frame_info *fi)
 {
-	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
+	struct ieee80211_mgmt *mgmt;
 	int broadcast;
+	u16 fc, stype;
+
+	mgmt = (struct ieee80211_mgmt *) buf;
+	fc = le_to_host16(mgmt->frame_control);
+	stype = WLAN_FC_GET_STYPE(fc);
 
 	if (stype == WLAN_FC_STYPE_BEACON) {
 		handle_beacon(hapd, mgmt, len, fi);
 		return;
 	}
 
-	if (fi && fi->passive_scan)
-		return;
-
 	broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff &&
 		mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff &&
 		mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff;
@@ -1517,7 +1469,7 @@ void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype,
 
 
 static void handle_auth_cb(struct hostapd_data *hapd,
-			   struct ieee80211_mgmt *mgmt,
+			   const struct ieee80211_mgmt *mgmt,
 			   size_t len, int ok)
 {
 	u16 auth_alg, auth_transaction, status_code;
@@ -1557,38 +1509,14 @@ static void handle_auth_cb(struct hostapd_data *hapd,
 }
 
 
-#ifdef CONFIG_IEEE80211N
-static void
-hostapd_get_ht_capab(struct hostapd_data *hapd,
-		     struct ht_cap_ie *ht_cap_ie,
-		     struct ht_cap_ie *neg_ht_cap_ie)
-{
-	u16 cap;
-
-	os_memcpy(neg_ht_cap_ie, ht_cap_ie, sizeof(struct ht_cap_ie));
-	cap = le_to_host16(neg_ht_cap_ie->data.capabilities_info);
-	cap &= hapd->iconf->ht_capab;
-	cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED);
-
-	/* FIXME: Rx STBC needs to be handled specially */
-	cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK);
-	neg_ht_cap_ie->data.capabilities_info = host_to_le16(cap);
-}
-#endif /* CONFIG_IEEE80211N */
-
-
 static void handle_assoc_cb(struct hostapd_data *hapd,
-			    struct ieee80211_mgmt *mgmt,
+			    const struct ieee80211_mgmt *mgmt,
 			    size_t len, int reassoc, int ok)
 {
 	u16 status;
 	struct sta_info *sta;
 	int new_assoc = 1;
-#ifdef CONFIG_IEEE80211N
-	struct ht_cap_ie ht_cap;
-#endif /* CONFIG_IEEE80211N */
-	struct ht_cap_ie *ht_cap_ptr = NULL;
-	int set_flags, flags_and, flags_or;
+	struct ieee80211_ht_capabilities ht_cap;
 
 	if (!ok) {
 		hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
@@ -1631,19 +1559,22 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
 	if (sta->flags & WLAN_STA_ASSOC)
 		new_assoc = 0;
 	sta->flags |= WLAN_STA_ASSOC;
+	if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
+	    sta->auth_alg == WLAN_AUTH_FT) {
+		/*
+		 * Open, static WEP, or FT protocol; no separate authorization
+		 * step.
+		 */
+		sta->flags |= WLAN_STA_AUTHORIZED;
+		wpa_msg(hapd->msg_ctx, MSG_INFO,
+			AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
+	}
 
 	if (reassoc)
 		mlme_reassociate_indication(hapd, sta);
 	else
 		mlme_associate_indication(hapd, sta);
 
-#ifdef CONFIG_IEEE80211N
-	if (sta->flags & WLAN_STA_HT) {
-		ht_cap_ptr = &ht_cap;
-		hostapd_get_ht_capab(hapd, &sta->ht_capabilities, ht_cap_ptr);
-	}
-#endif /* CONFIG_IEEE80211N */
-
 #ifdef CONFIG_IEEE80211W
 	sta->sa_query_timed_out = 0;
 #endif /* CONFIG_IEEE80211W */
@@ -1653,13 +1584,17 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
 	 * cleared and configuration gets updated in case of reassociation back
 	 * to the same AP.
 	 */
-	hostapd_sta_remove(hapd, sta->addr);
+	hapd->drv.sta_remove(hapd, sta->addr);
 
-	if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid,
-			    sta->capability, sta->supported_rates,
-			    sta->supported_rates_len, 0, sta->listen_interval,
-			    ht_cap_ptr))
-	{
+#ifdef CONFIG_IEEE80211N
+	if (sta->flags & WLAN_STA_HT)
+		hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
+#endif /* CONFIG_IEEE80211N */
+
+	if (hapd->drv.sta_add(hapd, sta->addr, sta->aid, sta->capability,
+			      sta->supported_rates, sta->supported_rates_len,
+			      sta->listen_interval,
+			      sta->flags & WLAN_STA_HT ? &ht_cap : NULL)) {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 			       HOSTAPD_LEVEL_NOTICE,
 			       "Could not add STA to kernel driver");
@@ -1671,26 +1606,21 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
 		 * so bind it to the selected VLAN interface now, since the
 		 * interface selection is not going to change anymore.
 		 */
-		ap_sta_bind_vlan(hapd, sta, 0);
+		if (ap_sta_bind_vlan(hapd, sta, 0) < 0)
+			goto fail;
 	} else if (sta->vlan_id) {
 		/* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
-		ap_sta_bind_vlan(hapd, sta, 0);
+		if (ap_sta_bind_vlan(hapd, sta, 0) < 0)
+			goto fail;
 	}
 
-	set_flags = WLAN_STA_SHORT_PREAMBLE | WLAN_STA_WMM | WLAN_STA_MFP;
-	if (!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
-	    sta->flags & WLAN_STA_AUTHORIZED)
-		set_flags |= WLAN_STA_AUTHORIZED;
-	flags_or = sta->flags & set_flags;
-	flags_and = sta->flags | ~set_flags;
-	hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
-			      flags_or, flags_and);
+	hapd->drv.set_sta_flags(hapd, sta);
 
 	if (sta->auth_alg == WLAN_AUTH_FT)
 		wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
 	else
 		wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
-	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
+	hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
 
 	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
 
@@ -1712,10 +1642,11 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
  * @stype: management frame subtype from frame control field
  * @ok: Whether the frame was ACK'ed
  */
-void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
+void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
 			u16 stype, int ok)
 {
-	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf;
+	const struct ieee80211_mgmt *mgmt;
+	mgmt = (const struct ieee80211_mgmt *) buf;
 
 	switch (stype) {
 	case WLAN_FC_STYPE_AUTH:
@@ -1746,76 +1677,6 @@ void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
 }
 
 
-static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
-						void *timeout_ctx)
-{
-	struct hostapd_data *hapd = eloop_ctx;
-	hapd->tkip_countermeasures = 0;
-	hostapd_set_countermeasures(hapd, 0);
-	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
-		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
-}
-
-
-static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
-{
-	struct sta_info *sta;
-
-	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
-		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
-
-	wpa_auth_countermeasures_start(hapd->wpa_auth);
-	hapd->tkip_countermeasures = 1;
-	hostapd_set_countermeasures(hapd, 1);
-	wpa_gtk_rekey(hapd->wpa_auth);
-	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
-	eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
-			       hapd, NULL);
-	for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
-		hostapd_sta_deauth(hapd, sta->addr,
-				   WLAN_REASON_MICHAEL_MIC_FAILURE);
-		sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
-				WLAN_STA_AUTHORIZED);
-		hostapd_sta_remove(hapd, sta->addr);
-	}
-}
-
-
-void ieee80211_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr,
-				   int local)
-{
-	time_t now;
-
-	if (addr && local) {
-		struct sta_info *sta = ap_get_sta(hapd, addr);
-		if (sta != NULL) {
-			wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
-			hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
-				       HOSTAPD_LEVEL_INFO,
-				       "Michael MIC failure detected in "
-				       "received frame");
-			mlme_michaelmicfailure_indication(hapd, addr);
-		} else {
-			wpa_printf(MSG_DEBUG,
-				   "MLME-MICHAELMICFAILURE.indication "
-				   "for not associated STA (" MACSTR
-				   ") ignored", MAC2STR(addr));
-			return;
-		}
-	}
-
-	time(&now);
-	if (now > hapd->michael_mic_failure + 60) {
-		hapd->michael_mic_failures = 1;
-	} else {
-		hapd->michael_mic_failures++;
-		if (hapd->michael_mic_failures > 1)
-			ieee80211_tkip_countermeasures_start(hapd);
-	}
-	hapd->michael_mic_failure = now;
-}
-
-
 int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
 {
 	/* TODO */
@@ -1830,4 +1691,65 @@ int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
 	return 0;
 }
 
+
+void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
+		       const u8 *buf, size_t len, int ack)
+{
+	struct sta_info *sta;
+	struct hostapd_iface *iface = hapd->iface;
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta == NULL && iface->num_bss > 1) {
+		size_t j;
+		for (j = 0; j < iface->num_bss; j++) {
+			hapd = iface->bss[j];
+			sta = ap_get_sta(hapd, addr);
+			if (sta)
+				break;
+		}
+	}
+	if (sta == NULL)
+		return;
+	if (sta->flags & WLAN_STA_PENDING_POLL) {
+		wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
+			   "activity poll", MAC2STR(sta->addr),
+			   ack ? "ACKed" : "did not ACK");
+		if (ack)
+			sta->flags &= ~WLAN_STA_PENDING_POLL;
+	}
+
+	ieee802_1x_tx_status(hapd, sta, buf, len, ack);
+}
+
+
+void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
+				int wds)
+{
+	struct sta_info *sta;
+
+	sta = ap_get_sta(hapd, src);
+	if (sta && (sta->flags & WLAN_STA_ASSOC)) {
+		if (wds && !(sta->flags & WLAN_STA_WDS)) {
+			wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
+				   "STA " MACSTR " (aid %u)",
+				   MAC2STR(sta->addr), sta->aid);
+			sta->flags |= WLAN_STA_WDS;
+			hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 1);
+		}
+		return;
+	}
+
+	wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
+		   MACSTR, MAC2STR(src));
+	if (sta && (sta->flags & WLAN_STA_AUTH))
+		hapd->drv.sta_disassoc(
+			hapd, src,
+			WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+	else
+		hapd->drv.sta_deauth(
+			hapd, src,
+			WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+}
+
+
 #endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/contrib/wpa/hostapd/ieee802_11.h b/contrib/wpa/src/ap/ieee802_11.h
similarity index 50%
rename from contrib/wpa/hostapd/ieee802_11.h
rename to contrib/wpa/src/ap/ieee802_11.h
index ca8ef93c090e..cfc069c8094f 100644
--- a/contrib/wpa/hostapd/ieee802_11.h
+++ b/contrib/wpa/src/ap/ieee802_11.h
@@ -1,7 +1,6 @@
 /*
  * hostapd / IEEE 802.11 Management
- * Copyright (c) 2002-2006, Jouni Malinen 
- * Copyright (c) 2007-2008, Intel Corporation
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -16,41 +15,53 @@
 #ifndef IEEE802_11_H
 #define IEEE802_11_H
 
-#include "ieee802_11_defs.h"
-#include "ieee802_11_common.h"
-
-struct hostapd_frame_info {
-	u32 phytype;
-	u32 channel;
-	u32 datarate;
-	u32 ssi_signal;
-
-	unsigned int passive_scan:1;
-};
-
 struct hostapd_iface;
 struct hostapd_data;
 struct sta_info;
+struct hostapd_frame_info;
+struct ieee80211_ht_capabilities;
 
-void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason);
-void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len,
-		     u16 stype, struct hostapd_frame_info *fi);
-void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len,
+void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
+		     struct hostapd_frame_info *fi);
+void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
 			u16 stype, int ok);
 void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len);
-void ieee80211_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr,
-				   int local);
+#ifdef NEED_AP_MLME
 int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen);
 int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
 			   char *buf, size_t buflen);
+#else /* NEED_AP_MLME */
+static inline int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf,
+				     size_t buflen)
+{
+	return 0;
+}
+
+static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd,
+					 struct sta_info *sta,
+					 char *buf, size_t buflen)
+{
+	return 0;
+}
+#endif /* NEED_AP_MLME */
 u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
 			   int probe);
 u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
-u8 * hostapd_eid_ht_capabilities_info(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
 int hostapd_ht_operation_update(struct hostapd_iface *iface);
 void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
 				  const u8 *addr, const u8 *trans_id);
+void hostapd_get_ht_capab(struct hostapd_data *hapd,
+			  struct ieee80211_ht_capabilities *ht_cap,
+			  struct ieee80211_ht_capabilities *neg_ht_cap);
+u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
+		      size_t ht_capab_len);
+void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
+void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
+		       const u8 *buf, size_t len, int ack);
+void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
+				int wds);
 
 #endif /* IEEE802_11_H */
diff --git a/contrib/wpa/hostapd/ieee802_11_auth.c b/contrib/wpa/src/ap/ieee802_11_auth.c
similarity index 92%
rename from contrib/wpa/hostapd/ieee802_11_auth.c
rename to contrib/wpa/src/ap/ieee802_11_auth.c
index 9aba1fe854bd..dec56d1e1a1e 100644
--- a/contrib/wpa/hostapd/ieee802_11_auth.c
+++ b/contrib/wpa/src/ap/ieee802_11_auth.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / IEEE 802.11 authentication (ACL)
- * Copyright (c) 2003-2007, Jouni Malinen 
+ * Copyright (c) 2003-2009, Jouni Malinen 
  *
  * 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
@@ -17,17 +17,16 @@
  * authentication frame processing.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#ifndef CONFIG_NATIVE_WINDOWS
-
-#include "hostapd.h"
-#include "ieee802_11.h"
-#include "ieee802_11_auth.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
 #include "radius/radius.h"
 #include "radius/radius_client.h"
-#include "eloop.h"
-#include "driver.h"
+#include "hostapd.h"
+#include "ap_config.h"
+#include "ieee802_11.h"
+#include "ieee802_11_auth.h"
 
 #define RADIUS_ACL_TIMEOUT 30
 
@@ -53,6 +52,7 @@ struct hostapd_acl_query_data {
 };
 
 
+#ifndef CONFIG_NO_RADIUS
 static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache)
 {
 	struct hostapd_cached_radius_acl *prev;
@@ -96,6 +96,7 @@ static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
 
 	return -1;
 }
+#endif /* CONFIG_NO_RADIUS */
 
 
 static void hostapd_acl_query_free(struct hostapd_acl_query_data *query)
@@ -107,6 +108,7 @@ static void hostapd_acl_query_free(struct hostapd_acl_query_data *query)
 }
 
 
+#ifndef CONFIG_NO_RADIUS
 static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
 				    struct hostapd_acl_query_data *query)
 {
@@ -193,9 +195,9 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
 
  fail:
 	radius_msg_free(msg);
-	os_free(msg);
 	return -1;
 }
+#endif /* CONFIG_NO_RADIUS */
 
 
 /**
@@ -234,6 +236,9 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 		return HOSTAPD_ACL_REJECT;
 
 	if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) {
+#ifdef CONFIG_NO_RADIUS
+		return HOSTAPD_ACL_REJECT;
+#else /* CONFIG_NO_RADIUS */
 		struct hostapd_acl_query_data *query;
 
 		/* Check whether ACL cache has an entry for this station */
@@ -289,12 +294,14 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 		/* Queued data will be processed in hostapd_acl_recv_radius()
 		 * when RADIUS server replies to the sent Access-Request. */
 		return HOSTAPD_ACL_PENDING;
+#endif /* CONFIG_NO_RADIUS */
 	}
 
 	return HOSTAPD_ACL_REJECT;
 }
 
 
+#ifndef CONFIG_NO_RADIUS
 static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
 {
 	struct hostapd_cached_radius_acl *prev, *entry, *tmp;
@@ -311,7 +318,7 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now)
 			else
 				hapd->acl_cache = entry->next;
 #ifdef CONFIG_DRIVER_RADIUS_ACL
-			hostapd_set_radius_acl_expire(hapd, entry->addr);
+			hapd->drv.set_radius_acl_expire(hapd, entry->addr);
 #endif /* CONFIG_DRIVER_RADIUS_ACL */
 			tmp = entry;
 			entry = entry->next;
@@ -389,11 +396,12 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
 	struct hostapd_data *hapd = data;
 	struct hostapd_acl_query_data *query, *prev;
 	struct hostapd_cached_radius_acl *cache;
+	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
 
 	query = hapd->acl_queries;
 	prev = NULL;
 	while (query) {
-		if (query->radius_id == msg->hdr->identifier)
+		if (query->radius_id == hdr->identifier)
 			break;
 		prev = query;
 		query = query->next;
@@ -410,10 +418,10 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
 		return RADIUS_RX_INVALID_AUTHENTICATOR;
 	}
 
-	if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
-	    msg->hdr->code != RADIUS_CODE_ACCESS_REJECT) {
+	if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
+	    hdr->code != RADIUS_CODE_ACCESS_REJECT) {
 		wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL "
-			   "query", msg->hdr->code);
+			   "query", hdr->code);
 		return RADIUS_RX_UNKNOWN;
 	}
 
@@ -425,7 +433,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
 	}
 	time(&cache->timestamp);
 	os_memcpy(cache->addr, query->addr, sizeof(cache->addr));
-	if (msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
+	if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) {
 		if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT,
 					      &cache->session_timeout) == 0)
 			cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT;
@@ -450,14 +458,15 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
 	hapd->acl_cache = cache;
 
 #ifdef CONFIG_DRIVER_RADIUS_ACL
-	hostapd_set_radius_acl_auth(hapd, query->addr, cache->accepted,
-				    cache->session_timeout);
+	hapd->drv.set_radius_acl_auth(hapd, query->addr, cache->accepted,
+				      cache->session_timeout);
 #else /* CONFIG_DRIVER_RADIUS_ACL */
+#ifdef NEED_AP_MLME
 	/* Re-send original authentication frame for 802.11 processing */
 	wpa_printf(MSG_DEBUG, "Re-sending authentication frame after "
 		   "successful RADIUS ACL query");
-	ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len,
-			WLAN_FC_STYPE_AUTH, NULL);
+	ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL);
+#endif /* NEED_AP_MLME */
 #endif /* CONFIG_DRIVER_RADIUS_ACL */
 
  done:
@@ -470,6 +479,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
 
 	return RADIUS_RX_PROCESSED;
 }
+#endif /* CONFIG_NO_RADIUS */
 
 
 /**
@@ -479,11 +489,13 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
  */
 int hostapd_acl_init(struct hostapd_data *hapd)
 {
+#ifndef CONFIG_NO_RADIUS
 	if (radius_client_register(hapd->radius, RADIUS_AUTH,
 				   hostapd_acl_recv_radius, hapd))
 		return -1;
 
 	eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
+#endif /* CONFIG_NO_RADIUS */
 
 	return 0;
 }
@@ -497,9 +509,11 @@ void hostapd_acl_deinit(struct hostapd_data *hapd)
 {
 	struct hostapd_acl_query_data *query, *prev;
 
+#ifndef CONFIG_NO_RADIUS
 	eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL);
 
 	hostapd_acl_cache_free(hapd->acl_cache);
+#endif /* CONFIG_NO_RADIUS */
 
 	query = hapd->acl_queries;
 	while (query) {
@@ -508,16 +522,3 @@ void hostapd_acl_deinit(struct hostapd_data *hapd)
 		hostapd_acl_query_free(prev);
 	}
 }
-
-
-int hostapd_acl_reconfig(struct hostapd_data *hapd,
-			 struct hostapd_config *oldconf)
-{
-	if (!hapd->radius_client_reconfigured)
-		return 0;
-
-	hostapd_acl_deinit(hapd);
-	return hostapd_acl_init(hapd);
-}
-
-#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/contrib/wpa/hostapd/ieee802_11_auth.h b/contrib/wpa/src/ap/ieee802_11_auth.h
similarity index 91%
rename from contrib/wpa/hostapd/ieee802_11_auth.h
rename to contrib/wpa/src/ap/ieee802_11_auth.h
index 0eed825e29a4..b2971e5092b5 100644
--- a/contrib/wpa/hostapd/ieee802_11_auth.h
+++ b/contrib/wpa/src/ap/ieee802_11_auth.h
@@ -27,7 +27,5 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 			    u32 *acct_interim_interval, int *vlan_id);
 int hostapd_acl_init(struct hostapd_data *hapd);
 void hostapd_acl_deinit(struct hostapd_data *hapd);
-int hostapd_acl_reconfig(struct hostapd_data *hapd,
-			 struct hostapd_config *oldconf);
 
 #endif /* IEEE802_11_AUTH_H */
diff --git a/contrib/wpa/src/ap/ieee802_11_ht.c b/contrib/wpa/src/ap/ieee802_11_ht.c
new file mode 100644
index 000000000000..7541b83816d0
--- /dev/null
+++ b/contrib/wpa/src/ap/ieee802_11_ht.c
@@ -0,0 +1,270 @@
+/*
+ * hostapd / IEEE 802.11n HT
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ * Copyright (c) 2007-2008, Intel Corporation
+ *
+ * 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 "common/ieee802_11_defs.h"
+#include "drivers/driver.h"
+#include "hostapd.h"
+#include "ap_config.h"
+#include "sta_info.h"
+#include "beacon.h"
+#include "ieee802_11.h"
+
+
+u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
+{
+	struct ieee80211_ht_capabilities *cap;
+	u8 *pos = eid;
+
+	if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode)
+		return eid;
+
+	*pos++ = WLAN_EID_HT_CAP;
+	*pos++ = sizeof(*cap);
+
+	cap = (struct ieee80211_ht_capabilities *) pos;
+	os_memset(cap, 0, sizeof(*cap));
+	cap->ht_capabilities_info = host_to_le16(hapd->iconf->ht_capab);
+	cap->a_mpdu_params = hapd->iface->current_mode->a_mpdu_params;
+	os_memcpy(cap->supported_mcs_set, hapd->iface->current_mode->mcs_set,
+		  16);
+
+	/* TODO: ht_extended_capabilities (now fully disabled) */
+	/* TODO: tx_bf_capability_info (now fully disabled) */
+	/* TODO: asel_capabilities (now fully disabled) */
+
+ 	pos += sizeof(*cap);
+
+	return pos;
+}
+
+
+u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
+{
+	struct ieee80211_ht_operation *oper;
+	u8 *pos = eid;
+
+	if (!hapd->iconf->ieee80211n)
+		return eid;
+
+	*pos++ = WLAN_EID_HT_OPERATION;
+	*pos++ = sizeof(*oper);
+
+	oper = (struct ieee80211_ht_operation *) pos;
+	os_memset(oper, 0, sizeof(*oper));
+
+	oper->control_chan = hapd->iconf->channel;
+	oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
+	if (hapd->iconf->secondary_channel == 1)
+		oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
+			HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
+	if (hapd->iconf->secondary_channel == -1)
+		oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
+			HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
+
+	pos += sizeof(*oper);
+
+	return pos;
+}
+
+
+/*
+op_mode
+Set to 0 (HT pure) under the followign conditions
+	- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
+	- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
+Set to 1 (HT non-member protection) if there may be non-HT STAs
+	in both the primary and the secondary channel
+Set to 2 if only HT STAs are associated in BSS,
+	however and at least one 20 MHz HT STA is associated
+Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
+	(currently non-GF HT station is considered as non-HT STA also)
+*/
+int hostapd_ht_operation_update(struct hostapd_iface *iface)
+{
+	u16 cur_op_mode, new_op_mode;
+	int op_mode_changes = 0;
+
+	if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X",
+		   __func__, iface->ht_op_mode);
+
+	if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
+	    && iface->num_sta_ht_no_gf) {
+		iface->ht_op_mode |=
+			HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
+		op_mode_changes++;
+	} else if ((iface->ht_op_mode &
+		    HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
+		   iface->num_sta_ht_no_gf == 0) {
+		iface->ht_op_mode &=
+			~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
+		op_mode_changes++;
+	}
+
+	if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
+	    (iface->num_sta_no_ht || iface->olbc_ht)) {
+		iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
+		op_mode_changes++;
+	} else if ((iface->ht_op_mode &
+		    HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
+		   (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) {
+		iface->ht_op_mode &=
+			~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
+		op_mode_changes++;
+	}
+
+	/* Note: currently we switch to the MIXED op mode if HT non-greenfield
+	 * station is associated. Probably it's a theoretical case, since
+	 * it looks like all known HT STAs support greenfield.
+	 */
+	new_op_mode = 0;
+	if (iface->num_sta_no_ht ||
+	    (iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
+		new_op_mode = OP_MODE_MIXED;
+	else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
+		 && iface->num_sta_ht_20mhz)
+		new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
+	else if (iface->olbc_ht)
+		new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
+	else
+		new_op_mode = OP_MODE_PURE;
+
+	cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
+	if (cur_op_mode != new_op_mode) {
+		iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
+		iface->ht_op_mode |= new_op_mode;
+		op_mode_changes++;
+	}
+
+	wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d",
+		   __func__, iface->ht_op_mode, op_mode_changes);
+
+	return op_mode_changes;
+}
+
+
+u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab,
+		      size_t ht_capab_len)
+{
+	if (!ht_capab ||
+	    ht_capab_len < sizeof(struct ieee80211_ht_capabilities)) {
+		sta->flags &= ~WLAN_STA_HT;
+		os_free(sta->ht_capabilities);
+		sta->ht_capabilities = NULL;
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	if (sta->ht_capabilities == NULL) {
+		sta->ht_capabilities =
+			os_zalloc(sizeof(struct ieee80211_ht_capabilities));
+		if (sta->ht_capabilities == NULL)
+			return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	}
+
+	sta->flags |= WLAN_STA_HT;
+	os_memcpy(sta->ht_capabilities, ht_capab,
+		  sizeof(struct ieee80211_ht_capabilities));
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+
+static void update_sta_ht(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	u16 ht_capab;
+
+	ht_capab = le_to_host16(sta->ht_capabilities->ht_capabilities_info);
+	wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities Info: "
+		   "0x%04x", MAC2STR(sta->addr), ht_capab);
+	if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) {
+		if (!sta->no_ht_gf_set) {
+			sta->no_ht_gf_set = 1;
+			hapd->iface->num_sta_ht_no_gf++;
+		}
+		wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no greenfield, num "
+			   "of non-gf stations %d",
+			   __func__, MAC2STR(sta->addr),
+			   hapd->iface->num_sta_ht_no_gf);
+	}
+	if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) {
+		if (!sta->ht_20mhz_set) {
+			sta->ht_20mhz_set = 1;
+			hapd->iface->num_sta_ht_20mhz++;
+		}
+		wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, num of "
+			   "20MHz HT STAs %d",
+			   __func__, MAC2STR(sta->addr),
+			   hapd->iface->num_sta_ht_20mhz);
+	}
+}
+
+
+static void update_sta_no_ht(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	if (!sta->no_ht_set) {
+		sta->no_ht_set = 1;
+		hapd->iface->num_sta_no_ht++;
+	}
+	if (hapd->iconf->ieee80211n) {
+		wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no HT, num of "
+			   "non-HT stations %d",
+			   __func__, MAC2STR(sta->addr),
+			   hapd->iface->num_sta_no_ht);
+	}
+}
+
+
+void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities)
+		update_sta_ht(hapd, sta);
+	else
+		update_sta_no_ht(hapd, sta);
+
+	if (hostapd_ht_operation_update(hapd->iface) > 0)
+		ieee802_11_set_beacons(hapd->iface);
+}
+
+
+void hostapd_get_ht_capab(struct hostapd_data *hapd,
+			  struct ieee80211_ht_capabilities *ht_cap,
+			  struct ieee80211_ht_capabilities *neg_ht_cap)
+{
+	u16 cap;
+
+	if (ht_cap == NULL)
+		return;
+	os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap));
+	cap = le_to_host16(neg_ht_cap->ht_capabilities_info);
+	cap &= hapd->iconf->ht_capab;
+	cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED);
+
+	/*
+	 * STBC needs to be handled specially
+	 * if we don't support RX STBC, mask out TX STBC in the STA's HT caps
+	 * if we don't support TX STBC, mask out RX STBC in the STA's HT caps
+	 */
+	if (!(hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK))
+		cap &= ~HT_CAP_INFO_TX_STBC;
+	if (!(hapd->iconf->ht_capab & HT_CAP_INFO_TX_STBC))
+		cap &= ~HT_CAP_INFO_RX_STBC_MASK;
+
+	neg_ht_cap->ht_capabilities_info = host_to_le16(cap);
+}
diff --git a/contrib/wpa/hostapd/ieee802_1x.c b/contrib/wpa/src/ap/ieee802_1x.c
similarity index 88%
rename from contrib/wpa/hostapd/ieee802_1x.c
rename to contrib/wpa/src/ap/ieee802_1x.c
index 7fd80280577c..eb160f8e015c 100644
--- a/contrib/wpa/hostapd/ieee802_1x.c
+++ b/contrib/wpa/src/ap/ieee802_1x.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / IEEE 802.1X-2004 Authenticator
- * Copyright (c) 2002-2008, Jouni Malinen 
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -12,25 +12,28 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#include "hostapd.h"
-#include "ieee802_1x.h"
-#include "accounting.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "crypto/md5.h"
+#include "crypto/crypto.h"
+#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
 #include "radius/radius.h"
 #include "radius/radius_client.h"
-#include "eapol_sm.h"
-#include "md5.h"
-#include "rc4.h"
-#include "eloop.h"
-#include "sta_info.h"
-#include "wpa.h"
-#include "preauth.h"
-#include "pmksa_cache.h"
-#include "driver.h"
-#include "hw_features.h"
 #include "eap_server/eap.h"
-#include "ieee802_11_defs.h"
+#include "eap_common/eap_wsc_common.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "eapol_auth/eapol_auth_sm_i.h"
+#include "hostapd.h"
+#include "accounting.h"
+#include "sta_info.h"
+#include "wpa_auth.h"
+#include "preauth_auth.h"
+#include "pmksa_cache_auth.h"
+#include "ap_config.h"
+#include "ieee802_1x.h"
 
 
 static void ieee802_1x_finished(struct hostapd_data *hapd,
@@ -67,7 +70,7 @@ static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta,
 	if (sta->flags & WLAN_STA_PREAUTH) {
 		rsn_preauth_send(hapd, sta, buf, len);
 	} else {
-		hostapd_send_eapol(hapd, sta->addr, buf, len, encrypt);
+		hapd->drv.send_eapol(hapd, sta->addr, buf, len, encrypt);
 	}
 
 	os_free(buf);
@@ -83,15 +86,21 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
 		return;
 
 	if (authorized) {
+		if (!(sta->flags & WLAN_STA_AUTHORIZED))
+			wpa_msg(hapd->msg_ctx, MSG_INFO,
+				AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
 		sta->flags |= WLAN_STA_AUTHORIZED;
-		res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
-					    WLAN_STA_AUTHORIZED, ~0);
+		res = hapd->drv.set_authorized(hapd, sta, 1);
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_DEBUG, "authorizing port");
 	} else {
+		if ((sta->flags & (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC)) ==
+		    (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC))
+			wpa_msg(hapd->msg_ctx, MSG_INFO,
+				AP_STA_DISCONNECTED MACSTR,
+				MAC2STR(sta->addr));
 		sta->flags &= ~WLAN_STA_AUTHORIZED;
-		res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
-					    0, ~WLAN_STA_AUTHORIZED);
+		res = hapd->drv.set_authorized(hapd, sta, 0);
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_DEBUG, "unauthorizing port");
 	}
@@ -185,6 +194,7 @@ static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
 }
 
 
+#ifndef CONFIG_NO_VLAN
 static struct hostapd_wep_keys *
 ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
 {
@@ -219,11 +229,11 @@ ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname)
 	wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)",
 			key->key[key->idx], key->len[key->idx]);
 
-	if (hostapd_set_encryption(ifname, hapd, "WEP", NULL, key->idx,
-				   key->key[key->idx], key->len[key->idx], 1))
+	if (hapd->drv.set_key(ifname, hapd, WPA_ALG_WEP, NULL, key->idx, 1,
+			      NULL, 0, key->key[key->idx], key->len[key->idx]))
 		printf("Could not set dynamic VLAN WEP encryption key.\n");
 
-	hostapd_set_ieee8021x(ifname, hapd, 1);
+	hapd->drv.set_drv_ieee8021x(hapd, ifname, 1);
 
 	return key;
 }
@@ -279,13 +289,17 @@ ieee802_1x_get_group(struct hostapd_data *hapd, struct hostapd_ssid *ssid,
 
 	return ssid->dyn_vlan_keys[vlan_id];
 }
+#endif /* CONFIG_NO_VLAN */
 
 
 void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
 {
-	struct hostapd_wep_keys *key = NULL;
+	struct eapol_authenticator *eapol = hapd->eapol_auth;
 	struct eapol_state_machine *sm = sta->eapol_sm;
+#ifndef CONFIG_NO_VLAN
+	struct hostapd_wep_keys *key = NULL;
 	int vlan_id;
+#endif /* CONFIG_NO_VLAN */
 
 	if (sm == NULL || !sm->eap_if->eapKeyData)
 		return;
@@ -293,6 +307,7 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
 	wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR,
 		   MAC2STR(sta->addr));
 
+#ifndef CONFIG_NO_VLAN
 	vlan_id = sta->vlan_id;
 	if (vlan_id < 0 || vlan_id > MAX_VLAN_ID)
 		vlan_id = 0;
@@ -303,9 +318,11 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
 			ieee802_1x_tx_key_one(hapd, sta, key->idx, 1,
 					      key->key[key->idx],
 					      key->len[key->idx]);
-	} else if (hapd->default_wep_key) {
-		ieee802_1x_tx_key_one(hapd, sta, hapd->default_wep_key_idx, 1,
-				      hapd->default_wep_key,
+	} else
+#endif /* CONFIG_NO_VLAN */
+	if (eapol->default_wep_key) {
+		ieee802_1x_tx_key_one(hapd, sta, eapol->default_wep_key_idx, 1,
+				      eapol->default_wep_key,
 				      hapd->conf->default_wep_key_len);
 	}
 
@@ -328,10 +345,9 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
 
 		/* TODO: set encryption in TX callback, i.e., only after STA
 		 * has ACKed EAPOL-Key frame */
-		if (hostapd_set_encryption(hapd->conf->iface, hapd, "WEP",
-					   sta->addr, 0, ikey,
-					   hapd->conf->individual_wep_key_len,
-					   1)) {
+		if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
+				      sta->addr, 0, 1, NULL, 0, ikey,
+				      hapd->conf->individual_wep_key_len)) {
 			wpa_printf(MSG_ERROR, "Could not set individual WEP "
 				   "encryption.");
 		}
@@ -343,10 +359,7 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
 
 const char *radius_mode_txt(struct hostapd_data *hapd)
 {
-	if (hapd->iface->current_mode == NULL)
-		return "802.11";
-
-	switch (hapd->iface->current_mode->mode) {
+	switch (hapd->iface->conf->hw_mode) {
 	case HOSTAPD_MODE_IEEE80211A:
 		return "802.11a";
 	case HOSTAPD_MODE_IEEE80211G:
@@ -371,6 +384,7 @@ int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta)
 }
 
 
+#ifndef CONFIG_NO_RADIUS
 static void ieee802_1x_learn_identity(struct hostapd_data *hapd,
 				      struct eapol_state_machine *sm,
 				      const u8 *eap, size_t len)
@@ -520,7 +534,8 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
 
 	/* State attribute must be copied if and only if this packet is
 	 * Access-Request reply to the previous Access-Challenge */
-	if (sm->last_recv_radius && sm->last_recv_radius->hdr->code ==
+	if (sm->last_recv_radius &&
+	    radius_msg_get_hdr(sm->last_recv_radius)->code ==
 	    RADIUS_CODE_ACCESS_CHALLENGE) {
 		int res = radius_msg_copy_attr(msg, sm->last_recv_radius,
 					       RADIUS_ATTR_STATE);
@@ -539,30 +554,8 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
 
  fail:
 	radius_msg_free(msg);
-	os_free(msg);
-}
-
-
-char *eap_type_text(u8 type)
-{
-	switch (type) {
-	case EAP_TYPE_IDENTITY: return "Identity";
-	case EAP_TYPE_NOTIFICATION: return "Notification";
-	case EAP_TYPE_NAK: return "Nak";
-	case EAP_TYPE_MD5: return "MD5-Challenge";
-	case EAP_TYPE_OTP: return "One-Time Password";
-	case EAP_TYPE_GTC: return "Generic Token Card";
-	case EAP_TYPE_TLS: return "TLS";
-	case EAP_TYPE_TTLS: return "TTLS";
-	case EAP_TYPE_PEAP: return "PEAP";
-	case EAP_TYPE_SIM: return "SIM";
-	case EAP_TYPE_FAST: return "FAST";
-	case EAP_TYPE_SAKE: return "SAKE";
-	case EAP_TYPE_PSK: return "PSK";
-	case EAP_TYPE_PAX: return "PAX";
-	default: return "Unknown";
-	}
 }
+#endif /* CONFIG_NO_RADIUS */
 
 
 static void handle_eap_response(struct hostapd_data *hapd,
@@ -587,7 +580,7 @@ static void handle_eap_response(struct hostapd_data *hapd,
 		       HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d "
 		       "id=%d len=%d) from STA: EAP Response-%s (%d)",
 		       eap->code, eap->identifier, be_to_host16(eap->length),
-		       eap_type_text(type), type);
+		       eap_server_get_name(0, type), type);
 
 	sm->dot1xAuthEapolRespFramesRx++;
 
@@ -647,6 +640,22 @@ static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta,
 }
 
 
+static struct eapol_state_machine *
+ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	int flags = 0;
+	if (sta->flags & WLAN_STA_PREAUTH)
+		flags |= EAPOL_SM_PREAUTH;
+	if (sta->wpa_sm) {
+		flags |= EAPOL_SM_USES_WPA;
+		if (wpa_auth_sta_get_pmksa(sta->wpa_sm))
+			flags |= EAPOL_SM_FROM_PMKSA_CACHE;
+	}
+	return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags,
+				sta->wps_ie, sta);
+}
+
+
 /**
  * ieee802_1x_receive - Process the EAPOL frames from the Supplicant
  * @hapd: hostapd BSS data
@@ -672,8 +681,9 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
 	wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
 		   (unsigned long) len, MAC2STR(sa));
 	sta = ap_get_sta(hapd, sa);
-	if (!sta) {
-		printf("   no station information available\n");
+	if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
+		wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
+			   "associated STA");
 		return;
 	}
 
@@ -720,9 +730,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
 		return;
 
 	if (!sta->eapol_sm) {
-		sta->eapol_sm = eapol_auth_alloc(hapd->eapol_auth, sta->addr,
-						 sta->flags & WLAN_STA_PREAUTH,
-						 sta);
+		sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta);
 		if (!sta->eapol_sm)
 			return;
 
@@ -839,9 +847,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
 	if (sta->eapol_sm == NULL) {
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_DEBUG, "start authentication");
-		sta->eapol_sm = eapol_auth_alloc(hapd->eapol_auth, sta->addr,
-						 sta->flags & WLAN_STA_PREAUTH,
-						 sta);
+		sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta);
 		if (sta->eapol_sm == NULL) {
 			hostapd_logger(hapd, sta->addr,
 				       HOSTAPD_MODULE_IEEE8021X,
@@ -900,47 +906,6 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
 }
 
 
-void ieee802_1x_free_radius_class(struct radius_class_data *class)
-{
-	size_t i;
-	if (class == NULL)
-		return;
-	for (i = 0; i < class->count; i++)
-		os_free(class->attr[i].data);
-	os_free(class->attr);
-	class->attr = NULL;
-	class->count = 0;
-}
-
-
-int ieee802_1x_copy_radius_class(struct radius_class_data *dst,
-				 const struct radius_class_data *src)
-{
-	size_t i;
-
-	if (src->attr == NULL)
-		return 0;
-
-	dst->attr = os_zalloc(src->count * sizeof(struct radius_attr_data));
-	if (dst->attr == NULL)
-		return -1;
-
-	dst->count = 0;
-
-	for (i = 0; i < src->count; i++) {
-		dst->attr[i].data = os_malloc(src->attr[i].len);
-		if (dst->attr[i].data == NULL)
-			break;
-		dst->count++;
-		os_memcpy(dst->attr[i].data, src->attr[i].data,
-			  src->attr[i].len);
-		dst->attr[i].len = src->attr[i].len;
-	}
-
-	return 0;
-}
-
-
 void ieee802_1x_free_station(struct sta_info *sta)
 {
 	struct eapol_state_machine *sm = sta->eapol_sm;
@@ -950,17 +915,17 @@ void ieee802_1x_free_station(struct sta_info *sta)
 
 	sta->eapol_sm = NULL;
 
-	if (sm->last_recv_radius) {
-		radius_msg_free(sm->last_recv_radius);
-		os_free(sm->last_recv_radius);
-	}
+#ifndef CONFIG_NO_RADIUS
+	radius_msg_free(sm->last_recv_radius);
+	radius_free_class(&sm->radius_class);
+#endif /* CONFIG_NO_RADIUS */
 
 	os_free(sm->identity);
-	ieee802_1x_free_radius_class(&sm->radius_class);
 	eapol_auth_free(sm);
 }
 
 
+#ifndef CONFIG_NO_RADIUS
 static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
 					  struct sta_info *sta)
 {
@@ -1010,12 +975,14 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd,
 		if (eap_type >= 0)
 			sm->eap_type_authsrv = eap_type;
 		os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)",
-			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
+			    eap_type >= 0 ? eap_server_get_name(0, eap_type) :
+			    "??",
 			    eap_type);
 		break;
 	case EAP_CODE_RESPONSE:
 		os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)",
-			    eap_type >= 0 ? eap_type_text(eap_type) : "??",
+			    eap_type >= 0 ? eap_server_get_name(0, eap_type) :
+			    "??",
 			    eap_type);
 		break;
 	case EAP_CODE_SUCCESS:
@@ -1097,7 +1064,7 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
 	    sm == NULL)
 		return;
 
-	ieee802_1x_free_radius_class(&sm->radius_class);
+	radius_free_class(&sm->radius_class);
 	count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1);
 	if (count <= 0)
 		return;
@@ -1225,8 +1192,9 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
 	int session_timeout_set, old_vlanid = 0;
 	struct eapol_state_machine *sm;
 	int override_eapReq = 0;
+	struct radius_hdr *hdr = radius_msg_get_hdr(msg);
 
-	sm = ieee802_1x_search_radius_identifier(hapd, msg->hdr->identifier);
+	sm = ieee802_1x_search_radius_identifier(hapd, hdr->identifier);
 	if (sm == NULL) {
 		wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not find matching "
 			   "station for this RADIUS message");
@@ -1236,7 +1204,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
 
 	/* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be
 	 * present when packet contains an EAP-Message attribute */
-	if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT &&
+	if (hdr->code == RADIUS_CODE_ACCESS_REJECT &&
 	    radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL,
 				0) < 0 &&
 	    radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) {
@@ -1250,9 +1218,9 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
 		return RADIUS_RX_INVALID_AUTHENTICATOR;
 	}
 
-	if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
-	    msg->hdr->code != RADIUS_CODE_ACCESS_REJECT &&
-	    msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
+	if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT &&
+	    hdr->code != RADIUS_CODE_ACCESS_REJECT &&
+	    hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) {
 		printf("Unknown RADIUS message code\n");
 		return RADIUS_RX_UNKNOWN;
 	}
@@ -1261,11 +1229,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
 	wpa_printf(MSG_DEBUG, "RADIUS packet matching with station " MACSTR,
 		   MAC2STR(sta->addr));
 
-	if (sm->last_recv_radius) {
-		radius_msg_free(sm->last_recv_radius);
-		os_free(sm->last_recv_radius);
-	}
-
+	radius_msg_free(sm->last_recv_radius);
 	sm->last_recv_radius = msg;
 
 	session_timeout_set =
@@ -1275,8 +1239,8 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
 				      &termination_action))
 		termination_action = RADIUS_TERMINATION_ACTION_DEFAULT;
 
-	if (hapd->conf->radius->acct_interim_interval == 0 &&
-	    msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
+	if (hapd->conf->acct_interim_interval == 0 &&
+	    hdr->code == RADIUS_CODE_ACCESS_ACCEPT &&
 	    radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL,
 				      &acct_interim_interval) == 0) {
 		if (acct_interim_interval < 60) {
@@ -1291,10 +1255,11 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
 	}
 
 
-	switch (msg->hdr->code) {
+	switch (hdr->code) {
 	case RADIUS_CODE_ACCESS_ACCEPT:
 		if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
 			sta->vlan_id = 0;
+#ifndef CONFIG_NO_VLAN
 		else {
 			old_vlanid = sta->vlan_id;
 			sta->vlan_id = radius_msg_get_vlanid(msg);
@@ -1315,8 +1280,10 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
 				       "ID in Access-Accept");
 			break;
 		}
+#endif /* CONFIG_NO_VLAN */
 
-		ap_sta_bind_vlan(hapd, sta, old_vlanid);
+		if (ap_sta_bind_vlan(hapd, sta, old_vlanid) < 0)
+			break;
 
 		/* RFC 3580, Ch. 3.17 */
 		if (session_timeout_set && termination_action ==
@@ -1373,6 +1340,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
 
 	return RADIUS_RX_QUEUED;
 }
+#endif /* CONFIG_NO_RADIUS */
 
 
 void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
@@ -1384,11 +1352,10 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
 		       HOSTAPD_LEVEL_DEBUG, "aborting authentication");
 
-	if (sm->last_recv_radius) {
-		radius_msg_free(sm->last_recv_radius);
-		os_free(sm->last_recv_radius);
-		sm->last_recv_radius = NULL;
-	}
+#ifndef CONFIG_NO_RADIUS
+	radius_msg_free(sm->last_recv_radius);
+	sm->last_recv_radius = NULL;
+#endif /* CONFIG_NO_RADIUS */
 
 	if (sm->eap_if->eapTimeout) {
 		/*
@@ -1397,74 +1364,32 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta)
 		 * could only be sent if the EAP peer actually replied).
 		 */
 		sm->eap_if->portEnabled = FALSE;
-		hostapd_sta_deauth(hapd, sta->addr,
-				   WLAN_REASON_PREV_AUTH_NOT_VALID);
-		sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
-				WLAN_STA_AUTHORIZED);
-		eloop_cancel_timeout(ap_handle_timer, hapd, sta);
-		eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
-		sta->timeout_next = STA_REMOVE;
+		ap_sta_disconnect(hapd, sta, sta->addr,
+				  WLAN_REASON_PREV_AUTH_NOT_VALID);
 	}
 }
 
 
-#ifdef HOSTAPD_DUMP_STATE
-static void fprint_char(FILE *f, char c)
-{
-	if (c >= 32 && c < 127)
-		fprintf(f, "%c", c);
-	else
-		fprintf(f, "<%02x>", c);
-}
-
-
-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_type_text(sm->eap_type_authsrv),
-		sm->eap_type_supp, eap_type_text(sm->eap_type_supp));
-
-	fprintf(f, "%scached_packets=%s\n", prefix,
-		sm->last_recv_radius ? "[RX RADIUS]" : "");
-
-	eapol_auth_dump_state(f, prefix, sm);
-}
-#endif /* HOSTAPD_DUMP_STATE */
-
-
 static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd)
 {
+	struct eapol_authenticator *eapol = hapd->eapol_auth;
+
 	if (hapd->conf->default_wep_key_len < 1)
 		return 0;
 
-	os_free(hapd->default_wep_key);
-	hapd->default_wep_key = os_malloc(hapd->conf->default_wep_key_len);
-	if (hapd->default_wep_key == NULL ||
-	    os_get_random(hapd->default_wep_key,
+	os_free(eapol->default_wep_key);
+	eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len);
+	if (eapol->default_wep_key == NULL ||
+	    os_get_random(eapol->default_wep_key,
 			  hapd->conf->default_wep_key_len)) {
 		printf("Could not generate random WEP key.\n");
-		os_free(hapd->default_wep_key);
-		hapd->default_wep_key = NULL;
+		os_free(eapol->default_wep_key);
+		eapol->default_wep_key = NULL;
 		return -1;
 	}
 
 	wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key",
-			hapd->default_wep_key,
+			eapol->default_wep_key,
 			hapd->conf->default_wep_key_len);
 
 	return 0;
@@ -1485,36 +1410,37 @@ static int ieee802_1x_sta_key_available(struct hostapd_data *hapd,
 static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
 {
 	struct hostapd_data *hapd = eloop_ctx;
+	struct eapol_authenticator *eapol = hapd->eapol_auth;
 
-	if (hapd->default_wep_key_idx >= 3)
-		hapd->default_wep_key_idx =
+	if (eapol->default_wep_key_idx >= 3)
+		eapol->default_wep_key_idx =
 			hapd->conf->individual_wep_key_len > 0 ? 1 : 0;
 	else
-		hapd->default_wep_key_idx++;
+		eapol->default_wep_key_idx++;
 
 	wpa_printf(MSG_DEBUG, "IEEE 802.1X: New default WEP key index %d",
-		   hapd->default_wep_key_idx);
+		   eapol->default_wep_key_idx);
 		      
 	if (ieee802_1x_rekey_broadcast(hapd)) {
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_WARNING, "failed to generate a "
 			       "new broadcast key");
-		os_free(hapd->default_wep_key);
-		hapd->default_wep_key = NULL;
+		os_free(eapol->default_wep_key);
+		eapol->default_wep_key = NULL;
 		return;
 	}
 
 	/* TODO: Could setup key for RX here, but change default TX keyid only
 	 * after new broadcast key has been sent to all stations. */
-	if (hostapd_set_encryption(hapd->conf->iface, hapd, "WEP", NULL,
-				   hapd->default_wep_key_idx,
-				   hapd->default_wep_key,
-				   hapd->conf->default_wep_key_len, 1)) {
+	if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, NULL,
+			      eapol->default_wep_key_idx, 1, NULL, 0,
+			      eapol->default_wep_key,
+			      hapd->conf->default_wep_key_len)) {
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_WARNING, "failed to configure a "
 			       "new broadcast key");
-		os_free(hapd->default_wep_key);
-		hapd->default_wep_key = NULL;
+		os_free(eapol->default_wep_key);
+		eapol->default_wep_key = NULL;
 		return;
 	}
 
@@ -1530,6 +1456,30 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
 static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type,
 				  const u8 *data, size_t datalen)
 {
+#ifdef CONFIG_WPS
+	struct sta_info *sta = sta_ctx;
+
+	if ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) ==
+	    WLAN_STA_MAYBE_WPS) {
+		const u8 *identity;
+		size_t identity_len;
+		struct eapol_state_machine *sm = sta->eapol_sm;
+
+		identity = eap_get_identity(sm->eap, &identity_len);
+		if (identity &&
+		    ((identity_len == WSC_ID_ENROLLEE_LEN &&
+		      os_memcmp(identity, WSC_ID_ENROLLEE,
+				WSC_ID_ENROLLEE_LEN) == 0) ||
+		     (identity_len == WSC_ID_REGISTRAR_LEN &&
+		      os_memcmp(identity, WSC_ID_REGISTRAR,
+				WSC_ID_REGISTRAR_LEN) == 0))) {
+			wpa_printf(MSG_DEBUG, "WPS: WLAN_STA_MAYBE_WPS -> "
+				   "WLAN_STA_WPS");
+			sta->flags |= WLAN_STA_WPS;
+		}
+	}
+#endif /* CONFIG_WPS */
+
 	ieee802_1x_send(ctx, sta_ctx, type, data, datalen);
 }
 
@@ -1537,10 +1487,12 @@ static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type,
 static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx,
 				const u8 *data, size_t datalen)
 {
+#ifndef CONFIG_NO_RADIUS
 	struct hostapd_data *hapd = ctx;
 	struct sta_info *sta = sta_ctx;
 
 	ieee802_1x_encapsulate_radius(hapd, sta, data, datalen);
+#endif /* CONFIG_NO_RADIUS */
 }
 
 
@@ -1608,6 +1560,7 @@ static int ieee802_1x_sta_entry_alive(void *ctx, const u8 *addr)
 static void ieee802_1x_logger(void *ctx, const u8 *addr,
 			      eapol_logger_level level, const char *txt)
 {
+#ifndef CONFIG_NO_HOSTAPD_LOGGER
 	struct hostapd_data *hapd = ctx;
 	int hlevel;
 
@@ -1626,6 +1579,7 @@ static void ieee802_1x_logger(void *ctx, const u8 *addr,
 
 	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE8021X, hlevel, "%s",
 		       txt);
+#endif /* CONFIG_NO_HOSTAPD_LOGGER */
 }
 
 
@@ -1654,6 +1608,22 @@ static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx)
 }
 
 
+static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx,
+				   enum eapol_event type)
+{
+	/* struct hostapd_data *hapd = ctx; */
+	struct sta_info *sta = sta_ctx;
+	switch (type) {
+	case EAPOL_AUTH_SM_CHANGE:
+		wpa_auth_sm_notify(sta->wpa_sm);
+		break;
+	case EAPOL_AUTH_REAUTHENTICATE:
+		wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL);
+		break;
+	}
+}
+
+
 int ieee802_1x_init(struct hostapd_data *hapd)
 {
 	int i;
@@ -1661,12 +1631,13 @@ int ieee802_1x_init(struct hostapd_data *hapd)
 	struct eapol_auth_cb cb;
 
 	os_memset(&conf, 0, sizeof(conf));
-	conf.hapd = hapd;
+	conf.ctx = hapd;
 	conf.eap_reauth_period = hapd->conf->eap_reauth_period;
 	conf.wpa = hapd->conf->wpa;
 	conf.individual_wep_key_len = hapd->conf->individual_wep_key_len;
 	conf.eap_server = hapd->conf->eap_server;
 	conf.ssl_ctx = hapd->ssl_ctx;
+	conf.msg_ctx = hapd->msg_ctx;
 	conf.eap_sim_db_priv = hapd->eap_sim_db_priv;
 	conf.eap_req_id_text = hapd->conf->eap_req_id_text;
 	conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len;
@@ -1691,29 +1662,31 @@ int ieee802_1x_init(struct hostapd_data *hapd)
 	cb.set_port_authorized = ieee802_1x_set_port_authorized;
 	cb.abort_auth = _ieee802_1x_abort_auth;
 	cb.tx_key = _ieee802_1x_tx_key;
+	cb.eapol_event = ieee802_1x_eapol_event;
 
 	hapd->eapol_auth = eapol_auth_init(&conf, &cb);
 	if (hapd->eapol_auth == NULL)
 		return -1;
 
 	if ((hapd->conf->ieee802_1x || hapd->conf->wpa) &&
-	    hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1))
+	    hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 1))
 		return -1;
 
+#ifndef CONFIG_NO_RADIUS
 	if (radius_client_register(hapd->radius, RADIUS_AUTH,
 				   ieee802_1x_receive_auth, hapd))
 		return -1;
+#endif /* CONFIG_NO_RADIUS */
 
 	if (hapd->conf->default_wep_key_len) {
-		hostapd_set_privacy(hapd, 1);
-
 		for (i = 0; i < 4; i++)
-			hostapd_set_encryption(hapd->conf->iface, hapd,
-					       "none", NULL, i, NULL, 0, 0);
+			hapd->drv.set_key(hapd->conf->iface, hapd,
+					  WPA_ALG_NONE, NULL, i, 0, NULL, 0,
+					  NULL, 0);
 
 		ieee802_1x_rekey(hapd, NULL);
 
-		if (hapd->default_wep_key == NULL)
+		if (hapd->eapol_auth->default_wep_key == NULL)
 			return -1;
 	}
 
@@ -1727,24 +1700,15 @@ void ieee802_1x_deinit(struct hostapd_data *hapd)
 
 	if (hapd->driver != NULL &&
 	    (hapd->conf->ieee802_1x || hapd->conf->wpa))
-		hostapd_set_ieee8021x(hapd->conf->iface, hapd, 0);
+		hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
 
 	eapol_auth_deinit(hapd->eapol_auth);
 	hapd->eapol_auth = NULL;
 }
 
 
-int ieee802_1x_reconfig(struct hostapd_data *hapd, 
-			struct hostapd_config *oldconf,
-			struct hostapd_bss_config *oldbss)
-{
-	ieee802_1x_deinit(hapd);
-	return ieee802_1x_init(hapd);
-}
-
-
 int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
-			 u8 *buf, size_t len, int ack)
+			 const u8 *buf, size_t len, int ack)
 {
 	struct ieee80211_hdr *hdr;
 	struct ieee802_1x_hdr *xhdr;
@@ -2039,4 +2003,23 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
 			       HOSTAPD_LEVEL_DEBUG,
 			       "Added PMKSA cache entry (IEEE 802.1X)");
 	}
+
+#ifdef CONFIG_WPS
+	if (!success && (sta->flags & WLAN_STA_WPS)) {
+		/*
+		 * Many devices require deauthentication after WPS provisioning
+		 * and some may not be be able to do that themselves, so
+		 * disconnect the client here.
+		 */
+		wpa_printf(MSG_DEBUG, "WPS: Force disconnection after "
+			   "EAP-Failure");
+		/* Add a small sleep to increase likelihood of previously
+		 * requested EAP-Failure TX getting out before this should the
+		 * driver reorder operations.
+		 */
+		os_sleep(0, 10000);
+		ap_sta_disconnect(hapd, sta, sta->addr,
+				  WLAN_REASON_PREV_AUTH_NOT_VALID);
+	}
+#endif /* CONFIG_WPS */
 }
diff --git a/contrib/wpa/hostapd/ieee802_1x.h b/contrib/wpa/src/ap/ieee802_1x.h
similarity index 89%
rename from contrib/wpa/hostapd/ieee802_1x.h
rename to contrib/wpa/src/ap/ieee802_1x.h
index 94cff9356372..1a4d2eb0f2c1 100644
--- a/contrib/wpa/hostapd/ieee802_1x.h
+++ b/contrib/wpa/src/ap/ieee802_1x.h
@@ -21,6 +21,10 @@ struct eapol_state_machine;
 struct hostapd_config;
 struct hostapd_bss_config;
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
 /* RFC 3580, 4. RC4 EAPOL-Key Frame */
 
 struct ieee802_1x_eapol_key {
@@ -43,7 +47,11 @@ struct ieee802_1x_eapol_key {
 	 * represents the number of least significant octets from
 	 * MS-MPPE-Send-Key attribute to be used as the keying material;
 	 * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
-} __attribute__ ((packed));
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
 
 void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
@@ -58,11 +66,8 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
 void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta);
 int ieee802_1x_init(struct hostapd_data *hapd);
 void ieee802_1x_deinit(struct hostapd_data *hapd);
-int ieee802_1x_reconfig(struct hostapd_data *hapd,
-			struct hostapd_config *oldconf,
-			struct hostapd_bss_config *oldbss);
 int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta,
-			 u8 *buf, size_t len, int ack);
+			 const u8 *buf, size_t len, int ack);
 u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len);
 u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len,
 				 int idx);
@@ -78,12 +83,6 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
 void hostapd_get_ntp_timestamp(u8 *buf);
 char *eap_type_text(u8 type);
 
-struct radius_class_data;
-
-void ieee802_1x_free_radius_class(struct radius_class_data *class);
-int ieee802_1x_copy_radius_class(struct radius_class_data *dst,
-				 const struct radius_class_data *src);
-
 const char *radius_mode_txt(struct hostapd_data *hapd);
 int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta);
 
diff --git a/contrib/wpa/hostapd/peerkey.c b/contrib/wpa/src/ap/peerkey_auth.c
similarity index 98%
rename from contrib/wpa/hostapd/peerkey.c
rename to contrib/wpa/src/ap/peerkey_auth.c
index 83f3ce513de3..f68c47909ae6 100644
--- a/contrib/wpa/hostapd/peerkey.c
+++ b/contrib/wpa/src/ap/peerkey_auth.c
@@ -1,6 +1,6 @@
 /*
  * hostapd - PeerKey for Direct Link Setup (DLS)
- * Copyright (c) 2006-2008, Jouni Malinen 
+ * Copyright (c) 2006-2009, Jouni Malinen 
  *
  * 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
@@ -12,14 +12,13 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#include "common.h"
-#include "eloop.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "wpa.h"
-#include "defs.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "wpa_auth.h"
 #include "wpa_auth_i.h"
 #include "wpa_auth_ie.h"
 
diff --git a/contrib/wpa/hostapd/pmksa_cache.c b/contrib/wpa/src/ap/pmksa_cache_auth.c
similarity index 79%
rename from contrib/wpa/hostapd/pmksa_cache.c
rename to contrib/wpa/src/ap/pmksa_cache_auth.c
index 5f54a34c11d4..22f44b78464a 100644
--- a/contrib/wpa/hostapd/pmksa_cache.c
+++ b/contrib/wpa/src/ap/pmksa_cache_auth.c
@@ -12,18 +12,15 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#include "common.h"
-#include "ap.h"
-#include "config.h"
-#include "common.h"
-#include "eloop.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "ieee802_1x.h"
-#include "eapol_sm.h"
-#include "pmksa_cache.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "eapol_auth/eapol_auth_sm_i.h"
+#include "sta_info.h"
+#include "ap_config.h"
+#include "pmksa_cache_auth.h"
 
 
 static const int pmksa_cache_max_entries = 1024;
@@ -41,40 +38,6 @@ struct rsn_pmksa_cache {
 };
 
 
-/**
- * rsn_pmkid - Calculate PMK identifier
- * @pmk: Pairwise master key
- * @pmk_len: Length of pmk in bytes
- * @aa: Authenticator address
- * @spa: Supplicant address
- * @pmkid: Buffer for PMKID
- * @use_sha256: Whether to use SHA256-based KDF
- *
- * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
- * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
- */
-void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
-	       u8 *pmkid, int use_sha256)
-{
-	char *title = "PMK Name";
-	const u8 *addr[3];
-	const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
-	unsigned char hash[SHA256_MAC_LEN];
-
-	addr[0] = (u8 *) title;
-	addr[1] = aa;
-	addr[2] = spa;
-
-#ifdef CONFIG_IEEE80211W
-	if (use_sha256)
-		hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
-	else
-#endif /* CONFIG_IEEE80211W */
-		hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
-	os_memcpy(pmkid, hash, PMKID_LEN);
-}
-
-
 static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
 
 
@@ -83,7 +46,9 @@ static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
 	if (entry == NULL)
 		return;
 	os_free(entry->identity);
-	ieee802_1x_free_radius_class(&entry->radius_class);
+#ifndef CONFIG_NO_RADIUS
+	radius_free_class(&entry->radius_class);
+#endif /* CONFIG_NO_RADIUS */
 	os_free(entry);
 }
 
@@ -177,11 +142,12 @@ static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
 		}
 	}
 
-	ieee802_1x_copy_radius_class(&entry->radius_class,
-				     &eapol->radius_class);
+#ifndef CONFIG_NO_RADIUS
+	radius_copy_class(&entry->radius_class, &eapol->radius_class);
+#endif /* CONFIG_NO_RADIUS */
 
 	entry->eap_type_authsrv = eapol->eap_type_authsrv;
-	entry->vlan_id = eapol->sta->vlan_id;
+	entry->vlan_id = ((struct sta_info *) eapol->sta)->vlan_id;
 }
 
 
@@ -203,16 +169,17 @@ void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
 				  eapol->identity, eapol->identity_len);
 	}
 
-	ieee802_1x_free_radius_class(&eapol->radius_class);
-	ieee802_1x_copy_radius_class(&eapol->radius_class,
-				     &entry->radius_class);
+#ifndef CONFIG_NO_RADIUS
+	radius_free_class(&eapol->radius_class);
+	radius_copy_class(&eapol->radius_class, &entry->radius_class);
+#endif /* CONFIG_NO_RADIUS */
 	if (eapol->radius_class.attr) {
 		wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from "
 			   "PMKSA", (unsigned long) eapol->radius_class.count);
 	}
 
 	eapol->eap_type_authsrv = entry->eap_type_authsrv;
-	eapol->sta->vlan_id = entry->vlan_id;
+	((struct sta_info *) eapol->sta)->vlan_id = entry->vlan_id;
 }
 
 
@@ -248,8 +215,8 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
 
 
 /**
- * pmksa_cache_add - Add a PMKSA cache entry
- * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
+ * pmksa_cache_auth_add - Add a PMKSA cache entry
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
  * @pmk: The new pairwise master key
  * @pmk_len: PMK length in bytes, usually PMK_LEN (32)
  * @aa: Authenticator address
@@ -265,7 +232,8 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
  * based on the PMK.
  */
 struct rsn_pmksa_cache_entry *
-pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
+pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
+		     const u8 *pmk, size_t pmk_len,
 		const u8 *aa, const u8 *spa, int session_timeout,
 		struct eapol_state_machine *eapol, int akmp)
 {
@@ -294,7 +262,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
 
 	/* Replace an old entry for the same STA (if found) with the new entry
 	 */
-	pos = pmksa_cache_get(pmksa, spa, NULL);
+	pos = pmksa_cache_auth_get(pmksa, spa, NULL);
 	if (pos)
 		pmksa_cache_free_entry(pmksa, pos);
 
@@ -337,8 +305,9 @@ pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
 				  old_entry->identity_len);
 		}
 	}
-	ieee802_1x_copy_radius_class(&entry->radius_class,
-				     &old_entry->radius_class);
+#ifndef CONFIG_NO_RADIUS
+	radius_copy_class(&entry->radius_class, &old_entry->radius_class);
+#endif /* CONFIG_NO_RADIUS */
 	entry->eap_type_authsrv = old_entry->eap_type_authsrv;
 	entry->vlan_id = old_entry->vlan_id;
 	entry->opportunistic = 1;
@@ -350,10 +319,10 @@ pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
 
 
 /**
- * pmksa_cache_deinit - Free all entries in PMKSA cache
- * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
+ * pmksa_cache_auth_deinit - Free all entries in PMKSA cache
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
  */
-void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
+void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa)
 {
 	struct rsn_pmksa_cache_entry *entry, *prev;
 	int i;
@@ -375,14 +344,15 @@ void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
 
 
 /**
- * pmksa_cache_get - Fetch a PMKSA cache entry
- * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
+ * pmksa_cache_auth_get - Fetch a PMKSA cache entry
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
  * @spa: Supplicant address or %NULL to match any
  * @pmkid: PMKID or %NULL to match any
  * Returns: Pointer to PMKSA cache entry or %NULL if no match was found
  */
-struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
-					       const u8 *spa, const u8 *pmkid)
+struct rsn_pmksa_cache_entry *
+pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa,
+		     const u8 *spa, const u8 *pmkid)
 {
 	struct rsn_pmksa_cache_entry *entry;
 
@@ -404,7 +374,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
 
 /**
  * pmksa_cache_get_okc - Fetch a PMKSA cache entry using OKC
- * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
  * @aa: Authenticator address
  * @spa: Supplicant address
  * @pmkid: PMKID
@@ -434,14 +404,14 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
 
 
 /**
- * pmksa_cache_init - Initialize PMKSA cache
+ * pmksa_cache_auth_init - Initialize PMKSA cache
  * @free_cb: Callback function to be called when a PMKSA cache entry is freed
  * @ctx: Context pointer for free_cb function
  * Returns: Pointer to PMKSA cache data or %NULL on failure
  */
 struct rsn_pmksa_cache *
-pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
-				 void *ctx), void *ctx)
+pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
+				      void *ctx), void *ctx)
 {
 	struct rsn_pmksa_cache *pmksa;
 
diff --git a/contrib/wpa/hostapd/pmksa_cache.h b/contrib/wpa/src/ap/pmksa_cache_auth.h
similarity index 71%
rename from contrib/wpa/hostapd/pmksa_cache.h
rename to contrib/wpa/src/ap/pmksa_cache_auth.h
index 6ba2da6073eb..9628b13da029 100644
--- a/contrib/wpa/hostapd/pmksa_cache.h
+++ b/contrib/wpa/src/ap/pmksa_cache_auth.h
@@ -15,6 +15,8 @@
 #ifndef PMKSA_CACHE_H
 #define PMKSA_CACHE_H
 
+#include "radius/radius.h"
+
 /**
  * struct rsn_pmksa_cache_entry - PMKSA cache entry
  */
@@ -38,25 +40,25 @@ struct rsn_pmksa_cache_entry {
 struct rsn_pmksa_cache;
 
 struct rsn_pmksa_cache *
-pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
-				 void *ctx), void *ctx);
-void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa);
-struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
-					       const u8 *spa, const u8 *pmkid);
+pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
+				      void *ctx), void *ctx);
+void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa);
+struct rsn_pmksa_cache_entry *
+pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa,
+		     const u8 *spa, const u8 *pmkid);
 struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
 	struct rsn_pmksa_cache *pmksa, const u8 *spa, const u8 *aa,
 	const u8 *pmkid);
 struct rsn_pmksa_cache_entry *
-pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
-		const u8 *aa, const u8 *spa, int session_timeout,
-		struct eapol_state_machine *eapol, int akmp);
+pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
+		     const u8 *pmk, size_t pmk_len,
+		     const u8 *aa, const u8 *spa, int session_timeout,
+		     struct eapol_state_machine *eapol, int akmp);
 struct rsn_pmksa_cache_entry *
 pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
 		    const struct rsn_pmksa_cache_entry *old_entry,
 		    const u8 *aa, const u8 *pmkid);
 void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
 			       struct eapol_state_machine *eapol);
-void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
-	       u8 *pmkid, int use_sha256);
 
 #endif /* PMKSA_CACHE_H */
diff --git a/contrib/wpa/hostapd/preauth.c b/contrib/wpa/src/ap/preauth_auth.c
similarity index 95%
rename from contrib/wpa/hostapd/preauth.c
rename to contrib/wpa/src/ap/preauth_auth.c
index 9ab41eda0bee..8e133158a976 100644
--- a/contrib/wpa/hostapd/preauth.c
+++ b/contrib/wpa/src/ap/preauth_auth.c
@@ -12,19 +12,22 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
 #ifdef CONFIG_RSN_PREAUTH
 
-#include "hostapd.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
 #include "l2_packet/l2_packet.h"
+#include "common/wpa_common.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "eapol_auth/eapol_auth_sm_i.h"
+#include "hostapd.h"
+#include "ap_config.h"
 #include "ieee802_1x.h"
-#include "eloop.h"
 #include "sta_info.h"
-#include "wpa_common.h"
-#include "eapol_sm.h"
-#include "wpa.h"
-#include "preauth.h"
+#include "wpa_auth.h"
+#include "preauth_auth.h"
 
 #ifndef ETH_P_PREAUTH
 #define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
@@ -256,7 +259,7 @@ void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
 
 	os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN);
 	os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN);
-	ethhdr->h_proto = htons(ETH_P_PREAUTH);
+	ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH);
 	os_memcpy(ethhdr + 1, buf, len);
 
 	if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr,
diff --git a/contrib/wpa/hostapd/preauth.h b/contrib/wpa/src/ap/preauth_auth.h
similarity index 100%
rename from contrib/wpa/hostapd/preauth.h
rename to contrib/wpa/src/ap/preauth_auth.h
diff --git a/contrib/wpa/hostapd/sta_info.c b/contrib/wpa/src/ap/sta_info.c
similarity index 88%
rename from contrib/wpa/hostapd/sta_info.c
rename to contrib/wpa/src/ap/sta_info.c
index a139ba9bdf94..335c9a5bd724 100644
--- a/contrib/wpa/hostapd/sta_info.c
+++ b/contrib/wpa/src/ap/sta_info.c
@@ -1,7 +1,6 @@
 /*
  * hostapd / Station table
- * Copyright (c) 2002-2008, Jouni Malinen 
- * Copyright (c) 2007-2008, Intel Corporation
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -13,26 +12,28 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
+#include "radius/radius.h"
+#include "radius/radius_client.h"
+#include "drivers/driver.h"
 #include "hostapd.h"
-#include "sta_info.h"
-#include "eloop.h"
 #include "accounting.h"
 #include "ieee802_1x.h"
 #include "ieee802_11.h"
-#include "radius/radius.h"
-#include "wpa.h"
-#include "preauth.h"
-#include "radius/radius_client.h"
-#include "driver.h"
+#include "wpa_auth.h"
+#include "preauth_auth.h"
+#include "ap_config.h"
 #include "beacon.h"
-#include "hw_features.h"
-#include "mlme.h"
+#include "ap_mlme.h"
 #include "vlan_init.h"
+#include "sta_info.h"
 
-static int ap_sta_in_other_bss(struct hostapd_data *hapd,
-			       struct sta_info *sta, u32 flags);
+static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
+				       struct sta_info *sta);
 static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
 #ifdef CONFIG_IEEE80211W
 static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
@@ -120,15 +121,18 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 
 	accounting_sta_stop(hapd, sta);
 
-	if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) &&
-	    !(sta->flags & WLAN_STA_PREAUTH))
-		hostapd_sta_remove(hapd, sta->addr);
+	if (sta->flags & WLAN_STA_WDS)
+		hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 0);
+
+	if (!(sta->flags & WLAN_STA_PREAUTH))
+		hapd->drv.sta_remove(hapd, sta->addr);
 
 	ap_sta_hash_del(hapd, sta);
 	ap_sta_list_del(hapd, sta);
 
 	if (sta->aid > 0)
-		hapd->sta_aid[sta->aid - 1] = NULL;
+		hapd->sta_aid[(sta->aid - 1) / 32] &=
+			~BIT((sta->aid - 1) % 32);
 
 	hapd->num_sta--;
 	if (sta->nonerp_set) {
@@ -154,7 +158,6 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 			set_beacon++;
 	}
 
-#ifdef CONFIG_IEEE80211N
 	if (sta->no_ht_gf_set) {
 		sta->no_ht_gf_set = 0;
 		hapd->iface->num_sta_ht_no_gf--;
@@ -170,9 +173,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 		hapd->iface->num_sta_ht_20mhz--;
 	}
 
+#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
 	if (hostapd_ht_operation_update(hapd->iface) > 0)
 		set_beacon++;
-#endif /* CONFIG_IEEE80211N */
+#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
 
 	if (set_beacon)
 		ieee802_11_set_beacons(hapd->iface);
@@ -183,7 +187,9 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 	ieee802_1x_free_station(sta);
 	wpa_auth_sta_deinit(sta->wpa_sm);
 	rsn_preauth_free_station(hapd, sta);
+#ifndef CONFIG_NO_RADIUS
 	radius_client_flush_auth(hapd->radius, sta->addr);
+#endif /* CONFIG_NO_RADIUS */
 
 	os_free(sta->last_assoc_req);
 	os_free(sta->challenge);
@@ -195,6 +201,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 
 	wpabuf_free(sta->wps_ie);
 
+	os_free(sta->ht_capabilities);
+
 	os_free(sta);
 }
 
@@ -247,7 +255,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
 		int inactive_sec;
 		wpa_printf(MSG_DEBUG, "Checking STA " MACSTR " inactivity:",
 			   MAC2STR(sta->addr));
-		inactive_sec = hostapd_get_inact_sec(hapd, sta->addr);
+		inactive_sec = hapd->drv.get_inact_sec(hapd, sta->addr);
 		if (inactive_sec == -1) {
 			wpa_printf(MSG_DEBUG, "Could not get station info "
 				   "from kernel driver for " MACSTR ".",
@@ -280,6 +288,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
 
 	if (sta->timeout_next == STA_NULLFUNC &&
 	    (sta->flags & WLAN_STA_ASSOC)) {
+#ifndef CONFIG_NATIVE_WINDOWS
 		/* send data frame to poll STA and check whether this frame
 		 * is ACKed */
 		struct ieee80211_hdr hdr;
@@ -287,7 +296,6 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
 		wpa_printf(MSG_DEBUG, "  Polling STA with data frame");
 		sta->flags |= WLAN_STA_PENDING_POLL;
 
-#ifndef CONFIG_NATIVE_WINDOWS
 		os_memset(&hdr, 0, sizeof(hdr));
 		if (hapd->driver &&
 		    os_strcmp(hapd->driver->name, "hostap") == 0) {
@@ -311,7 +319,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
 			  ETH_ALEN);
 		os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
 
-		if (hostapd_send_mgmt_frame(hapd, &hdr, sizeof(hdr), 0) < 0)
+		if (hapd->drv.send_mgmt_frame(hapd, &hdr, sizeof(hdr)) < 0)
 			perror("ap_handle_timer: send");
 #endif /* CONFIG_NATIVE_WINDOWS */
 	} else if (sta->timeout_next != STA_REMOVE) {
@@ -322,10 +330,10 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
 			   MAC2STR(sta->addr));
 
 		if (deauth) {
-			hostapd_sta_deauth(hapd, sta->addr,
-					   WLAN_REASON_PREV_AUTH_NOT_VALID);
+			hapd->drv.sta_deauth(hapd, sta->addr,
+					     WLAN_REASON_PREV_AUTH_NOT_VALID);
 		} else {
-			hostapd_sta_disassoc(
+			hapd->drv.sta_disassoc(
 				hapd, sta->addr,
 				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
 		}
@@ -389,7 +397,7 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
 		RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT;
 	os_memcpy(addr, sta->addr, ETH_ALEN);
 	ap_free_sta(hapd, sta);
-	hostapd_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
+	hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
 }
 
 
@@ -432,7 +440,7 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
 		wpa_printf(MSG_ERROR, "malloc failed");
 		return NULL;
 	}
-	sta->acct_interim_interval = hapd->conf->radius->acct_interim_interval;
+	sta->acct_interim_interval = hapd->conf->acct_interim_interval;
 
 	/* initialize STA info data */
 	eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
@@ -443,6 +451,7 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
 	hapd->num_sta++;
 	ap_sta_hash_add(hapd, sta);
 	sta->ssid = &hapd->conf->ssid;
+	ap_sta_remove_in_other_bss(hapd, sta);
 
 	return sta;
 }
@@ -454,7 +463,7 @@ static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
 
 	wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
 		   MAC2STR(sta->addr));
-	if (hostapd_sta_remove(hapd, sta->addr) &&
+	if (hapd->drv.sta_remove(hapd, sta->addr) &&
 	    sta->flags & WLAN_STA_ASSOC) {
 		wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
 			   " from kernel driver.", MAC2STR(sta->addr));
@@ -464,8 +473,8 @@ static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta)
 }
 
 
-static int ap_sta_in_other_bss(struct hostapd_data *hapd,
-			       struct sta_info *sta, u32 flags)
+static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
+				       struct sta_info *sta)
 {
 	struct hostapd_iface *iface = hapd->iface;
 	size_t i;
@@ -480,11 +489,12 @@ static int ap_sta_in_other_bss(struct hostapd_data *hapd,
 		if (bss == hapd || bss == NULL)
 			continue;
 		sta2 = ap_get_sta(bss, sta->addr);
-		if (sta2 && ((sta2->flags & flags) == flags))
-			return 1;
-	}
+		if (!sta2)
+			continue;
 
-	return 0;
+		ap_sta_disconnect(bss, sta2, sta2->addr,
+				  WLAN_REASON_PREV_AUTH_NOT_VALID);
+	}
 }
 
 
@@ -494,8 +504,7 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
 	wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR,
 		   hapd->conf->iface, MAC2STR(sta->addr));
 	sta->flags &= ~WLAN_STA_ASSOC;
-	if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC))
-		ap_sta_remove(hapd, sta);
+	ap_sta_remove(hapd, sta);
 	sta->timeout_next = STA_DEAUTH;
 	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
 	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
@@ -513,8 +522,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
 	wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR,
 		   hapd->conf->iface, MAC2STR(sta->addr));
 	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
-	if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC))
-		ap_sta_remove(hapd, sta);
+	ap_sta_remove(hapd, sta);
 	sta->timeout_next = STA_REMOVE;
 	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
 	eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
@@ -529,8 +537,10 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
 int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
 		     int old_vlanid)
 {
+#ifndef CONFIG_NO_VLAN
 	const char *iface;
 	struct hostapd_vlan *vlan = NULL;
+	int ret;
 
 	/*
 	 * Do not proceed furthur if the vlan id remains same. We do not want
@@ -626,7 +636,16 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
 	if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0)
 		wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
 
-	return hostapd_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
+	ret = hapd->drv.set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
+	if (ret < 0) {
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
+			       "entry to vlan_id=%d", sta->vlan_id);
+	}
+	return ret;
+#else /* CONFIG_NO_VLAN */
+	return 0;
+#endif /* CONFIG_NO_VLAN */
 }
 
 
@@ -690,7 +709,9 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
 		       HOSTAPD_LEVEL_DEBUG,
 		       "association SA Query attempt %d", sta->sa_query_count);
 
+#ifdef NEED_AP_MLME
 	ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
+#endif /* NEED_AP_MLME */
 }
 
 
@@ -709,3 +730,22 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
 }
 
 #endif /* CONFIG_IEEE80211W */
+
+
+void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
+		       const u8 *addr, u16 reason)
+{
+
+	if (sta == NULL && addr)
+		sta = ap_get_sta(hapd, addr);
+
+	if (addr)
+		hapd->drv.sta_deauth(hapd, addr, reason);
+
+	if (sta == NULL)
+		return;
+	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED);
+	eloop_cancel_timeout(ap_handle_timer, hapd, sta);
+	eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
+	sta->timeout_next = STA_REMOVE;
+}
diff --git a/contrib/wpa/hostapd/ap.h b/contrib/wpa/src/ap/sta_info.h
similarity index 68%
rename from contrib/wpa/hostapd/ap.h
rename to contrib/wpa/src/ap/sta_info.h
index 2c6d7e9799cd..55faa5a28c5e 100644
--- a/contrib/wpa/hostapd/ap.h
+++ b/contrib/wpa/src/ap/sta_info.h
@@ -1,7 +1,6 @@
 /*
- * hostapd / Station table data structures
- * Copyright (c) 2002-2008, Jouni Malinen 
- * Copyright (c) 2007-2008, Intel Corporation
+ * hostapd / Station table
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -13,12 +12,8 @@
  * See README and COPYING for more details.
  */
 
-#ifndef AP_H
-#define AP_H
-
-#ifdef CONFIG_IEEE80211N
-#include "ieee802_11_defs.h"
-#endif /* CONFIG_IEEE80211N */
+#ifndef STA_INFO_H
+#define STA_INFO_H
 
 /* STA flags */
 #define WLAN_STA_AUTH BIT(0)
@@ -35,6 +30,7 @@
 #define WLAN_STA_HT BIT(11)
 #define WLAN_STA_WPS BIT(12)
 #define WLAN_STA_MAYBE_WPS BIT(13)
+#define WLAN_STA_WDS BIT(14)
 #define WLAN_STA_NONERP BIT(31)
 
 /* Maximum number of supported rates (from both Supported Rates and Extended
@@ -47,7 +43,7 @@ struct sta_info {
 	struct sta_info *hnext; /* next entry in hash table list */
 	u8 addr[6];
 	u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
-	u32 flags;
+	u32 flags; /* Bitfield of WLAN_STA_* */
 	u16 capability;
 	u16 listen_interval; /* or beacon_int for APs */
 	u8 supported_rates[WLAN_SUPP_RATES_MAX];
@@ -95,9 +91,7 @@ struct sta_info {
 
 	int vlan_id;
 
-#ifdef CONFIG_IEEE80211N
-	struct ht_cap_ie ht_capabilities; /* IEEE 802.11n capabilities */
-#endif /* CONFIG_IEEE80211N */
+	struct ieee80211_ht_capabilities *ht_capabilities;
 
 #ifdef CONFIG_IEEE80211W
 	int sa_query_count; /* number of pending SA Query requests;
@@ -113,14 +107,6 @@ struct sta_info {
 };
 
 
-/* Maximum number of AIDs to use for STAs; must be 2007 or lower
- * (8802.11 limitation) */
-#define MAX_AID_TABLE_SIZE 128
-
-#define STA_HASH_SIZE 256
-#define STA_HASH(sta) (sta[5])
-
-
 /* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has
  * passed since last received frame from the station, a nullfunc data frame is
  * sent to the station. If this frame is not acknowledged and no other frames
@@ -136,4 +122,34 @@ struct sta_info {
 /* Number of seconds to keep STA entry after it has been deauthenticated. */
 #define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5)
 
-#endif /* AP_H */
+
+struct hostapd_data;
+
+int ap_for_each_sta(struct hostapd_data *hapd,
+		    int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
+			      void *ctx),
+		    void *ctx);
+struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
+void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
+void hostapd_free_stas(struct hostapd_data *hapd);
+void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
+void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
+			    u32 session_timeout);
+void ap_sta_no_session_timeout(struct hostapd_data *hapd,
+			       struct sta_info *sta);
+struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr);
+void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
+			 u16 reason);
+void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
+			   u16 reason);
+int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
+		     int old_vlanid);
+void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
+int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
+		       const u8 *addr, u16 reason);
+
+#endif /* STA_INFO_H */
diff --git a/contrib/wpa/src/ap/tkip_countermeasures.c b/contrib/wpa/src/ap/tkip_countermeasures.c
new file mode 100644
index 000000000000..9690348e9ccf
--- /dev/null
+++ b/contrib/wpa/src/ap/tkip_countermeasures.c
@@ -0,0 +1,93 @@
+/*
+ * hostapd / TKIP countermeasures
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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 "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
+#include "hostapd.h"
+#include "sta_info.h"
+#include "ap_mlme.h"
+#include "wpa_auth.h"
+#include "tkip_countermeasures.h"
+
+
+static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
+						void *timeout_ctx)
+{
+	struct hostapd_data *hapd = eloop_ctx;
+	hapd->tkip_countermeasures = 0;
+	hapd->drv.set_countermeasures(hapd, 0);
+	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
+}
+
+
+static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
+{
+	struct sta_info *sta;
+
+	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
+
+	wpa_auth_countermeasures_start(hapd->wpa_auth);
+	hapd->tkip_countermeasures = 1;
+	hapd->drv.set_countermeasures(hapd, 1);
+	wpa_gtk_rekey(hapd->wpa_auth);
+	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
+	eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
+			       hapd, NULL);
+	for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
+		hapd->drv.sta_deauth(hapd, sta->addr,
+				     WLAN_REASON_MICHAEL_MIC_FAILURE);
+		sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
+				WLAN_STA_AUTHORIZED);
+		hapd->drv.sta_remove(hapd, sta->addr);
+	}
+}
+
+
+void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
+{
+	time_t now;
+
+	if (addr && local) {
+		struct sta_info *sta = ap_get_sta(hapd, addr);
+		if (sta != NULL) {
+			wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
+			hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+				       HOSTAPD_LEVEL_INFO,
+				       "Michael MIC failure detected in "
+				       "received frame");
+			mlme_michaelmicfailure_indication(hapd, addr);
+		} else {
+			wpa_printf(MSG_DEBUG,
+				   "MLME-MICHAELMICFAILURE.indication "
+				   "for not associated STA (" MACSTR
+				   ") ignored", MAC2STR(addr));
+			return;
+		}
+	}
+
+	time(&now);
+	if (now > hapd->michael_mic_failure + 60) {
+		hapd->michael_mic_failures = 1;
+	} else {
+		hapd->michael_mic_failures++;
+		if (hapd->michael_mic_failures > 1)
+			ieee80211_tkip_countermeasures_start(hapd);
+	}
+	hapd->michael_mic_failure = now;
+}
diff --git a/contrib/wpa/src/ap/tkip_countermeasures.h b/contrib/wpa/src/ap/tkip_countermeasures.h
new file mode 100644
index 000000000000..5a1afceb0314
--- /dev/null
+++ b/contrib/wpa/src/ap/tkip_countermeasures.h
@@ -0,0 +1,20 @@
+/*
+ * hostapd / TKIP countermeasures
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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 TKIP_COUNTERMEASURES_H
+#define TKIP_COUNTERMEASURES_H
+
+void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local);
+
+#endif /* TKIP_COUNTERMEASURES_H */
diff --git a/contrib/wpa/src/ap/utils.c b/contrib/wpa/src/ap/utils.c
new file mode 100644
index 000000000000..0ff48aeb37de
--- /dev/null
+++ b/contrib/wpa/src/ap/utils.c
@@ -0,0 +1,88 @@
+/*
+ * AP mode helper functions
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 "common/ieee802_11_defs.h"
+#include "sta_info.h"
+#include "hostapd.h"
+
+
+int hostapd_register_probereq_cb(struct hostapd_data *hapd,
+				 int (*cb)(void *ctx, const u8 *sa,
+					   const u8 *ie, size_t ie_len),
+				 void *ctx)
+{
+	struct hostapd_probereq_cb *n;
+
+	n = os_realloc(hapd->probereq_cb, (hapd->num_probereq_cb + 1) *
+		       sizeof(struct hostapd_probereq_cb));
+	if (n == NULL)
+		return -1;
+
+	hapd->probereq_cb = n;
+	n = &hapd->probereq_cb[hapd->num_probereq_cb];
+	hapd->num_probereq_cb++;
+
+	n->cb = cb;
+	n->ctx = ctx;
+
+	return 0;
+}
+
+
+struct prune_data {
+	struct hostapd_data *hapd;
+	const u8 *addr;
+};
+
+static int prune_associations(struct hostapd_iface *iface, void *ctx)
+{
+	struct prune_data *data = ctx;
+	struct sta_info *osta;
+	struct hostapd_data *ohapd;
+	size_t j;
+
+	for (j = 0; j < iface->num_bss; j++) {
+		ohapd = iface->bss[j];
+		if (ohapd == data->hapd)
+			continue;
+		osta = ap_get_sta(ohapd, data->addr);
+		if (!osta)
+			continue;
+
+		ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED);
+	}
+
+	return 0;
+}
+
+/**
+ * hostapd_prune_associations - Remove extraneous associations
+ * @hapd: Pointer to BSS data for the most recent association
+ * @addr: Associated STA address
+ *
+ * This function looks through all radios and BSS's for previous
+ * (stale) associations of STA. If any are found they are removed.
+ */
+void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr)
+{
+	struct prune_data data;
+	data.hapd = hapd;
+	data.addr = addr;
+	if (hapd->iface->for_each_interface)
+		hapd->iface->for_each_interface(hapd->iface->interfaces,
+						prune_associations, &data);
+}
diff --git a/contrib/wpa/hostapd/vlan_init.c b/contrib/wpa/src/ap/vlan_init.c
similarity index 68%
rename from contrib/wpa/hostapd/vlan_init.c
rename to contrib/wpa/src/ap/vlan_init.c
index 87c61e2c0115..c9d166a8f346 100644
--- a/contrib/wpa/hostapd/vlan_init.c
+++ b/contrib/wpa/src/ap/vlan_init.c
@@ -2,6 +2,7 @@
  * hostapd / VLAN initialization
  * Copyright 2003, Instant802 Networks, Inc.
  * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2009, Jouni Malinen 
  *
  * 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
@@ -13,10 +14,11 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
+#include "utils/common.h"
 #include "hostapd.h"
-#include "driver.h"
+#include "ap_config.h"
 #include "vlan_init.h"
 
 
@@ -28,8 +30,8 @@
 #include 
 #include 
 
-#include "priv_netlink.h"
-#include "eloop.h"
+#include "drivers/priv_netlink.h"
+#include "utils/eloop.h"
 
 
 struct full_dynamic_vlan {
@@ -43,7 +45,8 @@ static int ifconfig_helper(const char *if_name, int up)
 	struct ifreq ifr;
 
 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("socket[AF_INET,SOCK_STREAM]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+			   "failed: %s", __func__, strerror(errno));
 		return -1;
 	}
 
@@ -51,7 +54,9 @@ static int ifconfig_helper(const char *if_name, int up)
 	os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
 
 	if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) {
-		perror("ioctl[SIOCGIFFLAGS]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCGIFFLAGS) failed "
+			   "for interface %s: %s",
+			   __func__, if_name, strerror(errno));
 		close(fd);
 		return -1;
 	}
@@ -62,7 +67,9 @@ static int ifconfig_helper(const char *if_name, int up)
 		ifr.ifr_flags &= ~IFF_UP;
 
 	if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
-		perror("ioctl[SIOCSIFFLAGS]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed "
+			   "for interface %s (up=%d): %s",
+			   __func__, if_name, up, strerror(errno));
 		close(fd);
 		return -1;
 	}
@@ -74,12 +81,14 @@ static int ifconfig_helper(const char *if_name, int up)
 
 static int ifconfig_up(const char *if_name)
 {
+	wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name);
 	return ifconfig_helper(if_name, 1);
 }
 
 
 static int ifconfig_down(const char *if_name)
 {
+	wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name);
 	return ifconfig_helper(if_name, 0);
 }
 
@@ -104,16 +113,19 @@ static int br_delif(const char *br_name, const char *if_name)
 	unsigned long args[2];
 	int if_index;
 
+	wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name);
 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("socket[AF_INET,SOCK_STREAM]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+			   "failed: %s", __func__, strerror(errno));
 		return -1;
 	}
 
 	if_index = if_nametoindex(if_name);
 
 	if (if_index == 0) {
-		printf("Failure determining interface index for '%s'\n",
-		       if_name);
+		wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
+			   "interface index for '%s'",
+			   __func__, if_name);
 		close(fd);
 		return -1;
 	}
@@ -126,7 +138,9 @@ static int br_delif(const char *br_name, const char *if_name)
 
 	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) {
 		/* No error if interface already removed. */
-		perror("ioctl[SIOCDEVPRIVATE,BRCTL_DEL_IF]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
+			   "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: "
+			   "%s", __func__, br_name, if_name, strerror(errno));
 		close(fd);
 		return -1;
 	}
@@ -150,16 +164,19 @@ static int br_addif(const char *br_name, const char *if_name)
 	unsigned long args[2];
 	int if_index;
 
+	wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name);
 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("socket[AF_INET,SOCK_STREAM]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+			   "failed: %s", __func__, strerror(errno));
 		return -1;
 	}
 
 	if_index = if_nametoindex(if_name);
 
 	if (if_index == 0) {
-		printf("Failure determining interface index for '%s'\n",
-		       if_name);
+		wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
+			   "interface index for '%s'",
+			   __func__, if_name);
 		close(fd);
 		return -1;
 	}
@@ -177,7 +194,9 @@ static int br_addif(const char *br_name, const char *if_name)
 			return 1;
 		}
 
-		perror("ioctl[SIOCDEVPRIVATE,BRCTL_ADD_IF]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
+			   "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: "
+			   "%s", __func__, br_name, if_name, strerror(errno));
 		close(fd);
 		return -1;
 	}
@@ -192,8 +211,10 @@ static int br_delbr(const char *br_name)
 	int fd;
 	unsigned long arg[2];
 
+	wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name);
 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("socket[AF_INET,SOCK_STREAM]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+			   "failed: %s", __func__, strerror(errno));
 		return -1;
 	}
 
@@ -202,7 +223,8 @@ static int br_delbr(const char *br_name)
 
 	if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) {
 		/* No error if bridge already removed. */
-		perror("ioctl[BRCTL_DEL_BRIDGE]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for "
+			   "%s: %s", __func__, br_name, strerror(errno));
 		close(fd);
 		return -1;
 	}
@@ -222,10 +244,13 @@ static int br_delbr(const char *br_name)
 static int br_addbr(const char *br_name)
 {
 	int fd;
-	unsigned long arg[2];
+	unsigned long arg[4];
+	struct ifreq ifr;
 
+	wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name);
 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("socket[AF_INET,SOCK_STREAM]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+			   "failed: %s", __func__, strerror(errno));
 		return -1;
 	}
 
@@ -238,12 +263,29 @@ static int br_addbr(const char *br_name)
 			close(fd);
 			return 1;
 		} else {
-			perror("ioctl[BRCTL_ADD_BRIDGE]");
+			wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE "
+				   "failed for %s: %s",
+				   __func__, br_name, strerror(errno));
 			close(fd);
 			return -1;
 		}
 	}
 
+	/* Decrease forwarding delay to avoid EAPOL timeouts. */
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ);
+	arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
+	arg[1] = 1;
+	arg[2] = 0;
+	arg[3] = 0;
+	ifr.ifr_data = (char *) &arg;
+	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
+		wpa_printf(MSG_ERROR, "VLAN: %s: "
+			   "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for "
+			   "%s: %s", __func__, br_name, strerror(errno));
+		/* Continue anyway */
+	}
+
 	close(fd);
 	return 0;
 }
@@ -259,7 +301,8 @@ static int br_getnumports(const char *br_name)
 	struct ifreq ifr;
 
 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("socket[AF_INET,SOCK_STREAM]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+			   "failed: %s", __func__, strerror(errno));
 		return -1;
 	}
 
@@ -273,7 +316,9 @@ static int br_getnumports(const char *br_name)
 	ifr.ifr_data = (__caddr_t) arg;
 
 	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
-		perror("ioctl[SIOCDEVPRIVATE,BRCTL_GET_PORT_LIST]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST "
+			   "failed for %s: %s",
+			   __func__, br_name, strerror(errno));
 		close(fd);
 		return -1;
 	}
@@ -294,13 +339,16 @@ static int vlan_rem(const char *if_name)
 	int fd;
 	struct vlan_ioctl_args if_request;
 
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
 	if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
-		fprintf(stderr, "Interface name to long.\n");
+		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
+			   if_name);
 		return -1;
 	}
 
 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("socket[AF_INET,SOCK_STREAM]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+			   "failed: %s", __func__, strerror(errno));
 		return -1;
 	}
 
@@ -310,7 +358,8 @@ static int vlan_rem(const char *if_name)
 	if_request.cmd = DEL_VLAN_CMD;
 
 	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
-		perror("ioctl[SIOCSIFVLAN,DEL_VLAN_CMD]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
+			   "%s", __func__, if_name, strerror(errno));
 		close(fd);
 		return -1;
 	}
@@ -333,15 +382,19 @@ static int vlan_add(const char *if_name, int vid)
 	int fd;
 	struct vlan_ioctl_args if_request;
 
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
+		   if_name, vid);
 	ifconfig_up(if_name);
 
 	if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
-		fprintf(stderr, "Interface name to long.\n");
+		wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
+			   if_name);
 		return -1;
 	}
 
 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("socket[AF_INET,SOCK_STREAM]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+			   "failed: %s", __func__, strerror(errno));
 		return -1;
 	}
 
@@ -363,6 +416,9 @@ static int vlan_add(const char *if_name, int vid)
 			    os_strncmp(if_request.u.device2, if_name,
 				       sizeof(if_request.u.device2)) == 0) {
 				close(fd);
+				wpa_printf(MSG_DEBUG, "VLAN: vlan_add: "
+					   "if_name %s exists already",
+					   if_request.device1);
 				return 1;
 			}
 		}
@@ -376,7 +432,9 @@ static int vlan_add(const char *if_name, int vid)
 	if_request.cmd = ADD_VLAN_CMD;
 
 	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
-		perror("ioctl[SIOCSIFVLAN,ADD_VLAN_CMD]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: ADD_VLAN_CMD failed for %s: "
+			   "%s",
+			   __func__, if_request.device1, strerror(errno));
 		close(fd);
 		return -1;
 	}
@@ -391,8 +449,11 @@ static int vlan_set_name_type(unsigned int name_type)
 	int fd;
 	struct vlan_ioctl_args if_request;
 
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
+		   name_type);
 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
-		perror("socket[AF_INET,SOCK_STREAM]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+			   "failed: %s", __func__, strerror(errno));
 		return -1;
 	}
 
@@ -401,7 +462,9 @@ static int vlan_set_name_type(unsigned int name_type)
 	if_request.u.name_type = name_type;
 	if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
 	if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
-		perror("ioctl[SIOCSIFVLAN,SET_VLAN_NAME_TYPE_CMD]");
+		wpa_printf(MSG_ERROR, "VLAN: %s: SET_VLAN_NAME_TYPE_CMD "
+			   "name_type=%u failed: %s",
+			   __func__, name_type, strerror(errno));
 		close(fd);
 		return -1;
 	}
@@ -418,6 +481,8 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
 	struct hostapd_vlan *vlan = hapd->conf->vlan;
 	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
 
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
+
 	while (vlan) {
 		if (os_strcmp(ifname, vlan->ifname) == 0) {
 
@@ -461,7 +526,8 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
 	char br_name[IFNAMSIZ];
 	struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
 	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
-	int numports;
+
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
 
 	first = prev = vlan;
 
@@ -470,19 +536,24 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
 			os_snprintf(br_name, sizeof(br_name), "brvlan%d",
 				    vlan->vlan_id);
 
+			if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
+				br_delif(br_name, vlan->ifname);
+
 			if (tagged_interface) {
 				os_snprintf(vlan_ifname, sizeof(vlan_ifname),
 					    "vlan%d", vlan->vlan_id);
-
-				numports = br_getnumports(br_name);
-				if (numports == 1) {
+				if (vlan->clean & DVLAN_CLEAN_VLAN_PORT)
 					br_delif(br_name, vlan_ifname);
+				ifconfig_down(vlan_ifname);
 
+				if (vlan->clean & DVLAN_CLEAN_VLAN)
 					vlan_rem(vlan_ifname);
+			}
 
-					ifconfig_down(br_name);
-					br_delbr(br_name);
-				}
+			if ((vlan->clean & DVLAN_CLEAN_BR) &&
+			    br_getnumports(br_name) == 0) {
+				ifconfig_down(br_name);
+				br_delbr(br_name);
 			}
 
 			if (vlan == first) {
@@ -561,7 +632,8 @@ static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
 			(struct sockaddr *) &from, &fromlen);
 	if (left < 0) {
 		if (errno != EINTR && errno != EAGAIN)
-			perror("recvfrom(netlink)");
+			wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
+				   __func__, strerror(errno));
 		return;
 	}
 
@@ -572,8 +644,9 @@ static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
 		len = h->nlmsg_len;
 		plen = len - sizeof(*h);
 		if (len > left || plen < 0) {
-			printf("Malformed netlink message: "
-			       "len=%d left=%d plen=%d", len, left, plen);
+			wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
+				   "message: len=%d left=%d plen=%d",
+				   len, left, plen);
 			break;
 		}
 
@@ -592,8 +665,8 @@ static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
 	}
 
 	if (left > 0) {
-		printf("%d extra bytes in the end of netlink message",
-		       left);
+		wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of "
+			   "netlink message", __func__, left);
 	}
 }
 
@@ -612,7 +685,9 @@ full_dynamic_vlan_init(struct hostapd_data *hapd)
 
 	priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
 	if (priv->s < 0) {
-		perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
+		wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
+			   "NETLINK_ROUTE) failed: %s",
+			   __func__, strerror(errno));
 		os_free(priv);
 		return NULL;
 	}
@@ -621,7 +696,8 @@ full_dynamic_vlan_init(struct hostapd_data *hapd)
 	local.nl_family = AF_NETLINK;
 	local.nl_groups = RTMGRP_LINK;
 	if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
-		perror("bind(netlink)");
+		wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
+			   __func__, strerror(errno));
 		close(priv->s);
 		os_free(priv);
 		return NULL;
@@ -661,12 +737,11 @@ int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
 	 * functions for setting up dynamic broadcast keys. */
 	for (i = 0; i < 4; i++) {
 		if (mssid->wep.key[i] &&
-		    hostapd_set_encryption(dyn_vlan, hapd, "WEP", NULL,
-					   i, mssid->wep.key[i],
-					   mssid->wep.len[i],
-					   i == mssid->wep.idx)) {
-			printf("VLAN: Could not set WEP encryption for "
-			       "dynamic VLAN.\n");
+		    hapd->drv.set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
+				      i == mssid->wep.idx, NULL, 0,
+				      mssid->wep.key[i], mssid->wep.len[i])) {
+			wpa_printf(MSG_ERROR, "VLAN: Could not set WEP "
+				   "encryption for dynamic VLAN");
 			return -1;
 		}
 	}
@@ -679,14 +754,19 @@ static int vlan_dynamic_add(struct hostapd_data *hapd,
 			    struct hostapd_vlan *vlan)
 {
 	while (vlan) {
-		if (vlan->vlan_id != VLAN_ID_WILDCARD &&
-		    hostapd_if_add(hapd, HOSTAPD_IF_VLAN, vlan->ifname, NULL))
-		{
-			if (errno != EEXIST) {
-				printf("Could not add VLAN iface: %s: %s\n",
-				       vlan->ifname, strerror(errno));
-				return -1;
+		if (vlan->vlan_id != VLAN_ID_WILDCARD) {
+			if (hapd->drv.vlan_if_add(hapd, vlan->ifname)) {
+				if (errno != EEXIST) {
+					wpa_printf(MSG_ERROR, "VLAN: Could "
+						   "not add VLAN %s: %s",
+						   vlan->ifname,
+						   strerror(errno));
+					return -1;
+				}
 			}
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+			ifconfig_up(vlan->ifname);
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
 		}
 
 		vlan = vlan->next;
@@ -705,10 +785,10 @@ static void vlan_dynamic_remove(struct hostapd_data *hapd,
 		next = vlan->next;
 
 		if (vlan->vlan_id != VLAN_ID_WILDCARD &&
-		    hostapd_if_remove(hapd, HOSTAPD_IF_VLAN, vlan->ifname,
-				      NULL)) {
-			printf("Could not remove VLAN iface: %s: %s\n",
-			       vlan->ifname, strerror(errno));
+		    hapd->drv.vlan_if_remove(hapd, vlan->ifname)) {
+			wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
+				   "iface: %s: %s",
+				   vlan->ifname, strerror(errno));
 		}
 #ifdef CONFIG_FULL_DYNAMIC_VLAN
 		if (vlan->clean)
@@ -722,13 +802,13 @@ static void vlan_dynamic_remove(struct hostapd_data *hapd,
 
 int vlan_init(struct hostapd_data *hapd)
 {
-	if (vlan_dynamic_add(hapd, hapd->conf->vlan))
-		return -1;
-
 #ifdef CONFIG_FULL_DYNAMIC_VLAN
 	hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
 
+	if (vlan_dynamic_add(hapd, hapd->conf->vlan))
+		return -1;
+
         return 0;
 }
 
@@ -743,17 +823,6 @@ void vlan_deinit(struct hostapd_data *hapd)
 }
 
 
-int vlan_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf,
-		  struct hostapd_bss_config *oldbss)
-{
-	vlan_dynamic_remove(hapd, oldbss->vlan);
-	if (vlan_dynamic_add(hapd, hapd->conf->vlan))
-		return -1;
-
-	return 0;
-}
-
-
 struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
 				       struct hostapd_vlan *vlan,
 				       int vlan_id)
@@ -765,6 +834,8 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
 	    vlan->vlan_id != VLAN_ID_WILDCARD)
 		return NULL;
 
+	wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
+		   __func__, vlan_id, vlan->ifname);
 	ifname = os_strdup(vlan->ifname);
 	if (ifname == NULL)
 		return NULL;
@@ -788,7 +859,7 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
 		    pos);
 	os_free(ifname);
 
-	if (hostapd_if_add(hapd, HOSTAPD_IF_VLAN, n->ifname, NULL)) {
+	if (hapd->drv.vlan_if_add(hapd, n->ifname)) {
 		os_free(n);
 		return NULL;
 	}
@@ -796,6 +867,10 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
 	n->next = hapd->conf->vlan;
 	hapd->conf->vlan = n;
 
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+	ifconfig_up(n->ifname);
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+
 	return n;
 }
 
@@ -807,6 +882,8 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
 	if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID)
 		return 1;
 
+	wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__, vlan_id);
+
 	vlan = hapd->conf->vlan;
 	while (vlan) {
 		if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
@@ -820,7 +897,7 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
 		return 1;
 
 	if (vlan->dynamic_vlan == 0)
-		hostapd_if_remove(hapd, HOSTAPD_IF_VLAN, vlan->ifname, NULL);
+		hapd->drv.vlan_if_remove(hapd, vlan->ifname);
 
 	return 0;
 }
diff --git a/contrib/wpa/hostapd/vlan_init.h b/contrib/wpa/src/ap/vlan_init.h
similarity index 59%
rename from contrib/wpa/hostapd/vlan_init.h
rename to contrib/wpa/src/ap/vlan_init.h
index cf55ac246220..382d5dee4f80 100644
--- a/contrib/wpa/hostapd/vlan_init.h
+++ b/contrib/wpa/src/ap/vlan_init.h
@@ -16,10 +16,9 @@
 #ifndef VLAN_INIT_H
 #define VLAN_INIT_H
 
+#ifndef CONFIG_NO_VLAN
 int vlan_init(struct hostapd_data *hapd);
 void vlan_deinit(struct hostapd_data *hapd);
-int vlan_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf,
-		  struct hostapd_bss_config *oldbss);
 struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
 				       struct hostapd_vlan *vlan,
 				       int vlan_id);
@@ -27,5 +26,34 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id);
 int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
 			      struct hostapd_ssid *mssid,
 			      const char *dyn_vlan);
+#else /* CONFIG_NO_VLAN */
+static inline int vlan_init(struct hostapd_data *hapd)
+{
+	return 0;
+}
+
+static inline void vlan_deinit(struct hostapd_data *hapd)
+{
+}
+
+static inline struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
+						     struct hostapd_vlan *vlan,
+						     int vlan_id)
+{
+	return NULL;
+}
+
+static inline int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
+{
+	return -1;
+}
+
+static inline int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
+					    struct hostapd_ssid *mssid,
+					    const char *dyn_vlan)
+{
+	return -1;
+}
+#endif /* CONFIG_NO_VLAN */
 
 #endif /* VLAN_INIT_H */
diff --git a/contrib/wpa/hostapd/wme.c b/contrib/wpa/src/ap/wmm.c
similarity index 86%
rename from contrib/wpa/hostapd/wme.c
rename to contrib/wpa/src/ap/wmm.c
index f2bbbd9cc2d0..36681309c3dc 100644
--- a/contrib/wpa/hostapd/wme.c
+++ b/contrib/wpa/src/ap/wmm.c
@@ -2,6 +2,7 @@
  * hostapd / WMM (Wi-Fi Multimedia)
  * Copyright 2002-2003, Instant802 Networks, Inc.
  * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2009, Jouni Malinen 
  *
  * 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
@@ -13,13 +14,16 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
 #include "hostapd.h"
 #include "ieee802_11.h"
-#include "wme.h"
 #include "sta_info.h"
-#include "driver.h"
+#include "ap_config.h"
+#include "wmm.h"
 
 
 /* TODO: maintain separate sequence and fragment numbers for each AC
@@ -67,6 +71,9 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
 	wmm->version = WMM_VERSION;
 	wmm->qos_info = hapd->parameter_set_count & 0xf;
 
+	if (hapd->conf->wmm_uapsd)
+		wmm->qos_info |= 0x80;
+
 	/* fill in a parameter set record for each AC */
 	for (e = 0; e < 4; e++) {
 		struct wmm_ac_parameter *ac = &wmm->ac[e];
@@ -90,7 +97,7 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid)
 /* This function is called when a station sends an association request with
  * WMM info element. The function returns zero on success or non-zero on any
  * error in WMM element. eid does not include Element ID and Length octets. */
-int hostapd_eid_wmm_valid(struct hostapd_data *hapd, u8 *eid, size_t len)
+int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len)
 {
 	struct wmm_information_element *wmm;
 
@@ -117,23 +124,6 @@ int hostapd_eid_wmm_valid(struct hostapd_data *hapd, u8 *eid, size_t len)
 }
 
 
-/* This function is called when a station sends an ACK frame for an AssocResp
- * frame (status=success) and the matching AssocReq contained a WMM element.
- */
-int hostapd_wmm_sta_config(struct hostapd_data *hapd, struct sta_info *sta)
-{
-	/* update kernel STA data for WMM related items (WLAN_STA_WPA flag) */
-	if (sta->flags & WLAN_STA_WMM)
-		hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
-				      WLAN_STA_WMM, ~0);
-	else
-		hostapd_sta_set_flags(hapd, sta->addr, sta->flags,
-				      0, ~WLAN_STA_WMM);
-
-	return 0;
-}
-
-
 static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
 			    const struct wmm_tspec_element *tspec,
 			    u8 action_code, u8 dialogue_token, u8 status_code)
@@ -160,30 +150,17 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
 	os_memcpy(t, tspec, sizeof(struct wmm_tspec_element));
 	len = ((u8 *) (t + 1)) - buf;
 
-	if (hostapd_send_mgmt_frame(hapd, m, len, 0) < 0)
+	if (hapd->drv.send_mgmt_frame(hapd, m, len) < 0)
 		perror("wmm_send_action: send");
 }
 
 
-static void wmm_addts_req(struct hostapd_data *hapd,
-			  struct ieee80211_mgmt *mgmt,
-			  struct wmm_tspec_element *tspec, size_t len)
+int wmm_process_tspec(struct wmm_tspec_element *tspec)
 {
-	u8 *end = ((u8 *) mgmt) + len;
 	int medium_time, pps, duration;
 	int up, psb, dir, tid;
 	u16 val, surplus;
 
-	if ((u8 *) (tspec + 1) > end) {
-		wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
-		return;
-	}
-
-	wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC "
-		   "from " MACSTR,
-		   mgmt->u.action.u.wmm_action.dialog_token,
-		   MAC2STR(mgmt->sa));
-
 	up = (tspec->ts_info[1] >> 3) & 0x07;
 	psb = (tspec->ts_info[1] >> 2) & 0x01;
 	dir = (tspec->ts_info[0] >> 5) & 0x03;
@@ -204,7 +181,7 @@ static void wmm_addts_req(struct hostapd_data *hapd,
 	val = le_to_host16(tspec->nominal_msdu_size);
 	if (val == 0) {
 		wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)");
-		goto invalid;
+		return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
 	}
 	/* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */
 	pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val;
@@ -213,7 +190,7 @@ static void wmm_addts_req(struct hostapd_data *hapd,
 
 	if (le_to_host32(tspec->minimum_phy_rate) < 1000000) {
 		wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate");
-		goto invalid;
+		return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
 	}
 
 	duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 /
@@ -226,7 +203,7 @@ static void wmm_addts_req(struct hostapd_data *hapd,
 	if (surplus <= 0x2000) {
 		wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not "
 			   "greater than unity");
-		goto invalid;
+		return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
 	}
 
 	medium_time = surplus * pps * duration / 0x2000;
@@ -241,35 +218,47 @@ static void wmm_addts_req(struct hostapd_data *hapd,
 	if (medium_time > 750000) {
 		wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over "
 			   "75%% of available bandwidth");
-		wmm_send_action(hapd, mgmt->sa, tspec,
-				WMM_ACTION_CODE_ADDTS_RESP,
-				mgmt->u.action.u.wmm_action.dialog_token,
-				WMM_ADDTS_STATUS_REFUSED);
-		return;
+		return WMM_ADDTS_STATUS_REFUSED;
 	}
 
 	/* Convert to 32 microseconds per second unit */
 	tspec->medium_time = host_to_le16(medium_time / 32);
 
-	wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
-			mgmt->u.action.u.wmm_action.dialog_token,
-			WMM_ADDTS_STATUS_ADMISSION_ACCEPTED);
-	return;
-
-invalid:
-	wmm_send_action(hapd, mgmt->sa, tspec,
-			WMM_ACTION_CODE_ADDTS_RESP,
-			mgmt->u.action.u.wmm_action.dialog_token,
-			WMM_ADDTS_STATUS_INVALID_PARAMETERS);
+	return WMM_ADDTS_STATUS_ADMISSION_ACCEPTED;
 }
 
 
-void hostapd_wmm_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
-			size_t len)
+static void wmm_addts_req(struct hostapd_data *hapd,
+			  const struct ieee80211_mgmt *mgmt,
+			  struct wmm_tspec_element *tspec, size_t len)
+{
+	const u8 *end = ((const u8 *) mgmt) + len;
+	int res;
+
+	if ((const u8 *) (tspec + 1) > end) {
+		wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
+		return;
+	}
+
+	wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC "
+		   "from " MACSTR,
+		   mgmt->u.action.u.wmm_action.dialog_token,
+		   MAC2STR(mgmt->sa));
+
+	res = wmm_process_tspec(tspec);
+	wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res);
+
+	wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
+			mgmt->u.action.u.wmm_action.dialog_token, res);
+}
+
+
+void hostapd_wmm_action(struct hostapd_data *hapd,
+			const struct ieee80211_mgmt *mgmt, size_t len)
 {
 	int action_code;
 	int left = len - IEEE80211_HDRLEN - 4;
-	u8 *pos = ((u8 *) mgmt) + IEEE80211_HDRLEN + 4;
+	const u8 *pos = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 4;
 	struct ieee802_11_elems elems;
 	struct sta_info *sta = ap_get_sta(hapd, mgmt->sa);
 
diff --git a/contrib/wpa/src/ap/wmm.h b/contrib/wpa/src/ap/wmm.h
new file mode 100644
index 000000000000..96b04e890963
--- /dev/null
+++ b/contrib/wpa/src/ap/wmm.h
@@ -0,0 +1,29 @@
+/*
+ * hostapd / WMM (Wi-Fi Multimedia)
+ * Copyright 2002-2003, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ *
+ * 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 WME_H
+#define WME_H
+
+struct ieee80211_mgmt;
+struct wmm_tspec_element;
+
+u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid);
+int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid,
+			  size_t len);
+void hostapd_wmm_action(struct hostapd_data *hapd,
+			const struct ieee80211_mgmt *mgmt, size_t len);
+int wmm_process_tspec(struct wmm_tspec_element *tspec);
+
+#endif /* WME_H */
diff --git a/contrib/wpa/hostapd/wpa.c b/contrib/wpa/src/ap/wpa_auth.c
similarity index 89%
rename from contrib/wpa/hostapd/wpa.c
rename to contrib/wpa/src/ap/wpa_auth.c
index 19b11d59d340..36cb0f4783c3 100644
--- a/contrib/wpa/hostapd/wpa.c
+++ b/contrib/wpa/src/ap/wpa_auth.c
@@ -12,23 +12,21 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#ifndef CONFIG_NATIVE_WINDOWS
-
-#include "common.h"
-#include "config.h"
-#include "eapol_sm.h"
-#include "wpa.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "rc4.h"
-#include "aes_wrap.h"
-#include "crypto.h"
-#include "eloop.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/state_machine.h"
+#include "common/ieee802_11_defs.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/crypto.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "ap_config.h"
 #include "ieee802_11.h"
-#include "pmksa_cache.h"
-#include "state_machine.h"
+#include "wpa_auth.h"
+#include "pmksa_cache_auth.h"
 #include "wpa_auth_i.h"
 #include "wpa_auth_ie.h"
 
@@ -38,7 +36,7 @@
 
 
 static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);
-static void wpa_sm_step(struct wpa_state_machine *sm);
+static int wpa_sm_step(struct wpa_state_machine *sm);
 static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len);
 static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx);
 static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
@@ -104,7 +102,7 @@ static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
 
 static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
 				   int vlan_id,
-				   const char *alg, const u8 *addr, int idx,
+				   enum wpa_alg alg, const u8 *addr, int idx,
 				   u8 *key, size_t key_len)
 {
 	if (wpa_auth->cb.set_key == NULL)
@@ -123,15 +121,6 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
 }
 
 
-static inline int wpa_auth_get_seqnum_igtk(struct wpa_authenticator *wpa_auth,
-					   const u8 *addr, int idx, u8 *seq)
-{
-	if (wpa_auth->cb.get_seqnum_igtk == NULL)
-		return -1;
-	return wpa_auth->cb.get_seqnum_igtk(wpa_auth->cb.ctx, addr, idx, seq);
-}
-
-
 static inline int
 wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
 		    const u8 *data, size_t data_len, int encrypt)
@@ -382,7 +371,8 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
 		return NULL;
 	}
 
-	wpa_auth->pmksa = pmksa_cache_init(wpa_auth_pmksa_free_cb, wpa_auth);
+	wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb,
+						wpa_auth);
 	if (wpa_auth->pmksa == NULL) {
 		wpa_printf(MSG_ERROR, "PMKSA cache initialization failed.");
 		os_free(wpa_auth->wpa_ie);
@@ -395,7 +385,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
 	if (wpa_auth->ft_pmk_cache == NULL) {
 		wpa_printf(MSG_ERROR, "FT PMK cache initialization failed.");
 		os_free(wpa_auth->wpa_ie);
-		pmksa_cache_deinit(wpa_auth->pmksa);
+		pmksa_cache_auth_deinit(wpa_auth->pmksa);
 		os_free(wpa_auth);
 		return NULL;
 	}
@@ -431,7 +421,7 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
 		wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations);
 #endif /* CONFIG_PEERKEY */
 
-	pmksa_cache_deinit(wpa_auth->pmksa);
+	pmksa_cache_auth_deinit(wpa_auth->pmksa);
 
 #ifdef CONFIG_IEEE80211R
 	wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache);
@@ -501,26 +491,25 @@ wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr)
 }
 
 
-void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
-			     struct wpa_state_machine *sm)
+int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
+			    struct wpa_state_machine *sm)
 {
 	if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
-		return;
+		return -1;
 
 #ifdef CONFIG_IEEE80211R
 	if (sm->ft_completed) {
 		wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
 				"FT authentication already completed - do not "
 				"start 4-way handshake");
-		return;
+		return 0;
 	}
 #endif /* CONFIG_IEEE80211R */
 
 	if (sm->started) {
 		os_memset(&sm->key_replay, 0, sizeof(sm->key_replay));
 		sm->ReAuthenticationRequest = TRUE;
-		wpa_sm_step(sm);
-		return;
+		return wpa_sm_step(sm);
 	}
 
 	wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
@@ -528,10 +517,11 @@ void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
 	sm->started = 1;
 
 	sm->Init = TRUE;
-	wpa_sm_step(sm);
+	if (wpa_sm_step(sm) == 1)
+		return 1; /* should not really happen */
 	sm->Init = FALSE;
 	sm->AuthenticationRequest = TRUE;
-	wpa_sm_step(sm);
+	return wpa_sm_step(sm);
 }
 
 
@@ -549,6 +539,9 @@ void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm)
 
 static void wpa_free_sta_sm(struct wpa_state_machine *sm)
 {
+#ifdef CONFIG_IEEE80211R
+	os_free(sm->assoc_resp_ftie);
+#endif /* CONFIG_IEEE80211R */
 	os_free(sm->last_rx_eapol_key);
 	os_free(sm->wpa_ie);
 	os_free(sm);
@@ -608,6 +601,56 @@ static int wpa_replay_counter_valid(struct wpa_state_machine *sm,
 }
 
 
+#ifdef CONFIG_IEEE80211R
+static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth,
+			       struct wpa_state_machine *sm,
+			       struct wpa_eapol_ie_parse *kde)
+{
+	struct wpa_ie_data ie;
+	struct rsn_mdie *mdie;
+
+	if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 ||
+	    ie.num_pmkid != 1 || ie.pmkid == NULL) {
+		wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in "
+			   "FT 4-way handshake message 2/4");
+		return -1;
+	}
+
+	os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN);
+	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant",
+		    sm->sup_pmk_r1_name, PMKID_LEN);
+
+	if (!kde->mdie || !kde->ftie) {
+		wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake "
+			   "message 2/4", kde->mdie ? "FTIE" : "MDIE");
+		return -1;
+	}
+
+	mdie = (struct rsn_mdie *) (kde->mdie + 2);
+	if (kde->mdie[1] < sizeof(struct rsn_mdie) ||
+	    os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain,
+		      MOBILITY_DOMAIN_ID_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
+		return -1;
+	}
+
+	if (sm->assoc_resp_ftie &&
+	    (kde->ftie[1] != sm->assoc_resp_ftie[1] ||
+	     os_memcmp(kde->ftie, sm->assoc_resp_ftie,
+		       2 + sm->assoc_resp_ftie[1]) != 0)) {
+		wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
+		wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4",
+			    kde->ftie, kde->ftie_len);
+		wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp",
+			    sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]);
+		return -1;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_IEEE80211R */
+
+
 void wpa_receive(struct wpa_authenticator *wpa_auth,
 		 struct wpa_state_machine *sm,
 		 u8 *data, size_t data_len)
@@ -619,6 +662,9 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
 	       SMK_M1, SMK_M3, SMK_ERROR } msg;
 	char *msgtxt;
 	struct wpa_eapol_ie_parse kde;
+	int ft;
+	const u8 *eapol_key_ie;
+	size_t eapol_key_ie_len;
 
 	if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL)
 		return;
@@ -749,9 +795,26 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
 					 sm->wpa_ptk_state);
 			return;
 		}
+		if (wpa_parse_kde_ies((u8 *) (key + 1), key_data_length,
+				      &kde) < 0) {
+			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+					 "received EAPOL-Key msg 2/4 with "
+					 "invalid Key Data contents");
+			return;
+		}
+		if (kde.rsn_ie) {
+			eapol_key_ie = kde.rsn_ie;
+			eapol_key_ie_len = kde.rsn_ie_len;
+		} else {
+			eapol_key_ie = kde.wpa_ie;
+			eapol_key_ie_len = kde.wpa_ie_len;
+		}
+		ft = sm->wpa == WPA_VERSION_WPA2 &&
+			wpa_key_mgmt_ft(sm->wpa_key_mgmt);
 		if (sm->wpa_ie == NULL ||
-		    sm->wpa_ie_len != key_data_length ||
-		    os_memcmp(sm->wpa_ie, key + 1, key_data_length) != 0) {
+		    wpa_compare_rsn_ie(ft,
+				       sm->wpa_ie, sm->wpa_ie_len,
+				       eapol_key_ie, eapol_key_ie_len)) {
 			wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
 					"WPA IE from (Re)AssocReq did not "
 					"match with msg 2/4");
@@ -760,11 +823,17 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
 					    sm->wpa_ie, sm->wpa_ie_len);
 			}
 			wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4",
-				    (u8 *) (key + 1), key_data_length);
+				    eapol_key_ie, eapol_key_ie_len);
 			/* MLME-DEAUTHENTICATE.request */
 			wpa_sta_disconnect(wpa_auth, sm->addr);
 			return;
 		}
+#ifdef CONFIG_IEEE80211R
+		if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
+			wpa_sta_disconnect(wpa_auth, sm->addr);
+			return;
+		}
+#endif /* CONFIG_IEEE80211R */
 		break;
 	case PAIRWISE_4:
 		if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
@@ -1178,18 +1247,19 @@ void wpa_remove_ptk(struct wpa_state_machine *sm)
 {
 	sm->PTK_valid = FALSE;
 	os_memset(&sm->PTK, 0, sizeof(sm->PTK));
-	wpa_auth_set_key(sm->wpa_auth, 0, "none", sm->addr, 0, (u8 *) "", 0);
+	wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, (u8 *) "",
+			 0);
 	sm->pairwise_set = FALSE;
 	eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
 }
 
 
-void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
+int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
 {
 	int remove_ptk = 1;
 
 	if (sm == NULL)
-		return;
+		return -1;
 
 	wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
 			 "event %d notification", event);
@@ -1204,6 +1274,24 @@ void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
 		break;
 	case WPA_REAUTH:
 	case WPA_REAUTH_EAPOL:
+		if (!sm->started) {
+			/*
+			 * When using WPS, we may end up here if the STA
+			 * manages to re-associate without the previous STA
+			 * entry getting removed. Consequently, we need to make
+			 * sure that the WPA state machines gets initialized
+			 * properly at this point.
+			 */
+			wpa_printf(MSG_DEBUG, "WPA state machine had not been "
+				   "started - initialize now");
+			sm->started = 1;
+			sm->Init = TRUE;
+			if (wpa_sm_step(sm) == 1)
+				return 1; /* should not really happen */
+			sm->Init = FALSE;
+			sm->AuthenticationRequest = TRUE;
+			break;
+		}
 		if (sm->GUpdateStationKeys) {
 			/*
 			 * Reauthentication cancels the pending group key
@@ -1217,9 +1305,13 @@ void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
 		break;
 	case WPA_ASSOC_FT:
 #ifdef CONFIG_IEEE80211R
+		wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration "
+			   "after association");
+		wpa_ft_install_ptk(sm);
+
 		/* Using FT protocol, not WPA auth state machine */
 		sm->ft_completed = 1;
-		return;
+		return 0;
 #else /* CONFIG_IEEE80211R */
 		break;
 #endif /* CONFIG_IEEE80211R */
@@ -1242,22 +1334,22 @@ void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
 			wpa_remove_ptk(sm);
 	}
 
-	wpa_sm_step(sm);
+	return wpa_sm_step(sm);
 }
 
 
-static const char * wpa_alg_txt(int alg)
+static enum wpa_alg wpa_alg_enum(int alg)
 {
 	switch (alg) {
 	case WPA_CIPHER_CCMP:
-		return "CCMP";
+		return WPA_ALG_CCMP;
 	case WPA_CIPHER_TKIP:
-		return "TKIP";
+		return WPA_ALG_TKIP;
 	case WPA_CIPHER_WEP104:
 	case WPA_CIPHER_WEP40:
-		return "WEP";
+		return WPA_ALG_WEP;
 	default:
-		return "";
+		return WPA_ALG_NONE;
 	}
 }
 
@@ -1492,6 +1584,27 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
 		return;
 	}
 
+#ifdef CONFIG_IEEE80211R
+	if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
+		/*
+		 * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
+		 * with the value we derived.
+		 */
+		if (os_memcmp(sm->sup_pmk_r1_name, sm->pmk_r1_name,
+			      WPA_PMK_NAME_LEN) != 0) {
+			wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+					"PMKR1Name mismatch in FT 4-way "
+					"handshake");
+			wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from "
+				    "Supplicant",
+				    sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
+			wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
+				    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
+			return;
+		}
+	}
+#endif /* CONFIG_IEEE80211R */
+
 	eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm);
 
 	if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
@@ -1537,8 +1650,8 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
 
 	igtk.keyid[0] = gsm->GN_igtk;
 	igtk.keyid[1] = 0;
-	if (wpa_auth_get_seqnum_igtk(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn)
-	    < 0)
+	if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE ||
+	    wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) < 0)
 		os_memset(igtk.pn, 0, sizeof(igtk.pn));
 	os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
 	pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
@@ -1581,10 +1694,12 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
 		return;
 	}
 
-	/* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, GTK[GN])
+	/* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE],
+	   GTK[GN], IGTK, [FTIE], [TIE * 2])
 	 */
 	os_memset(rsc, 0, WPA_KEY_RSC_LEN);
 	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
+	/* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */
 	wpa_ie = sm->wpa_auth->wpa_ie;
 	wpa_ie_len = sm->wpa_auth->wpa_ie_len;
 	if (sm->wpa == WPA_VERSION_WPA &&
@@ -1616,6 +1731,12 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
 	kde_len = wpa_ie_len + ieee80211w_kde_len(sm);
 	if (gtk)
 		kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
+#ifdef CONFIG_IEEE80211R
+	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
+		kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */
+		kde_len += 300; /* FTIE + 2 * TIE */
+	}
+#endif /* CONFIG_IEEE80211R */
 	kde = os_malloc(kde_len);
 	if (kde == NULL)
 		return;
@@ -1623,6 +1744,18 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
 	pos = kde;
 	os_memcpy(pos, wpa_ie, wpa_ie_len);
 	pos += wpa_ie_len;
+#ifdef CONFIG_IEEE80211R
+	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
+		int res = wpa_insert_pmkid(kde, pos - kde, sm->pmk_r1_name);
+		if (res < 0) {
+			wpa_printf(MSG_ERROR, "FT: Failed to insert "
+				   "PMKR1Name into RSN IE in EAPOL-Key data");
+			os_free(kde);
+			return;
+		}
+		pos += res;
+	}
+#endif /* CONFIG_IEEE80211R */
 	if (gtk) {
 		u8 hdr[2];
 		hdr[0] = keyidx & 0x03;
@@ -1632,6 +1765,40 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
 	}
 	pos = ieee80211w_kde_add(sm, pos);
 
+#ifdef CONFIG_IEEE80211R
+	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
+		int res;
+		struct wpa_auth_config *conf;
+
+		conf = &sm->wpa_auth->conf;
+		res = wpa_write_ftie(conf, conf->r0_key_holder,
+				     conf->r0_key_holder_len,
+				     NULL, NULL, pos, kde + kde_len - pos,
+				     NULL, 0);
+		if (res < 0) {
+			wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
+				   "into EAPOL-Key Key Data");
+			os_free(kde);
+			return;
+		}
+		pos += res;
+
+		/* TIE[ReassociationDeadline] (TU) */
+		*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
+		*pos++ = 5;
+		*pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE;
+		WPA_PUT_LE32(pos, conf->reassociation_deadline);
+		pos += 4;
+
+		/* TIE[KeyLifetime] (seconds) */
+		*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
+		*pos++ = 5;
+		*pos++ = WLAN_TIMEOUT_KEY_LIFETIME;
+		WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60);
+		pos += 4;
+	}
+#endif /* CONFIG_IEEE80211R */
+
 	wpa_send_eapol(sm->wpa_auth, sm,
 		       (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC |
 		       WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
@@ -1646,13 +1813,13 @@ SM_STATE(WPA_PTK, PTKINITDONE)
 	SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
 	sm->EAPOLKeyReceived = FALSE;
 	if (sm->Pair) {
-		char *alg;
+		enum wpa_alg alg;
 		int klen;
 		if (sm->pairwise == WPA_CIPHER_TKIP) {
-			alg = "TKIP";
+			alg = WPA_ALG_TKIP;
 			klen = 32;
 		} else {
-			alg = "CCMP";
+			alg = WPA_ALG_CCMP;
 			klen = 16;
 		}
 		if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
@@ -1934,7 +2101,7 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
 		       group->GTK[group->GN - 1], group->GTK_len);
 
 #ifdef CONFIG_IEEE80211W
-	if (wpa_auth->conf.ieee80211w != WPA_NO_IEEE80211W) {
+	if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		if (os_get_random(group->IGTK[group->GN_igtk - 4],
 				  WPA_IGTK_LEN) < 0) {
 			wpa_printf(MSG_INFO, "RSN: Failed to get new random "
@@ -2032,13 +2199,13 @@ static void wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
 	group->changed = TRUE;
 	group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
 	wpa_auth_set_key(wpa_auth, group->vlan_id,
-			 wpa_alg_txt(wpa_auth->conf.wpa_group),
+			 wpa_alg_enum(wpa_auth->conf.wpa_group),
 			 NULL, group->GN, group->GTK[group->GN - 1],
 			 group->GTK_len);
 
 #ifdef CONFIG_IEEE80211W
-	if (wpa_auth->conf.ieee80211w != WPA_NO_IEEE80211W) {
-		wpa_auth_set_key(wpa_auth, group->vlan_id, "IGTK",
+	if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+		wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK,
 				 NULL, group->GN_igtk,
 				 group->IGTK[group->GN_igtk - 4],
 				 WPA_IGTK_LEN);
@@ -2067,17 +2234,17 @@ static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
 }
 
 
-static void wpa_sm_step(struct wpa_state_machine *sm)
+static int wpa_sm_step(struct wpa_state_machine *sm)
 {
 	if (sm == NULL)
-		return;
+		return 0;
 
 	if (sm->in_step_loop) {
 		/* This should not happen, but if it does, make sure we do not
 		 * end up freeing the state machine too early by exiting the
 		 * recursive call. */
 		wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively");
-		return;
+		return 0;
 	}
 
 	sm->in_step_loop = 1;
@@ -2102,7 +2269,9 @@ static void wpa_sm_step(struct wpa_state_machine *sm)
 		wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state "
 			   "machine deinit for " MACSTR, MAC2STR(sm->addr));
 		wpa_free_sta_sm(sm);
+		return 1;
 	}
+	return 0;
 }
 
 
@@ -2404,9 +2573,9 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
 	if (sm == NULL || sm->wpa != WPA_VERSION_WPA2)
 		return -1;
 
-	if (pmksa_cache_add(sm->wpa_auth->pmksa, pmk, PMK_LEN,
-			    sm->wpa_auth->addr, sm->addr, session_timeout,
-			    eapol, sm->wpa_key_mgmt))
+	if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, PMK_LEN,
+				 sm->wpa_auth->addr, sm->addr, session_timeout,
+				 eapol, sm->wpa_key_mgmt))
 		return 0;
 
 	return -1;
@@ -2421,9 +2590,9 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
 	if (wpa_auth == NULL)
 		return -1;
 
-	if (pmksa_cache_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr,
-			    sta_addr, session_timeout, eapol,
-			    WPA_KEY_MGMT_IEEE8021X))
+	if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr,
+				 sta_addr, session_timeout, eapol,
+				 WPA_KEY_MGMT_IEEE8021X))
 		return 0;
 
 	return -1;
@@ -2480,5 +2649,3 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
 	sm->group = group;
 	return 0;
 }
-
-#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/contrib/wpa/hostapd/wpa.h b/contrib/wpa/src/ap/wpa_auth.h
similarity index 91%
rename from contrib/wpa/hostapd/wpa.h
rename to contrib/wpa/src/ap/wpa_auth.h
index 7d9b3d310677..d0136c71b666 100644
--- a/contrib/wpa/hostapd/wpa.h
+++ b/contrib/wpa/src/ap/wpa_auth.h
@@ -15,8 +15,9 @@
 #ifndef WPA_AUTH_H
 #define WPA_AUTH_H
 
-#include "eapol_common.h"
-#include "wpa_common.h"
+#include "common/defs.h"
+#include "common/eapol_common.h"
+#include "common/wpa_common.h"
 
 #ifdef _MSC_VER
 #pragma pack(push, 1)
@@ -44,13 +45,9 @@ struct ft_rrb_frame {
 #define FT_PACKET_R0KH_R1KH_RESP 201
 #define FT_PACKET_R0KH_R1KH_PUSH 202
 
-#ifndef ETH_P_RRB
-#define ETH_P_RRB 0x890D
-#endif /* ETH_P_RRB */
-
 #define FT_R0KH_R1KH_PULL_DATA_LEN 44
 #define FT_R0KH_R1KH_RESP_DATA_LEN 76
-#define FT_R0KH_R1KH_PUSH_DATA_LEN 80
+#define FT_R0KH_R1KH_PUSH_DATA_LEN 88
 
 struct ft_r0kh_r1kh_pull_frame {
 	u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
@@ -77,14 +74,15 @@ struct ft_r0kh_r1kh_resp_frame {
 	u8 s1kh_id[ETH_ALEN]; /* copied from pull */
 	u8 pmk_r1[PMK_LEN];
 	u8 pmk_r1_name[WPA_PMK_NAME_LEN];
-	u8 pad[4]; /* 8-octet boundary for AES key wrap */
+	le16 pairwise;
+	u8 pad[2]; /* 8-octet boundary for AES key wrap */
 	u8 key_wrap_extra[8];
 } STRUCT_PACKED;
 
 struct ft_r0kh_r1kh_push_frame {
 	u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
 	u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */
-	le16 data_length; /* little endian length of data (80) */
+	le16 data_length; /* little endian length of data (88) */
 	u8 ap_address[ETH_ALEN];
 
 	/* Encrypted with AES key-wrap */
@@ -95,6 +93,8 @@ struct ft_r0kh_r1kh_push_frame {
 	u8 pmk_r0_name[WPA_PMK_NAME_LEN];
 	u8 pmk_r1[PMK_LEN];
 	u8 pmk_r1_name[WPA_PMK_NAME_LEN];
+	le16 pairwise;
+	u8 pad[6]; /* 8-octet boundary for AES key wrap */
 	u8 key_wrap_extra[8];
 } STRUCT_PACKED;
 
@@ -142,13 +142,10 @@ struct wpa_auth_config {
 	int eapol_version;
 	int peerkey;
 	int wmm_enabled;
+	int wmm_uapsd;
 	int okc;
 #ifdef CONFIG_IEEE80211W
-	enum {
-		WPA_NO_IEEE80211W = 0,
-		WPA_IEEE80211W_OPTIONAL = 1,
-		WPA_IEEE80211W_REQUIRED = 2
-	} ieee80211w;
+	enum mfp_options ieee80211w;
 #endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_IEEE80211R
 #define SSID_LEN 32
@@ -187,10 +184,9 @@ struct wpa_auth_callbacks {
 	int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
 	const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *prev_psk);
 	int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len);
-	int (*set_key)(void *ctx, int vlan_id, const char *alg, const u8 *addr,
-		       int idx, u8 *key, size_t key_len);
+	int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg,
+		       const u8 *addr, int idx, u8 *key, size_t key_len);
 	int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq);
-	int (*get_seqnum_igtk)(void *ctx, const u8 *addr, int idx, u8 *seq);
 	int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data,
 			  size_t data_len, int encrypt);
 	int (*for_each_sta)(void *ctx, int (*cb)(struct wpa_state_machine *sm,
@@ -227,8 +223,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
 int wpa_auth_uses_mfp(struct wpa_state_machine *sm);
 struct wpa_state_machine *
 wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr);
-void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
-			     struct wpa_state_machine *sm);
+int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
+			    struct wpa_state_machine *sm);
 void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm);
 void wpa_auth_sta_deinit(struct wpa_state_machine *sm);
 void wpa_receive(struct wpa_authenticator *wpa_auth,
@@ -239,7 +235,7 @@ typedef enum {
 	WPA_REAUTH_EAPOL, WPA_ASSOC_FT
 } wpa_event;
 void wpa_remove_ptk(struct wpa_state_machine *sm);
-void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event);
+int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event);
 void wpa_auth_sm_notify(struct wpa_state_machine *sm);
 void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth);
 int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen);
@@ -266,7 +262,8 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
 
 #ifdef CONFIG_IEEE80211R
 u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
-				 size_t max_len, int auth_alg);
+				 size_t max_len, int auth_alg,
+				 const u8 *req_ies, size_t req_ies_len);
 void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
 			 u16 auth_transaction, const u8 *ies, size_t ies_len,
 			 void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
diff --git a/contrib/wpa/hostapd/wpa_ft.c b/contrib/wpa/src/ap/wpa_auth_ft.c
similarity index 77%
rename from contrib/wpa/hostapd/wpa_ft.c
rename to contrib/wpa/src/ap/wpa_auth_ft.c
index 31391051febd..c9871d9a61bf 100644
--- a/contrib/wpa/hostapd/wpa_ft.c
+++ b/contrib/wpa/src/ap/wpa_auth_ft.c
@@ -1,6 +1,6 @@
 /*
  * hostapd - IEEE 802.11r - Fast BSS Transition
- * Copyright (c) 2004-2007, Jouni Malinen 
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -12,25 +12,50 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#include "common.h"
-#include "config.h"
-#include "wpa.h"
-#include "aes_wrap.h"
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "crypto/aes_wrap.h"
+#include "ap_config.h"
 #include "ieee802_11.h"
-#include "defs.h"
+#include "wmm.h"
+#include "wpa_auth.h"
 #include "wpa_auth_i.h"
 #include "wpa_auth_ie.h"
 
 
 #ifdef CONFIG_IEEE80211R
 
+struct wpa_ft_ies {
+	const u8 *mdie;
+	size_t mdie_len;
+	const u8 *ftie;
+	size_t ftie_len;
+	const u8 *r1kh_id;
+	const u8 *gtk;
+	size_t gtk_len;
+	const u8 *r0kh_id;
+	size_t r0kh_id_len;
+	const u8 *rsn;
+	size_t rsn_len;
+	const u8 *rsn_pmkid;
+	const u8 *ric;
+	size_t ric_len;
+};
+
+
+static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
+			    struct wpa_ft_ies *parse);
+
+
 static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
 			   const u8 *data, size_t data_len)
 {
 	if (wpa_auth->cb.send_ether == NULL)
 		return -1;
+	wpa_printf(MSG_DEBUG, "FT: RRB send to " MACSTR, MAC2STR(dst));
 	return wpa_auth->cb.send_ether(wpa_auth->cb.ctx, dst, ETH_P_RRB,
 				       data, data_len);
 }
@@ -73,11 +98,11 @@ int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
 }
 
 
-static int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
-			  size_t r0kh_id_len,
-			  const u8 *anonce, const u8 *snonce,
-			  u8 *buf, size_t len, const u8 *subelem,
-			  size_t subelem_len)
+int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
+		   size_t r0kh_id_len,
+		   const u8 *anonce, const u8 *snonce,
+		   u8 *buf, size_t len, const u8 *subelem,
+		   size_t subelem_len)
 {
 	u8 *pos = buf, *ielen;
 	struct rsn_ftie *hdr;
@@ -127,6 +152,7 @@ struct wpa_ft_pmk_r0_sa {
 	u8 pmk_r0[PMK_LEN];
 	u8 pmk_r0_name[WPA_PMK_NAME_LEN];
 	u8 spa[ETH_ALEN];
+	int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
 	/* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
 	int pmk_r1_pushed;
 };
@@ -136,6 +162,7 @@ struct wpa_ft_pmk_r1_sa {
 	u8 pmk_r1[PMK_LEN];
 	u8 pmk_r1_name[WPA_PMK_NAME_LEN];
 	u8 spa[ETH_ALEN];
+	int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
 	/* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
 };
 
@@ -181,7 +208,7 @@ void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache)
 
 static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth,
 			       const u8 *spa, const u8 *pmk_r0,
-			       const u8 *pmk_r0_name)
+			       const u8 *pmk_r0_name, int pairwise)
 {
 	struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
 	struct wpa_ft_pmk_r0_sa *r0;
@@ -195,6 +222,7 @@ static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth,
 	os_memcpy(r0->pmk_r0, pmk_r0, PMK_LEN);
 	os_memcpy(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);
 	os_memcpy(r0->spa, spa, ETH_ALEN);
+	r0->pairwise = pairwise;
 
 	r0->next = cache->pmk_r0;
 	cache->pmk_r0 = r0;
@@ -205,7 +233,7 @@ static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth,
 
 static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth,
 			       const u8 *spa, const u8 *pmk_r0_name,
-			       u8 *pmk_r0)
+			       u8 *pmk_r0, int *pairwise)
 {
 	struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
 	struct wpa_ft_pmk_r0_sa *r0;
@@ -216,6 +244,8 @@ static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth,
 		    os_memcmp(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN)
 		    == 0) {
 			os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN);
+			if (pairwise)
+				*pairwise = r0->pairwise;
 			return 0;
 		}
 
@@ -228,7 +258,7 @@ static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth,
 
 static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth,
 			       const u8 *spa, const u8 *pmk_r1,
-			       const u8 *pmk_r1_name)
+			       const u8 *pmk_r1_name, int pairwise)
 {
 	struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
 	struct wpa_ft_pmk_r1_sa *r1;
@@ -242,6 +272,7 @@ static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth,
 	os_memcpy(r1->pmk_r1, pmk_r1, PMK_LEN);
 	os_memcpy(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);
 	os_memcpy(r1->spa, spa, ETH_ALEN);
+	r1->pairwise = pairwise;
 
 	r1->next = cache->pmk_r1;
 	cache->pmk_r1 = r1;
@@ -252,7 +283,7 @@ static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth,
 
 static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
 			       const u8 *spa, const u8 *pmk_r1_name,
-			       u8 *pmk_r1)
+			       u8 *pmk_r1, int *pairwise)
 {
 	struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
 	struct wpa_ft_pmk_r1_sa *r1;
@@ -263,6 +294,8 @@ static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
 		    os_memcmp(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN)
 		    == 0) {
 			os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN);
+			if (pairwise)
+				*pairwise = r1->pairwise;
 			return 0;
 		}
 
@@ -324,7 +357,7 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
 			   struct wpa_ptk *ptk, size_t ptk_len)
 {
 	u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN];
-	u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN];
+	u8 pmk_r1[PMK_LEN];
 	u8 ptk_name[WPA_PMK_NAME_LEN];
 	const u8 *mdid = sm->wpa_auth->conf.mobility_domain;
 	const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder;
@@ -344,16 +377,19 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
 			  r0kh, r0kh_len, sm->addr, pmk_r0, pmk_r0_name);
 	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, PMK_LEN);
 	wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN);
-	wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_name);
+	wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_name,
+			    sm->pairwise);
 
 	wpa_derive_pmk_r1(pmk_r0, pmk_r0_name, r1kh, sm->addr,
-			  pmk_r1, pmk_r1_name);
+			  pmk_r1, sm->pmk_r1_name);
 	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN);
-	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
-	wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_name);
+	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
+		    WPA_PMK_NAME_LEN);
+	wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, sm->pmk_r1_name,
+			    sm->pairwise);
 
 	wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
-			  sm->wpa_auth->addr, pmk_r1_name,
+			  sm->wpa_auth->addr, sm->pmk_r1_name,
 			  (u8 *) ptk, ptk_len, ptk_name);
 	wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len);
 	wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
@@ -371,17 +407,6 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
 }
 
 
-#ifdef CONFIG_IEEE80211W
-static inline int wpa_auth_get_seqnum_igtk(struct wpa_authenticator *wpa_auth,
-					   const u8 *addr, int idx, u8 *seq)
-{
-	if (wpa_auth->cb.get_seqnum_igtk == NULL)
-		return -1;
-	return wpa_auth->cb.get_seqnum_igtk(wpa_auth->cb.ctx, addr, idx, seq);
-}
-#endif /* CONFIG_IEEE80211W */
-
-
 static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
 {
 	u8 *subelem;
@@ -414,20 +439,21 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
 		key = gsm->GTK[gsm->GN - 1];
 
 	/*
-	 * Sub-elem ID[1] | Length[1] | Key Info[1] | Key Length[1] | RSC[8] |
+	 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
 	 * Key[5..32].
 	 */
-	subelem_len = 12 + key_len + 8;
+	subelem_len = 13 + key_len + 8;
 	subelem = os_zalloc(subelem_len);
 	if (subelem == NULL)
 		return NULL;
 
 	subelem[0] = FTIE_SUBELEM_GTK;
-	subelem[1] = 10 + key_len + 8;
-	subelem[2] = gsm->GN & 0x03; /* Key ID in B0-B1 of Key Info */
-	subelem[3] = gsm->GTK_len;
-	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 4);
-	if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 12)) {
+	subelem[1] = 11 + key_len + 8;
+	/* Key ID in B0-B1 of Key Info */
+	WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03);
+	subelem[4] = gsm->GTK_len;
+	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5);
+	if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) {
 		os_free(subelem);
 		return NULL;
 	}
@@ -456,7 +482,7 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
 	*pos++ = subelem_len - 2;
 	WPA_PUT_LE16(pos, gsm->GN_igtk);
 	pos += 2;
-	wpa_auth_get_seqnum_igtk(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
+	wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
 	pos += 6;
 	*pos++ = WPA_IGTK_LEN;
 	if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8,
@@ -471,14 +497,125 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
 #endif /* CONFIG_IEEE80211W */
 
 
-u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
-				 size_t max_len, int auth_alg)
+static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
+				const u8 *ies, size_t ies_len)
 {
-	u8 *end, *mdie, *ftie, *rsnie, *r0kh_id, *subelem = NULL;
-	size_t mdie_len, ftie_len, rsnie_len, r0kh_id_len, subelem_len = 0;
+	struct ieee802_11_elems parse;
+	struct rsn_rdie *rdie;
+
+	wpa_printf(MSG_DEBUG, "FT: Resource Request: id=%d descr_count=%d",
+		   id, descr_count);
+	wpa_hexdump(MSG_MSGDUMP, "FT: Resource descriptor IE(s)",
+		    ies, ies_len);
+
+	if (end - pos < (int) sizeof(*rdie)) {
+		wpa_printf(MSG_ERROR, "FT: Not enough room for response RDIE");
+		return pos;
+	}
+
+	*pos++ = WLAN_EID_RIC_DATA;
+	*pos++ = sizeof(*rdie);
+	rdie = (struct rsn_rdie *) pos;
+	rdie->id = id;
+	rdie->descr_count = 0;
+	rdie->status_code = host_to_le16(WLAN_STATUS_SUCCESS);
+	pos += sizeof(*rdie);
+
+	if (ieee802_11_parse_elems((u8 *) ies, ies_len, &parse, 1) ==
+	    ParseFailed) {
+		wpa_printf(MSG_DEBUG, "FT: Failed to parse request IEs");
+		rdie->status_code =
+			host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
+		return pos;
+	}
+
+#ifdef NEED_AP_MLME
+	if (parse.wmm_tspec) {
+		struct wmm_tspec_element *tspec;
+		int res;
+
+		if (parse.wmm_tspec_len + 2 < (int) sizeof(*tspec)) {
+			wpa_printf(MSG_DEBUG, "FT: Too short WMM TSPEC IE "
+				   "(%d)", (int) parse.wmm_tspec_len);
+			rdie->status_code =
+				host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
+			return pos;
+		}
+		if (end - pos < (int) sizeof(*tspec)) {
+			wpa_printf(MSG_ERROR, "FT: Not enough room for "
+				   "response TSPEC");
+			rdie->status_code =
+				host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
+			return pos;
+		}
+		tspec = (struct wmm_tspec_element *) pos;
+		os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec));
+		res = wmm_process_tspec(tspec);
+		wpa_printf(MSG_DEBUG, "FT: ADDTS processing result: %d", res);
+		if (res == WMM_ADDTS_STATUS_INVALID_PARAMETERS)
+			rdie->status_code =
+				host_to_le16(WLAN_STATUS_INVALID_PARAMETERS);
+		else if (res == WMM_ADDTS_STATUS_REFUSED)
+			rdie->status_code =
+				host_to_le16(WLAN_STATUS_REQUEST_DECLINED);
+		else {
+			/* TSPEC accepted; include updated TSPEC in response */
+			rdie->descr_count = 1;
+			pos += sizeof(*tspec);
+		}
+		return pos;
+	}
+#endif /* NEED_AP_MLME */
+
+	wpa_printf(MSG_DEBUG, "FT: No supported resource requested");
+	rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
+	return pos;
+}
+
+
+static u8 * wpa_ft_process_ric(u8 *pos, u8 *end, const u8 *ric, size_t ric_len)
+{
+	const u8 *rpos, *start;
+	const struct rsn_rdie *rdie;
+
+	wpa_hexdump(MSG_MSGDUMP, "FT: RIC Request", ric, ric_len);
+
+	rpos = ric;
+	while (rpos + sizeof(*rdie) < ric + ric_len) {
+		if (rpos[0] != WLAN_EID_RIC_DATA || rpos[1] < sizeof(*rdie) ||
+		    rpos + 2 + rpos[1] > ric + ric_len)
+			break;
+		rdie = (const struct rsn_rdie *) (rpos + 2);
+		rpos += 2 + rpos[1];
+		start = rpos;
+
+		while (rpos + 2 <= ric + ric_len &&
+		       rpos + 2 + rpos[1] <= ric + ric_len) {
+			if (rpos[0] == WLAN_EID_RIC_DATA)
+				break;
+			rpos += 2 + rpos[1];
+		}
+		pos = wpa_ft_process_rdie(pos, end, rdie->id,
+					  rdie->descr_count,
+					  start, rpos - start);
+	}
+
+	return pos;
+}
+
+
+u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
+				 size_t max_len, int auth_alg,
+				 const u8 *req_ies, size_t req_ies_len)
+{
+	u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL;
+	size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0;
 	int res;
 	struct wpa_auth_config *conf;
 	struct rsn_ftie *_ftie;
+	struct wpa_ft_ies parse;
+	u8 *ric_start;
+	u8 *anonce, *snonce;
 
 	if (sm == NULL)
 		return pos;
@@ -491,13 +628,18 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
 
 	end = pos + max_len;
 
-	/* RSN */
-	res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name);
-	if (res < 0)
-		return pos;
-	rsnie = pos;
-	rsnie_len = res;
-	pos += res;
+	if (auth_alg == WLAN_AUTH_FT) {
+		/*
+		 * RSN (only present if this is a Reassociation Response and
+		 * part of a fast BSS transition)
+		 */
+		res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name);
+		if (res < 0)
+			return pos;
+		rsnie = pos;
+		rsnie_len = res;
+		pos += res;
+	}
 
 	/* Mobility Domain Information */
 	res = wpa_write_mdie(conf, pos, end - pos);
@@ -512,6 +654,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
 		subelem = wpa_ft_gtk_subelem(sm, &subelem_len);
 		r0kh_id = sm->r0kh_id;
 		r0kh_id_len = sm->r0kh_id_len;
+		anonce = sm->ANonce;
+		snonce = sm->SNonce;
 #ifdef CONFIG_IEEE80211W
 		if (sm->mgmt_frame_prot) {
 			u8 *igtk;
@@ -537,8 +681,10 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
 	} else {
 		r0kh_id = conf->r0_key_holder;
 		r0kh_id_len = conf->r0_key_holder_len;
+		anonce = NULL;
+		snonce = NULL;
 	}
-	res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, NULL, NULL, pos,
+	res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, anonce, snonce, pos,
 			     end - pos, subelem, subelem_len);
 	os_free(subelem);
 	if (res < 0)
@@ -547,33 +693,38 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
 	ftie_len = res;
 	pos += res;
 
+	os_free(sm->assoc_resp_ftie);
+	sm->assoc_resp_ftie = os_malloc(ftie_len);
+	if (sm->assoc_resp_ftie)
+		os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
+
 	_ftie = (struct rsn_ftie *) (ftie + 2);
-	_ftie->mic_control[1] = 3; /* Information element count */
-	if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6,
+	if (auth_alg == WLAN_AUTH_FT)
+		_ftie->mic_control[1] = 3; /* Information element count */
+
+	ric_start = pos;
+	if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) {
+		pos = wpa_ft_process_ric(pos, end, parse.ric, parse.ric_len);
+		if (auth_alg == WLAN_AUTH_FT)
+			_ftie->mic_control[1] +=
+				ieee802_11_ie_count(ric_start,
+						    pos - ric_start);
+	}
+	if (ric_start == pos)
+		ric_start = NULL;
+
+	if (auth_alg == WLAN_AUTH_FT &&
+	    wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6,
 		       mdie, mdie_len, ftie, ftie_len,
-		       rsnie, rsnie_len, NULL, 0, _ftie->mic) < 0)
+		       rsnie, rsnie_len,
+		       ric_start, ric_start ? pos - ric_start : 0,
+		       _ftie->mic) < 0)
 		wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
 
 	return pos;
 }
 
 
-struct wpa_ft_ies {
-	const u8 *mdie;
-	size_t mdie_len;
-	const u8 *ftie;
-	size_t ftie_len;
-	const u8 *r1kh_id;
-	const u8 *gtk;
-	size_t gtk_len;
-	const u8 *r0kh_id;
-	size_t r0kh_id_len;
-	const u8 *rsn;
-	size_t rsn_len;
-	const u8 *rsn_pmkid;
-};
-
-
 static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
 			     struct wpa_ft_ies *parse)
 {
@@ -623,6 +774,8 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
 	const u8 *end, *pos;
 	struct wpa_ie_data data;
 	int ret;
+	const struct rsn_ftie *ftie;
+	int prot_ie_count = 0;
 
 	os_memset(parse, 0, sizeof(*parse));
 	if (ies == NULL)
@@ -651,21 +804,67 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
 			parse->mdie_len = pos[1];
 			break;
 		case WLAN_EID_FAST_BSS_TRANSITION:
+			if (pos[1] < sizeof(*ftie))
+				return -1;
+			ftie = (const struct rsn_ftie *) (pos + 2);
+			prot_ie_count = ftie->mic_control[1];
 			if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
 				return -1;
 			break;
+		case WLAN_EID_RIC_DATA:
+			if (parse->ric == NULL)
+				parse->ric = pos;
 		}
 
 		pos += 2 + pos[1];
 	}
 
+	if (prot_ie_count == 0)
+		return 0; /* no MIC */
+
+	/*
+	 * Check that the protected IE count matches with IEs included in the
+	 * frame.
+	 */
+	if (parse->rsn)
+		prot_ie_count--;
+	if (parse->mdie)
+		prot_ie_count--;
+	if (parse->ftie)
+		prot_ie_count--;
+	if (prot_ie_count < 0) {
+		wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
+			   "the protected IE count");
+		return -1;
+	}
+
+	if (prot_ie_count == 0 && parse->ric) {
+		wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
+			   "included in protected IE count");
+		return -1;
+	}
+
+	/* Determine the end of the RIC IE(s) */
+	pos = parse->ric;
+	while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
+	       prot_ie_count) {
+		prot_ie_count--;
+		pos += 2 + pos[1];
+	}
+	parse->ric_len = pos - parse->ric;
+	if (prot_ie_count) {
+		wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
+			   "frame", (int) prot_ie_count);
+		return -1;
+	}
+
 	return 0;
 }
 
 
 static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
 				   int vlan_id,
-				   const char *alg, const u8 *addr, int idx,
+				   enum wpa_alg alg, const u8 *addr, int idx,
 				   u8 *key, size_t key_len)
 {
 	if (wpa_auth->cb.set_key == NULL)
@@ -675,25 +874,29 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
 }
 
 
-static void wpa_ft_install_ptk(struct wpa_state_machine *sm)
+void wpa_ft_install_ptk(struct wpa_state_machine *sm)
 {
-	char *alg;
+	enum wpa_alg alg;
 	int klen;
 
 	/* MLME-SETKEYS.request(PTK) */
 	if (sm->pairwise == WPA_CIPHER_TKIP) {
-		alg = "TKIP";
+		alg = WPA_ALG_TKIP;
 		klen = 32;
 	} else if (sm->pairwise == WPA_CIPHER_CCMP) {
-		alg = "CCMP";
+		alg = WPA_ALG_CCMP;
 		klen = 16;
-	} else
+	} else {
+		wpa_printf(MSG_DEBUG, "FT: Unknown pairwise alg 0x%x - skip "
+			   "PTK configuration", sm->pairwise);
 		return;
+	}
 
 	/* FIX: add STA entry to kernel/driver here? The set_key will fail
 	 * most likely without this.. At the moment, STA entry is added only
-	 * after association has been completed. Alternatively, could
-	 * re-configure PTK at that point(?).
+	 * after association has been completed. This function will be called
+	 * again after association to get the PTK configured, but that could be
+	 * optimized by adding the STA entry earlier.
 	 */
 	if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
 			     sm->PTK.tk1, klen))
@@ -717,6 +920,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
 	size_t buflen, ptk_len;
 	int ret;
 	u8 *pos, *end;
+	int pairwise;
 
 	*resp_ies = NULL;
 	*resp_ies_len = 0;
@@ -772,8 +976,8 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
 	wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name",
 		    pmk_r1_name, WPA_PMK_NAME_LEN);
 
-	if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1) <
-	    0) {
+	if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1,
+		    &pairwise) < 0) {
 		if (wpa_ft_pull_pmk_r1(sm->wpa_auth, sm->addr, sm->r0kh_id,
 				       sm->r0kh_id_len, parse.rsn_pmkid) < 0) {
 			wpa_printf(MSG_DEBUG, "FT: Did not have matching "
@@ -804,7 +1008,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
 	wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",
 		    sm->ANonce, WPA_NONCE_LEN);
 
-	ptk_len = sm->pairwise == WPA_CIPHER_CCMP ? 48 : 64;
+	ptk_len = pairwise != WPA_CIPHER_CCMP ? 64 : 48;
 	wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
 			  sm->wpa_auth->addr, pmk_r1_name,
 			  (u8 *) &sm->PTK, ptk_len, ptk_name);
@@ -812,6 +1016,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm,
 			(u8 *) &sm->PTK, ptk_len);
 	wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
 
+	sm->pairwise = pairwise;
 	wpa_ft_install_ptk(sm);
 
 	buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
@@ -895,6 +1100,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
 	struct rsn_mdie *mdie;
 	struct rsn_ftie *ftie;
 	u8 mic[16];
+	unsigned int count;
 
 	if (sm == NULL)
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -938,20 +1144,79 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
 		return WLAN_STATUS_INVALID_FTIE;
 	}
 
-	/*
-	 * Assume that MDIE, FTIE, and RSN IE are protected and that there is
-	 * no RIC, so total of 3 protected IEs.
-	 */
-	if (ftie->mic_control[1] != 3) {
-		wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in FTIE (%d)",
-			   ftie->mic_control[1]);
-		return WLAN_STATUS_INVALID_FTIE;
+	if (os_memcmp(ftie->snonce, sm->SNonce, WPA_NONCE_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
+		wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
+			    ftie->snonce, WPA_NONCE_LEN);
+		wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
+			    sm->SNonce, WPA_NONCE_LEN);
+		return -1;
+	}
+
+	if (os_memcmp(ftie->anonce, sm->ANonce, WPA_NONCE_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
+		wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
+			    ftie->anonce, WPA_NONCE_LEN);
+		wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
+			    sm->ANonce, WPA_NONCE_LEN);
+		return -1;
+	}
+
+
+	if (parse.r0kh_id == NULL) {
+		wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
+		return -1;
+	}
+
+	if (parse.r0kh_id_len != sm->r0kh_id_len ||
+	    os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
+			   "the current R0KH-ID");
+		wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
+			    parse.r0kh_id, parse.r0kh_id_len);
+		wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
+			    sm->r0kh_id, sm->r0kh_id_len);
+		return -1;
+	}
+
+	if (parse.r1kh_id == NULL) {
+		wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
+		return -1;
+	}
+
+	if (os_memcmp(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder,
+		      FT_R1KH_ID_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
+			   "ReassocReq");
+		wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE",
+			    parse.r1kh_id, FT_R1KH_ID_LEN);
+		wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID",
+			    sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
+		return -1;
+	}
+
+	if (parse.rsn_pmkid == NULL ||
+	    os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) {
+		wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
+			   "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
+		return -1;
+	}
+
+	count = 3;
+	if (parse.ric)
+		count++;
+	if (ftie->mic_control[1] != count) {
+		wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
+			   "Control: received %u expected %u",
+			   ftie->mic_control[1], count);
+		return -1;
 	}
 
 	if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 5,
 		       parse.mdie - 2, parse.mdie_len + 2,
 		       parse.ftie - 2, parse.ftie_len + 2,
-		       parse.rsn - 2, parse.rsn_len + 2, NULL, 0,
+		       parse.rsn - 2, parse.rsn_len + 2,
+		       parse.ric, parse.ric_len,
 		       mic) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
 		return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -1107,6 +1372,7 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
 	struct ft_remote_r1kh *r1kh;
 	struct ft_r0kh_r1kh_resp_frame resp, r;
 	u8 pmk_r0[PMK_LEN];
+	int pairwise;
 
 	wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull");
 
@@ -1154,8 +1420,8 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
 	os_memcpy(r.nonce, f.nonce, sizeof(f.nonce));
 	os_memcpy(r.r1kh_id, f.r1kh_id, FT_R1KH_ID_LEN);
 	os_memcpy(r.s1kh_id, f.s1kh_id, ETH_ALEN);
-	if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0) <
-	    0) {
+	if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0,
+				&pairwise) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for "
 			   "PMK-R1 pull");
 		return -1;
@@ -1166,6 +1432,7 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
 	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN);
 	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name,
 		    WPA_PMK_NAME_LEN);
+	r.pairwise = host_to_le16(pairwise);
 
 	if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
 		     r.nonce, resp.nonce) < 0) {
@@ -1187,6 +1454,7 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
 {
 	struct ft_r0kh_r1kh_resp_frame *frame, f;
 	struct ft_remote_r0kh *r0kh;
+	int pairwise;
 
 	wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response");
 
@@ -1227,16 +1495,19 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
 	 * and call this requests callback function to finish request
 	 * processing */
 
+	pairwise = le_to_host16(f.pairwise);
 	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
 		    f.nonce, sizeof(f.nonce));
 	wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID="
-		   MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id));
+		   MACSTR " pairwise=0x%x",
+		   MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
 	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1",
 			f.pmk_r1, PMK_LEN);
 	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name",
 			f.pmk_r1_name, WPA_PMK_NAME_LEN);
 
-	wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name);
+	wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
+			    pairwise);
 	os_memset(f.pmk_r1, 0, PMK_LEN);
 
 	return 0;
@@ -1251,6 +1522,7 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
 	struct ft_remote_r0kh *r0kh;
 	struct os_time now;
 	os_time_t tsend;
+	int pairwise;
 
 	wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push");
 
@@ -1299,14 +1571,17 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
 		return -1;
 	}
 
+	pairwise = le_to_host16(f.pairwise);
 	wpa_printf(MSG_DEBUG, "FT: PMK-R1 push - R1KH-ID=" MACSTR " S1KH-ID="
-		   MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id));
+		   MACSTR " pairwise=0x%x",
+		   MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
 	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 push - PMK-R1",
 			f.pmk_r1, PMK_LEN);
 	wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 push - PMKR1Name",
 			f.pmk_r1_name, WPA_PMK_NAME_LEN);
 
-	wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name);
+	wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
+			    pairwise);
 	os_memset(f.pmk_r1, 0, PMK_LEN);
 
 	return 0;
@@ -1436,7 +1711,7 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
 static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
 				   struct wpa_ft_pmk_r0_sa *pmk_r0,
 				   struct ft_remote_r1kh *r1kh,
-				   const u8 *s1kh_id)
+				   const u8 *s1kh_id, int pairwise)
 {
 	struct ft_r0kh_r1kh_push_frame frame, f;
 	struct os_time now;
@@ -1460,6 +1735,7 @@ static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
 		    WPA_PMK_NAME_LEN);
 	os_get_time(&now);
 	WPA_PUT_LE32(f.timestamp, now.sec);
+	f.pairwise = host_to_le16(pairwise);
 	if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
 		     f.timestamp, frame.timestamp) < 0)
 		return;
@@ -1492,7 +1768,7 @@ void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr)
 
 	r1kh = wpa_auth->conf.r1kh_list;
 	while (r1kh) {
-		wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr);
+		wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr, r0->pairwise);
 		r1kh = r1kh->next;
 	}
 }
diff --git a/contrib/wpa/src/ap/wpa_auth_glue.c b/contrib/wpa/src/ap/wpa_auth_glue.c
new file mode 100644
index 000000000000..afa13a698bef
--- /dev/null
+++ b/contrib/wpa/src/ap/wpa_auth_glue.c
@@ -0,0 +1,545 @@
+/*
+ * hostapd / WPA authenticator glue code
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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 "common/ieee802_11_defs.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "eapol_auth/eapol_auth_sm_i.h"
+#include "eap_server/eap.h"
+#include "l2_packet/l2_packet.h"
+#include "drivers/driver.h"
+#include "hostapd.h"
+#include "ieee802_1x.h"
+#include "preauth_auth.h"
+#include "sta_info.h"
+#include "tkip_countermeasures.h"
+#include "ap_drv_ops.h"
+#include "ap_config.h"
+#include "wpa_auth.h"
+
+
+#ifdef CONFIG_IEEE80211R
+static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
+				size_t len);
+#endif /* CONFIG_IEEE80211R */
+
+
+static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
+				  struct wpa_auth_config *wconf)
+{
+	wconf->wpa = conf->wpa;
+	wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
+	wconf->wpa_pairwise = conf->wpa_pairwise;
+	wconf->wpa_group = conf->wpa_group;
+	wconf->wpa_group_rekey = conf->wpa_group_rekey;
+	wconf->wpa_strict_rekey = conf->wpa_strict_rekey;
+	wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey;
+	wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey;
+	wconf->rsn_pairwise = conf->rsn_pairwise;
+	wconf->rsn_preauth = conf->rsn_preauth;
+	wconf->eapol_version = conf->eapol_version;
+	wconf->peerkey = conf->peerkey;
+	wconf->wmm_enabled = conf->wmm_enabled;
+	wconf->wmm_uapsd = conf->wmm_uapsd;
+	wconf->okc = conf->okc;
+#ifdef CONFIG_IEEE80211W
+	wconf->ieee80211w = conf->ieee80211w;
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_IEEE80211R
+	wconf->ssid_len = conf->ssid.ssid_len;
+	if (wconf->ssid_len > SSID_LEN)
+		wconf->ssid_len = SSID_LEN;
+	os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len);
+	os_memcpy(wconf->mobility_domain, conf->mobility_domain,
+		  MOBILITY_DOMAIN_ID_LEN);
+	if (conf->nas_identifier &&
+	    os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) {
+		wconf->r0_key_holder_len = os_strlen(conf->nas_identifier);
+		os_memcpy(wconf->r0_key_holder, conf->nas_identifier,
+			  wconf->r0_key_holder_len);
+	}
+	os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN);
+	wconf->r0_key_lifetime = conf->r0_key_lifetime;
+	wconf->reassociation_deadline = conf->reassociation_deadline;
+	wconf->r0kh_list = conf->r0kh_list;
+	wconf->r1kh_list = conf->r1kh_list;
+	wconf->pmk_r1_push = conf->pmk_r1_push;
+#endif /* CONFIG_IEEE80211R */
+}
+
+
+static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr,
+				    logger_level level, const char *txt)
+{
+#ifndef CONFIG_NO_HOSTAPD_LOGGER
+	struct hostapd_data *hapd = ctx;
+	int hlevel;
+
+	switch (level) {
+	case LOGGER_WARNING:
+		hlevel = HOSTAPD_LEVEL_WARNING;
+		break;
+	case LOGGER_INFO:
+		hlevel = HOSTAPD_LEVEL_INFO;
+		break;
+	case LOGGER_DEBUG:
+	default:
+		hlevel = HOSTAPD_LEVEL_DEBUG;
+		break;
+	}
+
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt);
+#endif /* CONFIG_NO_HOSTAPD_LOGGER */
+}
+
+
+static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr,
+					u16 reason)
+{
+	struct hostapd_data *hapd = ctx;
+	wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: "
+		   "STA " MACSTR " reason %d",
+		   __func__, MAC2STR(addr), reason);
+	ap_sta_disconnect(hapd, NULL, addr, reason);
+}
+
+
+static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
+{
+	struct hostapd_data *hapd = ctx;
+	michael_mic_failure(hapd, addr, 0);
+}
+
+
+static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr,
+				       wpa_eapol_variable var, int value)
+{
+	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta = ap_get_sta(hapd, addr);
+	if (sta == NULL)
+		return;
+	switch (var) {
+	case WPA_EAPOL_portEnabled:
+		ieee802_1x_notify_port_enabled(sta->eapol_sm, value);
+		break;
+	case WPA_EAPOL_portValid:
+		ieee802_1x_notify_port_valid(sta->eapol_sm, value);
+		break;
+	case WPA_EAPOL_authorized:
+		ieee802_1x_set_sta_authorized(hapd, sta, value);
+		break;
+	case WPA_EAPOL_portControl_Auto:
+		if (sta->eapol_sm)
+			sta->eapol_sm->portControl = Auto;
+		break;
+	case WPA_EAPOL_keyRun:
+		if (sta->eapol_sm)
+			sta->eapol_sm->keyRun = value ? TRUE : FALSE;
+		break;
+	case WPA_EAPOL_keyAvailable:
+		if (sta->eapol_sm)
+			sta->eapol_sm->eap_if->eapKeyAvailable =
+				value ? TRUE : FALSE;
+		break;
+	case WPA_EAPOL_keyDone:
+		if (sta->eapol_sm)
+			sta->eapol_sm->keyDone = value ? TRUE : FALSE;
+		break;
+	case WPA_EAPOL_inc_EapolFramesTx:
+		if (sta->eapol_sm)
+			sta->eapol_sm->dot1xAuthEapolFramesTx++;
+		break;
+	}
+}
+
+
+static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr,
+				      wpa_eapol_variable var)
+{
+	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta = ap_get_sta(hapd, addr);
+	if (sta == NULL || sta->eapol_sm == NULL)
+		return -1;
+	switch (var) {
+	case WPA_EAPOL_keyRun:
+		return sta->eapol_sm->keyRun;
+	case WPA_EAPOL_keyAvailable:
+		return sta->eapol_sm->eap_if->eapKeyAvailable;
+	default:
+		return -1;
+	}
+}
+
+
+static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
+					   const u8 *prev_psk)
+{
+	struct hostapd_data *hapd = ctx;
+	return hostapd_get_psk(hapd->conf, addr, prev_psk);
+}
+
+
+static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk,
+				    size_t *len)
+{
+	struct hostapd_data *hapd = ctx;
+	const u8 *key;
+	size_t keylen;
+	struct sta_info *sta;
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta == NULL)
+		return -1;
+
+	key = ieee802_1x_get_key(sta->eapol_sm, &keylen);
+	if (key == NULL)
+		return -1;
+
+	if (keylen > *len)
+		keylen = *len;
+	os_memcpy(msk, key, keylen);
+	*len = keylen;
+
+	return 0;
+}
+
+
+static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
+				    const u8 *addr, int idx, u8 *key,
+				    size_t key_len)
+{
+	struct hostapd_data *hapd = ctx;
+	const char *ifname = hapd->conf->iface;
+
+	if (vlan_id > 0) {
+		ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id);
+		if (ifname == NULL)
+			return -1;
+	}
+
+	return hapd->drv.set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
+				 key, key_len);
+}
+
+
+static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx,
+				       u8 *seq)
+{
+	struct hostapd_data *hapd = ctx;
+	return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq);
+}
+
+
+static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
+				       const u8 *data, size_t data_len,
+				       int encrypt)
+{
+	struct hostapd_data *hapd = ctx;
+	return hapd->drv.send_eapol(hapd, addr, data, data_len, encrypt);
+}
+
+
+static int hostapd_wpa_auth_for_each_sta(
+	void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx),
+	void *cb_ctx)
+{
+	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta;
+
+	for (sta = hapd->sta_list; sta; sta = sta->next) {
+		if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx))
+			return 1;
+	}
+	return 0;
+}
+
+
+struct wpa_auth_iface_iter_data {
+	int (*cb)(struct wpa_authenticator *sm, void *ctx);
+	void *cb_ctx;
+};
+
+static int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx)
+{
+	struct wpa_auth_iface_iter_data *data = ctx;
+	size_t i;
+	for (i = 0; i < iface->num_bss; i++) {
+		if (iface->bss[i]->wpa_auth &&
+		    data->cb(iface->bss[i]->wpa_auth, data->cb_ctx))
+			return 1;
+	}
+	return 0;
+}
+
+
+static int hostapd_wpa_auth_for_each_auth(
+	void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx),
+	void *cb_ctx)
+{
+	struct hostapd_data *hapd = ctx;
+	struct wpa_auth_iface_iter_data data;
+	if (hapd->iface->for_each_interface == NULL)
+		return -1;
+	data.cb = cb;
+	data.cb_ctx = cb_ctx;
+	return hapd->iface->for_each_interface(hapd->iface->interfaces,
+					       wpa_auth_iface_iter, &data);
+}
+
+
+#ifdef CONFIG_IEEE80211R
+
+struct wpa_auth_ft_iface_iter_data {
+	struct hostapd_data *src_hapd;
+	const u8 *dst;
+	const u8 *data;
+	size_t data_len;
+};
+
+
+static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx)
+{
+	struct wpa_auth_ft_iface_iter_data *idata = ctx;
+	struct hostapd_data *hapd;
+	size_t j;
+
+	for (j = 0; j < iface->num_bss; j++) {
+		hapd = iface->bss[j];
+		if (hapd == idata->src_hapd)
+			continue;
+		if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) {
+			wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to "
+				   "locally managed BSS " MACSTR "@%s -> "
+				   MACSTR "@%s",
+				   MAC2STR(idata->src_hapd->own_addr),
+				   idata->src_hapd->conf->iface,
+				   MAC2STR(hapd->own_addr), hapd->conf->iface);
+			hostapd_rrb_receive(hapd, idata->src_hapd->own_addr,
+					    idata->data, idata->data_len);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_IEEE80211R */
+
+
+static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
+				       const u8 *data, size_t data_len)
+{
+	struct hostapd_data *hapd = ctx;
+
+#ifdef CONFIG_IEEE80211R
+	if (proto == ETH_P_RRB && hapd->iface->for_each_interface) {
+		int res;
+		struct wpa_auth_ft_iface_iter_data idata;
+		idata.src_hapd = hapd;
+		idata.dst = dst;
+		idata.data = data;
+		idata.data_len = data_len;
+		res = hapd->iface->for_each_interface(hapd->iface->interfaces,
+						      hostapd_wpa_auth_ft_iter,
+						      &idata);
+		if (res == 1)
+			return data_len;
+	}
+#endif /* CONFIG_IEEE80211R */
+
+	if (hapd->driver && hapd->driver->send_ether)
+		return hapd->driver->send_ether(hapd->drv_priv, dst,
+						hapd->own_addr, proto,
+						data, data_len);
+	if (hapd->l2 == NULL)
+		return -1;
+	return l2_packet_send(hapd->l2, dst, proto, data, data_len);
+}
+
+
+#ifdef CONFIG_IEEE80211R
+
+static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
+					   const u8 *data, size_t data_len)
+{
+	struct hostapd_data *hapd = ctx;
+	int res;
+	struct ieee80211_mgmt *m;
+	size_t mlen;
+	struct sta_info *sta;
+
+	sta = ap_get_sta(hapd, dst);
+	if (sta == NULL || sta->wpa_sm == NULL)
+		return -1;
+
+	m = os_zalloc(sizeof(*m) + data_len);
+	if (m == NULL)
+		return -1;
+	mlen = ((u8 *) &m->u - (u8 *) m) + data_len;
+	m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+					WLAN_FC_STYPE_ACTION);
+	os_memcpy(m->da, dst, ETH_ALEN);
+	os_memcpy(m->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
+	os_memcpy(&m->u, data, data_len);
+
+	res = hapd->drv.send_mgmt_frame(hapd, (u8 *) m, mlen);
+	os_free(m);
+	return res;
+}
+
+
+static struct wpa_state_machine *
+hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
+{
+	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta;
+
+	sta = ap_sta_add(hapd, sta_addr);
+	if (sta == NULL)
+		return NULL;
+	if (sta->wpa_sm) {
+		sta->auth_alg = WLAN_AUTH_FT;
+		return sta->wpa_sm;
+	}
+
+	sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr);
+	if (sta->wpa_sm == NULL) {
+		ap_free_sta(hapd, sta);
+		return NULL;
+	}
+	sta->auth_alg = WLAN_AUTH_FT;
+
+	return sta->wpa_sm;
+}
+
+
+static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
+				size_t len)
+{
+	struct hostapd_data *hapd = ctx;
+	wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len);
+}
+
+#endif /* CONFIG_IEEE80211R */
+
+
+int hostapd_setup_wpa(struct hostapd_data *hapd)
+{
+	struct wpa_auth_config _conf;
+	struct wpa_auth_callbacks cb;
+	const u8 *wpa_ie;
+	size_t wpa_ie_len;
+
+	hostapd_wpa_auth_conf(hapd->conf, &_conf);
+	os_memset(&cb, 0, sizeof(cb));
+	cb.ctx = hapd;
+	cb.logger = hostapd_wpa_auth_logger;
+	cb.disconnect = hostapd_wpa_auth_disconnect;
+	cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report;
+	cb.set_eapol = hostapd_wpa_auth_set_eapol;
+	cb.get_eapol = hostapd_wpa_auth_get_eapol;
+	cb.get_psk = hostapd_wpa_auth_get_psk;
+	cb.get_msk = hostapd_wpa_auth_get_msk;
+	cb.set_key = hostapd_wpa_auth_set_key;
+	cb.get_seqnum = hostapd_wpa_auth_get_seqnum;
+	cb.send_eapol = hostapd_wpa_auth_send_eapol;
+	cb.for_each_sta = hostapd_wpa_auth_for_each_sta;
+	cb.for_each_auth = hostapd_wpa_auth_for_each_auth;
+	cb.send_ether = hostapd_wpa_auth_send_ether;
+#ifdef CONFIG_IEEE80211R
+	cb.send_ft_action = hostapd_wpa_auth_send_ft_action;
+	cb.add_sta = hostapd_wpa_auth_add_sta;
+#endif /* CONFIG_IEEE80211R */
+	hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb);
+	if (hapd->wpa_auth == NULL) {
+		wpa_printf(MSG_ERROR, "WPA initialization failed.");
+		return -1;
+	}
+
+	if (hostapd_set_privacy(hapd, 1)) {
+		wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked "
+			   "for interface %s", hapd->conf->iface);
+		return -1;
+	}
+
+	wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
+	if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) {
+		wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
+			   "the kernel driver.");
+		return -1;
+	}
+
+	if (rsn_preauth_iface_init(hapd)) {
+		wpa_printf(MSG_ERROR, "Initialization of RSN "
+			   "pre-authentication failed.");
+		return -1;
+	}
+
+#ifdef CONFIG_IEEE80211R
+	if (!hostapd_drv_none(hapd)) {
+		hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ?
+					  hapd->conf->bridge :
+					  hapd->conf->iface, NULL, ETH_P_RRB,
+					  hostapd_rrb_receive, hapd, 0);
+		if (hapd->l2 == NULL &&
+		    (hapd->driver == NULL ||
+		     hapd->driver->send_ether == NULL)) {
+			wpa_printf(MSG_ERROR, "Failed to open l2_packet "
+				   "interface");
+			return -1;
+		}
+	}
+#endif /* CONFIG_IEEE80211R */
+
+	return 0;
+
+}
+
+
+void hostapd_reconfig_wpa(struct hostapd_data *hapd)
+{
+	struct wpa_auth_config wpa_auth_conf;
+	hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf);
+	wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf);
+}
+
+
+void hostapd_deinit_wpa(struct hostapd_data *hapd)
+{
+	rsn_preauth_iface_deinit(hapd);
+	if (hapd->wpa_auth) {
+		wpa_deinit(hapd->wpa_auth);
+		hapd->wpa_auth = NULL;
+
+		if (hostapd_set_privacy(hapd, 0)) {
+			wpa_printf(MSG_DEBUG, "Could not disable "
+				   "PrivacyInvoked for interface %s",
+				   hapd->conf->iface);
+		}
+
+		if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) {
+			wpa_printf(MSG_DEBUG, "Could not remove generic "
+				   "information element from interface %s",
+				   hapd->conf->iface);
+		}
+	}
+	ieee802_1x_deinit(hapd);
+
+#ifdef CONFIG_IEEE80211R
+	l2_packet_deinit(hapd->l2);
+#endif /* CONFIG_IEEE80211R */
+}
diff --git a/contrib/wpa/src/ap/wpa_auth_glue.h b/contrib/wpa/src/ap/wpa_auth_glue.h
new file mode 100644
index 000000000000..79d7e05c4055
--- /dev/null
+++ b/contrib/wpa/src/ap/wpa_auth_glue.h
@@ -0,0 +1,22 @@
+/*
+ * hostapd / WPA authenticator glue code
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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 WPA_AUTH_GLUE_H
+#define WPA_AUTH_GLUE_H
+
+int hostapd_setup_wpa(struct hostapd_data *hapd);
+void hostapd_reconfig_wpa(struct hostapd_data *hapd);
+void hostapd_deinit_wpa(struct hostapd_data *hapd);
+
+#endif /* WPA_AUTH_GLUE_H */
diff --git a/contrib/wpa/hostapd/wpa_auth_i.h b/contrib/wpa/src/ap/wpa_auth_i.h
similarity index 94%
rename from contrib/wpa/hostapd/wpa_auth_i.h
rename to contrib/wpa/src/ap/wpa_auth_i.h
index 925d3ee459ce..b69129ff44cf 100644
--- a/contrib/wpa/hostapd/wpa_auth_i.h
+++ b/contrib/wpa/src/ap/wpa_auth_i.h
@@ -116,6 +116,9 @@ struct wpa_state_machine {
 					   * Request */
 	u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */
 	size_t r0kh_id_len;
+	u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key
+					       * message 2/4 */
+	u8 *assoc_resp_ftie;
 #endif /* CONFIG_IEEE80211R */
 };
 
@@ -212,10 +215,16 @@ void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
 
 #ifdef CONFIG_IEEE80211R
 int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len);
+int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
+		   size_t r0kh_id_len,
+		   const u8 *anonce, const u8 *snonce,
+		   u8 *buf, size_t len, const u8 *subelem,
+		   size_t subelem_len);
 int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
 			   struct wpa_ptk *ptk, size_t ptk_len);
 struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
 void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
+void wpa_ft_install_ptk(struct wpa_state_machine *sm);
 #endif /* CONFIG_IEEE80211R */
 
 #endif /* WPA_AUTH_I_H */
diff --git a/contrib/wpa/hostapd/wpa_auth_ie.c b/contrib/wpa/src/ap/wpa_auth_ie.c
similarity index 97%
rename from contrib/wpa/hostapd/wpa_auth_ie.c
rename to contrib/wpa/src/ap/wpa_auth_ie.c
index 7e0163528455..f8a1804c9f71 100644
--- a/contrib/wpa/hostapd/wpa_auth_ie.c
+++ b/contrib/wpa/src/ap/wpa_auth_ie.c
@@ -12,14 +12,15 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#include "common.h"
-#include "config.h"
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "ap_config.h"
 #include "ieee802_11.h"
-#include "eapol_sm.h"
-#include "wpa.h"
-#include "pmksa_cache.h"
+#include "wpa_auth.h"
+#include "pmksa_cache_auth.h"
 #include "wpa_auth_ie.h"
 #include "wpa_auth_i.h"
 
@@ -220,9 +221,9 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
 		capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
 	}
 #ifdef CONFIG_IEEE80211W
-	if (conf->ieee80211w != WPA_NO_IEEE80211W) {
+	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		capab |= WPA_CAPABILITY_MFPC;
-		if (conf->ieee80211w == IEEE80211W_REQUIRED)
+		if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
 			capab |= WPA_CAPABILITY_MFPR;
 	}
 #endif /* CONFIG_IEEE80211W */
@@ -240,7 +241,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
 	}
 
 #ifdef CONFIG_IEEE80211W
-	if (conf->ieee80211w != WPA_NO_IEEE80211W) {
+	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		if (pos + 2 + 4 > buf + len)
 			return -1;
 		if (pmkid == NULL) {
@@ -612,7 +613,7 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
 	}
 
 #ifdef CONFIG_IEEE80211W
-	if (wpa_auth->conf.ieee80211w == WPA_IEEE80211W_REQUIRED) {
+	if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
 		if (!(data.capabilities & WPA_CAPABILITY_MFPC)) {
 			wpa_printf(MSG_DEBUG, "Management frame protection "
 				   "required, but client did not enable it");
@@ -632,7 +633,7 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
 		}
 	}
 
-	if (wpa_auth->conf.ieee80211w == WPA_NO_IEEE80211W ||
+	if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
 	    !(data.capabilities & WPA_CAPABILITY_MFPC))
 		sm->mgmt_frame_prot = 0;
 	else
@@ -670,8 +671,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
 	for (i = 0; i < data.num_pmkid; i++) {
 		wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID",
 			    &data.pmkid[i * PMKID_LEN], PMKID_LEN);
-		sm->pmksa = pmksa_cache_get(wpa_auth->pmksa, sm->addr,
-					    &data.pmkid[i * PMKID_LEN]);
+		sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr,
+						 &data.pmkid[i * PMKID_LEN]);
 		if (sm->pmksa) {
 			pmkid = sm->pmksa->pmkid;
 			break;
@@ -839,6 +840,9 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
 		} else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
 			ie->mdie = pos;
 			ie->mdie_len = pos[1] + 2;
+		} else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
+			ie->ftie = pos;
+			ie->ftie_len = pos[1] + 2;
 #endif /* CONFIG_IEEE80211R */
 		} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
 			ret = wpa_parse_generic(pos, end, ie);
diff --git a/contrib/wpa/hostapd/wpa_auth_ie.h b/contrib/wpa/src/ap/wpa_auth_ie.h
similarity index 97%
rename from contrib/wpa/hostapd/wpa_auth_ie.h
rename to contrib/wpa/src/ap/wpa_auth_ie.h
index 9968d2d92a16..61d4cb4075fe 100644
--- a/contrib/wpa/hostapd/wpa_auth_ie.h
+++ b/contrib/wpa/src/ap/wpa_auth_ie.h
@@ -42,6 +42,8 @@ struct wpa_eapol_ie_parse {
 #ifdef CONFIG_IEEE80211R
 	const u8 *mdie;
 	size_t mdie_len;
+	const u8 *ftie;
+	size_t ftie_len;
 #endif /* CONFIG_IEEE80211R */
 };
 
diff --git a/contrib/wpa/hostapd/wps_hostapd.c b/contrib/wpa/src/ap/wps_hostapd.c
similarity index 69%
rename from contrib/wpa/hostapd/wps_hostapd.c
rename to contrib/wpa/src/ap/wps_hostapd.c
index 818767ef46fa..a6ffd4d0db0b 100644
--- a/contrib/wpa/hostapd/wps_hostapd.c
+++ b/contrib/wpa/src/ap/wps_hostapd.c
@@ -1,6 +1,6 @@
 /*
  * hostapd / WPS integration
- * Copyright (c) 2008, Jouni Malinen 
+ * Copyright (c) 2008-2010, Jouni Malinen 
  *
  * 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
@@ -12,19 +12,24 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#include "hostapd.h"
-#include "driver.h"
-#include "eloop.h"
-#include "uuid.h"
-#include "wpa_ctrl.h"
-#include "ieee802_11_defs.h"
-#include "sta_info.h"
-#include "eapol_sm.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/uuid.h"
+#include "crypto/dh_groups.h"
+#include "common/wpa_ctrl.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "eapol_auth/eapol_auth_sm_i.h"
 #include "wps/wps.h"
 #include "wps/wps_defs.h"
 #include "wps/wps_dev_attr.h"
+#include "hostapd.h"
+#include "ap_config.h"
+#include "beacon.h"
+#include "sta_info.h"
 #include "wps_hostapd.h"
 
 
@@ -35,6 +40,10 @@ static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
 static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd);
 #endif /* CONFIG_WPS_UPNP */
 
+static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
+				    const u8 *ie, size_t ie_len);
+static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
+
 
 static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk,
 				  size_t psk_len)
@@ -83,46 +92,16 @@ static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk,
 }
 
 
-static int hostapd_wps_set_ie_cb(void *ctx, const u8 *beacon_ie,
-				 size_t beacon_ie_len, const u8 *probe_resp_ie,
-				 size_t probe_resp_ie_len)
+static int hostapd_wps_set_ie_cb(void *ctx, struct wpabuf *beacon_ie,
+				 struct wpabuf *probe_resp_ie)
 {
 	struct hostapd_data *hapd = ctx;
-
-	os_free(hapd->wps_beacon_ie);
-	if (beacon_ie_len == 0) {
-		hapd->wps_beacon_ie = NULL;
-		hapd->wps_beacon_ie_len = 0;
-	} else {
-		hapd->wps_beacon_ie = os_malloc(beacon_ie_len);
-		if (hapd->wps_beacon_ie == NULL) {
-			hapd->wps_beacon_ie_len = 0;
-			return -1;
-		}
-		os_memcpy(hapd->wps_beacon_ie, beacon_ie, beacon_ie_len);
-		hapd->wps_beacon_ie_len = beacon_ie_len;
-	}
-	hostapd_set_wps_beacon_ie(hapd, hapd->wps_beacon_ie,
-				  hapd->wps_beacon_ie_len);
-
-	os_free(hapd->wps_probe_resp_ie);
-	if (probe_resp_ie_len == 0) {
-		hapd->wps_probe_resp_ie = NULL;
-		hapd->wps_probe_resp_ie_len = 0;
-	} else {
-		hapd->wps_probe_resp_ie = os_malloc(probe_resp_ie_len);
-		if (hapd->wps_probe_resp_ie == NULL) {
-			hapd->wps_probe_resp_ie_len = 0;
-			return -1;
-		}
-		os_memcpy(hapd->wps_probe_resp_ie, probe_resp_ie,
-			  probe_resp_ie_len);
-		hapd->wps_probe_resp_ie_len = probe_resp_ie_len;
-	}
-	hostapd_set_wps_probe_resp_ie(hapd, hapd->wps_probe_resp_ie,
-				      hapd->wps_probe_resp_ie_len);
-
-	return 0;
+	wpabuf_free(hapd->wps_beacon_ie);
+	hapd->wps_beacon_ie = beacon_ie;
+	wpabuf_free(hapd->wps_probe_resp_ie);
+	hapd->wps_probe_resp_ie = probe_resp_ie;
+	ieee802_11_set_beacon(hapd);
+	return hapd->drv.set_ap_wps_ie(hapd);
 }
 
 
@@ -132,17 +111,19 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
 	struct hostapd_data *hapd = ctx;
 	char uuid[40], txt[400];
 	int len;
+	char devtype[WPS_DEV_TYPE_BUFSIZE];
 	if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
 		return;
 	wpa_printf(MSG_DEBUG, "WPS: PIN needed for E-UUID %s", uuid);
 	len = os_snprintf(txt, sizeof(txt), WPS_EVENT_PIN_NEEDED
-			  "%s " MACSTR " [%s|%s|%s|%s|%s|%d-%08X-%d]",
+			  "%s " MACSTR " [%s|%s|%s|%s|%s|%s]",
 			  uuid, MAC2STR(dev->mac_addr), dev->device_name,
 			  dev->manufacturer, dev->model_name,
 			  dev->model_number, dev->serial_number,
-			  dev->categ, dev->oui, dev->sub_categ);
+			  wps_dev_type_bin2str(dev->pri_dev_type, devtype,
+					       sizeof(devtype)));
 	if (len > 0 && len < (int) sizeof(txt))
-		wpa_msg(hapd, MSG_INFO, "%s", txt);
+		wpa_msg(hapd->msg_ctx, MSG_INFO, "%s", txt);
 
 	if (hapd->conf->wps_pin_requests) {
 		FILE *f;
@@ -152,11 +133,12 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
 			return;
 		os_get_time(&t);
 		fprintf(f, "%ld\t%s\t" MACSTR "\t%s\t%s\t%s\t%s\t%s"
-			"\t%d-%08X-%d\n",
+			"\t%s\n",
 			t.sec, uuid, MAC2STR(dev->mac_addr), dev->device_name,
 			dev->manufacturer, dev->model_name, dev->model_number,
 			dev->serial_number,
-			dev->categ, dev->oui, dev->sub_categ);
+			wps_dev_type_bin2str(dev->pri_dev_type, devtype,
+					     sizeof(devtype)));
 		fclose(f);
 	}
 }
@@ -169,8 +151,34 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
 	char uuid[40];
 	if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
 		return;
-	wpa_msg(hapd, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s",
+	wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s",
 		MAC2STR(mac_addr), uuid);
+	if (hapd->wps_reg_success_cb)
+		hapd->wps_reg_success_cb(hapd->wps_reg_success_cb_ctx,
+					 mac_addr, uuid_e);
+}
+
+
+static void hostapd_wps_enrollee_seen_cb(void *ctx, const u8 *addr,
+					 const u8 *uuid_e,
+					 const u8 *pri_dev_type,
+					 u16 config_methods,
+					 u16 dev_password_id, u8 request_type,
+					 const char *dev_name)
+{
+	struct hostapd_data *hapd = ctx;
+	char uuid[40];
+	char devtype[WPS_DEV_TYPE_BUFSIZE];
+	if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
+		return;
+	if (dev_name == NULL)
+		dev_name = "";
+	wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, WPS_EVENT_ENROLLEE_SEEN MACSTR
+		     " %s %s 0x%x %u %u [%s]",
+		     MAC2STR(addr), uuid,
+		     wps_dev_type_bin2str(pri_dev_type, devtype,
+					  sizeof(devtype)),
+		     config_methods, dev_password_id, request_type, dev_name);
 }
 
 
@@ -185,7 +193,7 @@ static void wps_reload_config(void *eloop_data, void *user_ctx)
 	struct hostapd_iface *iface = eloop_data;
 
 	wpa_printf(MSG_DEBUG, "WPS: Reload configuration data");
-	if (hostapd_reload_config(iface) < 0) {
+	if (iface->reload_config(iface) < 0) {
 		wpa_printf(MSG_WARNING, "WPS: Failed to reload the updated "
 			   "configuration");
 	}
@@ -223,12 +231,12 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
 		if (_buf) {
 			wpa_snprintf_hex(_buf, blen,
 					 cred->cred_attr, cred->cred_attr_len);
-			wpa_msg(hapd, MSG_INFO, "%s%s",
+			wpa_msg(hapd->msg_ctx, MSG_INFO, "%s%s",
 				WPS_EVENT_NEW_AP_SETTINGS, _buf);
 			os_free(_buf);
 		}
 	} else
-		wpa_msg(hapd, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS);
+		wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS);
 
 	if (hapd->conf->wps_cred_processing == 1)
 		return 0;
@@ -414,44 +422,58 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
 }
 
 
+static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
+{
+	struct hostapd_data *hapd = eloop_data;
+
+	if (hapd->conf->ap_setup_locked)
+		return;
+
+	wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN");
+	wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
+	hapd->wps->ap_setup_locked = 0;
+	wps_registrar_update_ie(hapd->wps->registrar);
+}
+
+
 static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
 				  struct wps_event_pwd_auth_fail *data)
 {
-	FILE *f;
-
-	if (!data->enrollee)
+	if (!data->enrollee || hapd->conf->ap_pin == NULL)
 		return;
 
 	/*
 	 * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup
-	 * if this happens multiple times.
+	 * for some time if this happens multiple times to slow down brute
+	 * force attacks.
 	 */
 	hapd->ap_pin_failures++;
-	if (hapd->ap_pin_failures < 4)
+	wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u",
+		   hapd->ap_pin_failures);
+	if (hapd->ap_pin_failures < 3)
 		return;
 
-	wpa_msg(hapd, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
+	wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
 	hapd->wps->ap_setup_locked = 1;
 
 	wps_registrar_update_ie(hapd->wps->registrar);
 
-	if (hapd->conf->wps_cred_processing == 1)
-		return;
+	if (!hapd->conf->ap_setup_locked) {
+		if (hapd->ap_pin_lockout_time == 0)
+			hapd->ap_pin_lockout_time = 60;
+		else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 &&
+			 (hapd->ap_pin_failures % 3) == 0)
+			hapd->ap_pin_lockout_time *= 2;
 
-	f = fopen(hapd->iface->config_fname, "a");
-	if (f == NULL) {
-		wpa_printf(MSG_WARNING, "WPS: Could not append to the current "
-			   "configuration file");
-		return;
+		wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN for %u seconds",
+			   hapd->ap_pin_lockout_time);
+		eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
+		eloop_register_timeout(hapd->ap_pin_lockout_time, 0,
+				       hostapd_wps_reenable_ap_pin, hapd,
+				       NULL);
 	}
 
-	fprintf(f, "# WPS AP Setup Locked based on possible attack\n");
-	fprintf(f, "ap_setup_locked=1\n");
-	fclose(f);
-
-	/* TODO: dualband AP may need to update multiple configuration files */
-
-	wpa_printf(MSG_DEBUG, "WPS: AP configuration updated");
+	/* TODO: dualband AP may need to update other interfaces */
 }
 
 
@@ -467,15 +489,13 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
 
 static void hostapd_wps_clear_ies(struct hostapd_data *hapd)
 {
-	os_free(hapd->wps_beacon_ie);
+	wpabuf_free(hapd->wps_beacon_ie);
 	hapd->wps_beacon_ie = NULL;
-	hapd->wps_beacon_ie_len = 0;
-	hostapd_set_wps_beacon_ie(hapd, NULL, 0);
 
-	os_free(hapd->wps_probe_resp_ie);
+	wpabuf_free(hapd->wps_probe_resp_ie);
 	hapd->wps_probe_resp_ie = NULL;
-	hapd->wps_probe_resp_ie_len = 0;
-	hostapd_set_wps_probe_resp_ie(hapd, NULL, 0);
+
+	hapd->drv.set_ap_wps_ie(hapd);
 }
 
 
@@ -521,43 +541,14 @@ int hostapd_init_wps(struct hostapd_data *hapd,
 		os_strdup(hapd->conf->model_number) : NULL;
 	wps->dev.serial_number = hapd->conf->serial_number ?
 		os_strdup(hapd->conf->serial_number) : NULL;
-	if (hapd->conf->config_methods) {
-		char *m = hapd->conf->config_methods;
-		if (os_strstr(m, "label"))
-			wps->config_methods |= WPS_CONFIG_LABEL;
-		if (os_strstr(m, "display"))
-			wps->config_methods |= WPS_CONFIG_DISPLAY;
-		if (os_strstr(m, "push_button"))
-			wps->config_methods |= WPS_CONFIG_PUSHBUTTON;
-		if (os_strstr(m, "keypad"))
-			wps->config_methods |= WPS_CONFIG_KEYPAD;
-	}
-	if (hapd->conf->device_type) {
-		char *pos;
-		u8 oui[4];
-		/* -- */
-		wps->dev.categ = atoi(hapd->conf->device_type);
-		pos = os_strchr(hapd->conf->device_type, '-');
-		if (pos == NULL) {
-			wpa_printf(MSG_ERROR, "WPS: Invalid device_type");
-			os_free(wps);
-			return -1;
-		}
-		pos++;
-		if (hexstr2bin(pos, oui, 4)) {
-			wpa_printf(MSG_ERROR, "WPS: Invalid device_type OUI");
-			os_free(wps);
-			return -1;
-		}
-		wps->dev.oui = WPA_GET_BE32(oui);
-		pos = os_strchr(pos, '-');
-		if (pos == NULL) {
-			wpa_printf(MSG_ERROR, "WPS: Invalid device_type");
-			os_free(wps);
-			return -1;
-		}
-		pos++;
-		wps->dev.sub_categ = atoi(pos);
+	wps->config_methods =
+		wps_config_methods_str2bin(hapd->conf->config_methods);
+	if (hapd->conf->device_type &&
+	    wps_dev_type_str2bin(hapd->conf->device_type,
+				 wps->dev.pri_dev_type) < 0) {
+		wpa_printf(MSG_ERROR, "WPS: Invalid device_type");
+		os_free(wps);
+		return -1;
 	}
 	wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version);
 	wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
@@ -629,6 +620,11 @@ int hostapd_init_wps(struct hostapd_data *hapd,
 		wps->network_key_len = conf->ssid.wep.len[0];
 	}
 
+	if (conf->ssid.wpa_psk) {
+		os_memcpy(wps->psk, conf->ssid.wpa_psk->psk, PMK_LEN);
+		wps->psk_set = 1;
+	}
+
 	if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) {
 		/* Override parameters to enable security by default */
 		wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
@@ -642,6 +638,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
 	cfg.set_ie_cb = hostapd_wps_set_ie_cb;
 	cfg.pin_needed_cb = hostapd_wps_pin_needed_cb;
 	cfg.reg_success_cb = hostapd_wps_reg_success_cb;
+	cfg.enrollee_seen_cb = hostapd_wps_enrollee_seen_cb;
 	cfg.cb_ctx = hapd;
 	cfg.skip_cred_build = conf->skip_cred_build;
 	cfg.extra_cred = conf->extra_cred;
@@ -675,6 +672,8 @@ int hostapd_init_wps(struct hostapd_data *hapd,
 	}
 #endif /* CONFIG_WPS_UPNP */
 
+	hostapd_register_probereq_cb(hapd, hostapd_wps_probe_req_rx, hapd);
+
 	hapd->wps = wps;
 
 	return 0;
@@ -683,6 +682,8 @@ int hostapd_init_wps(struct hostapd_data *hapd,
 
 void hostapd_deinit_wps(struct hostapd_data *hapd)
 {
+	eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
+	eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
 	if (hapd->wps == NULL)
 		return;
 #ifdef CONFIG_WPS_UPNP
@@ -691,6 +692,10 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
 	wps_registrar_deinit(hapd->wps->registrar);
 	os_free(hapd->wps->network_key);
 	wps_device_data_free(&hapd->wps->dev);
+	wpabuf_free(hapd->wps->dh_pubkey);
+	wpabuf_free(hapd->wps->dh_privkey);
+	wpabuf_free(hapd->wps->oob_conf.pubkey_hash);
+	wpabuf_free(hapd->wps->oob_conf.dev_password);
 	wps_free_pending_msgs(hapd->wps->upnp_msgs);
 	os_free(hapd->wps);
 	hapd->wps = NULL;
@@ -698,6 +703,17 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
 }
 
 
+void hostapd_update_wps(struct hostapd_data *hapd)
+{
+	if (hapd->wps == NULL)
+		return;
+	if (hapd->conf->wps_state)
+		wps_registrar_update_ie(hapd->wps->registrar);
+	else
+		hostapd_deinit_wps(hapd);
+}
+
+
 int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
 			const char *pin, int timeout)
 {
@@ -724,47 +740,85 @@ int hostapd_wps_button_pushed(struct hostapd_data *hapd)
 }
 
 
-void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr,
-			      const u8 *ie, size_t ie_len)
+#ifdef CONFIG_WPS_OOB
+int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
+			  char *path, char *method, char *name)
 {
+	struct wps_context *wps = hapd->wps;
+	struct oob_device_data *oob_dev;
+
+	oob_dev = wps_get_oob_device(device_type);
+	if (oob_dev == NULL)
+		return -1;
+	oob_dev->device_path = path;
+	oob_dev->device_name = name;
+	wps->oob_conf.oob_method = wps_get_oob_method(method);
+
+	if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) {
+		/*
+		 * Use pre-configured DH keys in order to be able to write the
+		 * key hash into the OOB file.
+		 */
+		wpabuf_free(wps->dh_pubkey);
+		wpabuf_free(wps->dh_privkey);
+		wps->dh_privkey = NULL;
+		wps->dh_pubkey = dh_init(dh_groups_get(WPS_DH_GROUP),
+					 &wps->dh_privkey);
+		wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192);
+		if (wps->dh_pubkey == NULL) {
+			wpa_printf(MSG_ERROR, "WPS: Failed to initialize "
+				   "Diffie-Hellman handshake");
+			return -1;
+		}
+	}
+
+	if (wps_process_oob(wps, oob_dev, 1) < 0)
+		goto error;
+
+	if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ||
+	     wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) &&
+	    hostapd_wps_add_pin(hapd, "any",
+				wpabuf_head(wps->oob_conf.dev_password), 0) <
+	    0)
+		goto error;
+
+	return 0;
+
+error:
+	wpabuf_free(wps->dh_pubkey);
+	wps->dh_pubkey = NULL;
+	wpabuf_free(wps->dh_privkey);
+	wps->dh_privkey = NULL;
+	return -1;
+}
+#endif /* CONFIG_WPS_OOB */
+
+
+static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr,
+				    const u8 *ie, size_t ie_len)
+{
+	struct hostapd_data *hapd = ctx;
 	struct wpabuf *wps_ie;
-	const u8 *end, *pos, *wps;
+	struct ieee802_11_elems elems;
 
 	if (hapd->wps == NULL)
-		return;
+		return 0;
 
-	pos = ie;
-	end = ie + ie_len;
-	wps = NULL;
-
-	while (pos + 1 < end) {
-		if (pos + 2 + pos[1] > end)
-			return;
-		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
-		    WPA_GET_BE32(&pos[2]) == WPS_DEV_OUI_WFA) {
-			wps = pos;
-			break;
-		}
-		pos += 2 + pos[1];
+	if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
+		wpa_printf(MSG_DEBUG, "WPS: Could not parse ProbeReq from "
+			   MACSTR, MAC2STR(addr));
+		return 0;
 	}
 
-	if (wps == NULL)
-		return; /* No WPS IE in Probe Request */
+	if (elems.ssid && elems.ssid_len > 0 &&
+	    (elems.ssid_len != hapd->conf->ssid.ssid_len ||
+	     os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) !=
+	     0))
+		return 0; /* Not for us */
 
-	wps_ie = wpabuf_alloc(ie_len);
+	wps_ie = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
 	if (wps_ie == NULL)
-		return;
-
-	/* There may be multiple WPS IEs in the message, so need to concatenate
-	 * their WPS Data fields */
-	while (pos + 1 < end) {
-		if (pos + 2 + pos[1] > end)
-			break;
-		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
-		    WPA_GET_BE32(&pos[2]) == WPS_DEV_OUI_WFA)
-			wpabuf_put_data(wps_ie, pos + 6, pos[1] - 4);
-		pos += 2 + pos[1];
-	}
+		return 0;
 
 	if (wpabuf_len(wps_ie) > 0) {
 		wps_registrar_probe_req_rx(hapd->wps->registrar, addr, wps_ie);
@@ -778,112 +832,13 @@ void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr,
 	}
 
 	wpabuf_free(wps_ie);
+
+	return 0;
 }
 
 
 #ifdef CONFIG_WPS_UPNP
 
-static struct wpabuf *
-hostapd_rx_req_get_device_info(void *priv, struct upnp_wps_peer *peer)
-{
-	struct hostapd_data *hapd = priv;
-	struct wps_config cfg;
-	struct wps_data *wps;
-	enum wsc_op_code op_code;
-	struct wpabuf *m1;
-
-	/*
-	 * Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS
-	 * registration over UPnP with the AP acting as an Enrollee. It should
-	 * be noted that this is frequently used just to get the device data,
-	 * i.e., there may not be any intent to actually complete the
-	 * registration.
-	 */
-
-	if (peer->wps)
-		wps_deinit(peer->wps);
-
-	os_memset(&cfg, 0, sizeof(cfg));
-	cfg.wps = hapd->wps;
-	cfg.pin = (u8 *) hapd->conf->ap_pin;
-	cfg.pin_len = os_strlen(hapd->conf->ap_pin);
-	wps = wps_init(&cfg);
-	if (wps == NULL)
-		return NULL;
-
-	m1 = wps_get_msg(wps, &op_code);
-	if (m1 == NULL) {
-		wps_deinit(wps);
-		return NULL;
-	}
-
-	peer->wps = wps;
-
-	return m1;
-}
-
-
-static struct wpabuf *
-hostapd_rx_req_put_message(void *priv, struct upnp_wps_peer *peer,
-			   const struct wpabuf *msg)
-{
-	enum wps_process_res res;
-	enum wsc_op_code op_code;
-
-	/* PutMessage: msg = InMessage, return OutMessage */
-	res = wps_process_msg(peer->wps, WSC_UPnP, msg);
-	if (res == WPS_FAILURE)
-		return NULL;
-	return wps_get_msg(peer->wps, &op_code);
-}
-
-
-static struct wpabuf *
-hostapd_rx_req_get_ap_settings(void *priv, const struct wpabuf *msg)
-{
-	wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__);
-	return NULL;
-}
-
-
-static int hostapd_rx_req_set_ap_settings(void *priv, const struct wpabuf *msg)
-{
-	wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__);
-	return -1;
-}
-
-
-static int hostapd_rx_req_del_ap_settings(void *priv, const struct wpabuf *msg)
-{
-	wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__);
-	return -1;
-}
-
-
-static struct wpabuf *
-hostapd_rx_req_get_sta_settings(void *priv, const struct wpabuf *msg)
-{
-	wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__);
-	return NULL;
-}
-
-
-static int hostapd_rx_req_set_sta_settings(void *priv,
-					   const struct wpabuf *msg)
-{
-	wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__);
-	return -1;
-}
-
-
-static int hostapd_rx_req_del_sta_settings(void *priv,
-					   const struct wpabuf *msg)
-{
-	wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__);
-	return -1;
-}
-
-
 static int hostapd_rx_req_put_wlan_response(
 	void *priv, enum upnp_wps_wlanevent_type ev_type,
 	const u8 *mac_addr, const struct wpabuf *msg,
@@ -941,42 +896,6 @@ static int hostapd_rx_req_put_wlan_response(
 }
 
 
-static int hostapd_rx_req_set_selected_registrar(void *priv,
-						 const struct wpabuf *msg)
-{
-	struct hostapd_data *hapd = priv;
-	return wps_registrar_set_selected_registrar(hapd->wps->registrar, msg);
-}
-
-
-static int hostapd_rx_req_reboot_ap(void *priv, const struct wpabuf *msg)
-{
-	wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__);
-	return -1;
-}
-
-
-static int hostapd_rx_req_reset_ap(void *priv, const struct wpabuf *msg)
-{
-	wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__);
-	return -1;
-}
-
-
-static int hostapd_rx_req_reboot_sta(void *priv, const struct wpabuf *msg)
-{
-	wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__);
-	return -1;
-}
-
-
-static int hostapd_rx_req_reset_sta(void *priv, const struct wpabuf *msg)
-{
-	wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__);
-	return -1;
-}
-
-
 static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
 				 struct wps_context *wps)
 {
@@ -988,21 +907,9 @@ static int hostapd_wps_upnp_init(struct hostapd_data *hapd,
 	if (ctx == NULL)
 		return -1;
 
-	ctx->rx_req_get_device_info = hostapd_rx_req_get_device_info;
-	ctx->rx_req_put_message = hostapd_rx_req_put_message;
-	ctx->rx_req_get_ap_settings = hostapd_rx_req_get_ap_settings;
-	ctx->rx_req_set_ap_settings = hostapd_rx_req_set_ap_settings;
-	ctx->rx_req_del_ap_settings = hostapd_rx_req_del_ap_settings;
-	ctx->rx_req_get_sta_settings = hostapd_rx_req_get_sta_settings;
-	ctx->rx_req_set_sta_settings = hostapd_rx_req_set_sta_settings;
-	ctx->rx_req_del_sta_settings = hostapd_rx_req_del_sta_settings;
 	ctx->rx_req_put_wlan_response = hostapd_rx_req_put_wlan_response;
-	ctx->rx_req_set_selected_registrar =
-		hostapd_rx_req_set_selected_registrar;
-	ctx->rx_req_reboot_ap = hostapd_rx_req_reboot_ap;
-	ctx->rx_req_reset_ap = hostapd_rx_req_reset_ap;
-	ctx->rx_req_reboot_sta = hostapd_rx_req_reboot_sta;
-	ctx->rx_req_reset_sta = hostapd_rx_req_reset_sta;
+	if (hapd->conf->ap_pin)
+		ctx->ap_pin = os_strdup(hapd->conf->ap_pin);
 
 	hapd->wps_upnp = upnp_wps_device_init(ctx, wps, hapd);
 	if (hapd->wps_upnp == NULL) {
@@ -1027,3 +934,87 @@ static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd)
 }
 
 #endif /* CONFIG_WPS_UPNP */
+
+
+int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
+			    char *buf, size_t buflen)
+{
+	if (hapd->wps == NULL)
+		return 0;
+	return wps_registrar_get_info(hapd->wps->registrar, addr, buf, buflen);
+}
+
+
+static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx)
+{
+	struct hostapd_data *hapd = eloop_data;
+	wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out");
+	hostapd_wps_ap_pin_disable(hapd);
+}
+
+
+static void hostapd_wps_ap_pin_enable(struct hostapd_data *hapd, int timeout)
+{
+	wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
+	hapd->ap_pin_failures = 0;
+	hapd->conf->ap_setup_locked = 0;
+	if (hapd->wps->ap_setup_locked) {
+		wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
+		hapd->wps->ap_setup_locked = 0;
+		wps_registrar_update_ie(hapd->wps->registrar);
+	}
+	eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
+	if (timeout > 0)
+		eloop_register_timeout(timeout, 0,
+				       hostapd_wps_ap_pin_timeout, hapd, NULL);
+}
+
+
+void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd)
+{
+	wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
+	os_free(hapd->conf->ap_pin);
+	hapd->conf->ap_pin = NULL;
+#ifdef CONFIG_WPS_UPNP
+	upnp_wps_set_ap_pin(hapd->wps_upnp, NULL);
+#endif /* CONFIG_WPS_UPNP */
+	eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
+}
+
+
+const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout)
+{
+	unsigned int pin;
+	char pin_txt[9];
+
+	pin = wps_generate_pin();
+	os_snprintf(pin_txt, sizeof(pin_txt), "%u", pin);
+	os_free(hapd->conf->ap_pin);
+	hapd->conf->ap_pin = os_strdup(pin_txt);
+#ifdef CONFIG_WPS_UPNP
+	upnp_wps_set_ap_pin(hapd->wps_upnp, pin_txt);
+#endif /* CONFIG_WPS_UPNP */
+	hostapd_wps_ap_pin_enable(hapd, timeout);
+	return hapd->conf->ap_pin;
+}
+
+
+const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd)
+{
+	return hapd->conf->ap_pin;
+}
+
+
+int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
+			   int timeout)
+{
+	os_free(hapd->conf->ap_pin);
+	hapd->conf->ap_pin = os_strdup(pin);
+	if (hapd->conf->ap_pin == NULL)
+		return -1;
+#ifdef CONFIG_WPS_UPNP
+	upnp_wps_set_ap_pin(hapd->wps_upnp, hapd->conf->ap_pin);
+#endif /* CONFIG_WPS_UPNP */
+	hostapd_wps_ap_pin_enable(hapd, timeout);
+	return 0;
+}
diff --git a/contrib/wpa/hostapd/wps_hostapd.h b/contrib/wpa/src/ap/wps_hostapd.h
similarity index 52%
rename from contrib/wpa/hostapd/wps_hostapd.h
rename to contrib/wpa/src/ap/wps_hostapd.h
index e949bee87ac6..e978a1cf668d 100644
--- a/contrib/wpa/hostapd/wps_hostapd.h
+++ b/contrib/wpa/src/ap/wps_hostapd.h
@@ -1,6 +1,6 @@
 /*
  * hostapd / WPS integration
- * Copyright (c) 2008, Jouni Malinen 
+ * Copyright (c) 2008-2010, Jouni Malinen 
  *
  * 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
@@ -20,11 +20,19 @@
 int hostapd_init_wps(struct hostapd_data *hapd,
 		     struct hostapd_bss_config *conf);
 void hostapd_deinit_wps(struct hostapd_data *hapd);
+void hostapd_update_wps(struct hostapd_data *hapd);
 int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid,
 			const char *pin, int timeout);
 int hostapd_wps_button_pushed(struct hostapd_data *hapd);
-void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr,
-			      const u8 *ie, size_t ie_len);
+int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
+			  char *path, char *method, char *name);
+int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr,
+			    char *buf, size_t buflen);
+void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd);
+const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout);
+const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd);
+int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
+			   int timeout);
 
 #else /* CONFIG_WPS */
 
@@ -38,11 +46,22 @@ static inline void hostapd_deinit_wps(struct hostapd_data *hapd)
 {
 }
 
-static inline void hostapd_wps_probe_req_rx(struct hostapd_data *hapd,
-					    const u8 *addr,
-					    const u8 *ie, size_t ie_len)
+static inline void hostapd_update_wps(struct hostapd_data *hapd)
 {
 }
+
+static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd,
+					  const u8 *addr,
+					  char *buf, size_t buflen)
+{
+	return 0;
+}
+
+static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd)
+{
+	return 0;
+}
+
 #endif /* CONFIG_WPS */
 
 #endif /* WPS_HOSTAPD_H */
diff --git a/contrib/wpa/src/common/Makefile b/contrib/wpa/src/common/Makefile
index cffba620da04..9c41962fd7e1 100644
--- a/contrib/wpa/src/common/Makefile
+++ b/contrib/wpa/src/common/Makefile
@@ -2,7 +2,6 @@ all:
 	@echo Nothing to be made.
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
 	rm -f *~ *.o *.d
 
 install:
diff --git a/contrib/wpa/src/common/defs.h b/contrib/wpa/src/common/defs.h
index 4930e73e75cc..173bbd1c9897 100644
--- a/contrib/wpa/src/common/defs.h
+++ b/contrib/wpa/src/common/defs.h
@@ -77,18 +77,44 @@ static inline int wpa_key_mgmt_sha256(int akm)
 #define WPA_AUTH_ALG_OPEN BIT(0)
 #define WPA_AUTH_ALG_SHARED BIT(1)
 #define WPA_AUTH_ALG_LEAP BIT(2)
+#define WPA_AUTH_ALG_FT BIT(3)
 
 
-typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP,
-	       WPA_ALG_IGTK, WPA_ALG_PMK } wpa_alg;
-typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
-	       CIPHER_WEP104 } wpa_cipher;
-typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
-	       KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE,
-	       KEY_MGMT_FT_802_1X, KEY_MGMT_FT_PSK,
-	       KEY_MGMT_802_1X_SHA256, KEY_MGMT_PSK_SHA256,
-	       KEY_MGMT_WPS
-} wpa_key_mgmt;
+enum wpa_alg {
+	WPA_ALG_NONE,
+	WPA_ALG_WEP,
+	WPA_ALG_TKIP,
+	WPA_ALG_CCMP,
+	WPA_ALG_IGTK,
+	WPA_ALG_PMK
+};
+
+/**
+ * enum wpa_cipher - Cipher suites
+ */
+enum wpa_cipher {
+	CIPHER_NONE,
+	CIPHER_WEP40,
+	CIPHER_TKIP,
+	CIPHER_CCMP,
+	CIPHER_WEP104
+};
+
+/**
+ * enum wpa_key_mgmt - Key management suites
+ */
+enum wpa_key_mgmt {
+	KEY_MGMT_802_1X,
+	KEY_MGMT_PSK,
+	KEY_MGMT_NONE,
+	KEY_MGMT_802_1X_NO_WPA,
+	KEY_MGMT_WPA_NONE,
+	KEY_MGMT_FT_802_1X,
+	KEY_MGMT_FT_PSK,
+	KEY_MGMT_802_1X_SHA256,
+	KEY_MGMT_PSK_SHA256,
+	KEY_MGMT_WPS
+};
 
 /**
  * enum wpa_states - wpa_supplicant state
@@ -100,7 +126,7 @@ typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
  * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used
  * to access the state variable.
  */
-typedef enum {
+enum wpa_states {
 	/**
 	 * WPA_DISCONNECTED - Disconnected state
 	 *
@@ -128,6 +154,16 @@ typedef enum {
 	 */
 	WPA_SCANNING,
 
+	/**
+	 * WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID
+	 *
+	 * This state is entered when wpa_supplicant has found a suitable BSS
+	 * to authenticate with and the driver is configured to try to
+	 * authenticate with this BSS. This state is used only with drivers
+	 * that use wpa_supplicant as the SME.
+	 */
+	WPA_AUTHENTICATING,
+
 	/**
 	 * WPA_ASSOCIATING - Trying to associate with a BSS/SSID
 	 *
@@ -186,7 +222,7 @@ typedef enum {
 	 * fully configured.
 	 */
 	WPA_COMPLETED
-} wpa_states;
+};
 
 #define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0
 #define MLME_SETPROTECTION_PROTECT_TYPE_RX 1
@@ -196,4 +232,24 @@ typedef enum {
 #define MLME_SETPROTECTION_KEY_TYPE_GROUP 0
 #define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1
 
+
+/**
+ * enum mfp_options - Management frame protection (IEEE 802.11w) options
+ */
+enum mfp_options {
+	NO_MGMT_FRAME_PROTECTION = 0,
+	MGMT_FRAME_PROTECTION_OPTIONAL = 1,
+	MGMT_FRAME_PROTECTION_REQUIRED = 2
+};
+
+/**
+ * enum hostapd_hw_mode - Hardware mode
+ */
+enum hostapd_hw_mode {
+	HOSTAPD_MODE_IEEE80211B,
+	HOSTAPD_MODE_IEEE80211G,
+	HOSTAPD_MODE_IEEE80211A,
+	NUM_HOSTAPD_MODES
+};
+
 #endif /* DEFS_H */
diff --git a/contrib/wpa/src/common/ieee802_11_common.c b/contrib/wpa/src/common/ieee802_11_common.c
index 242f933b03fd..96ef5b65a176 100644
--- a/contrib/wpa/src/common/ieee802_11_common.c
+++ b/contrib/wpa/src/common/ieee802_11_common.c
@@ -1,6 +1,6 @@
 /*
  * IEEE 802.11 Common routines
- * Copyright (c) 2002-2008, Jouni Malinen 
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -19,7 +19,7 @@
 #include "ieee802_11_common.h"
 
 
-static int ieee802_11_parse_vendor_specific(u8 *pos, size_t elen,
+static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
 					    struct ieee802_11_elems *elems,
 					    int show_errors)
 {
@@ -131,12 +131,12 @@ static int ieee802_11_parse_vendor_specific(u8 *pos, size_t elen,
  * @show_errors: Whether to show parsing errors in debug log
  * Returns: Parsing result
  */
-ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
+ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
 				struct ieee802_11_elems *elems,
 				int show_errors)
 {
 	size_t left = len;
-	u8 *pos = start;
+	const u8 *pos = start;
 	int unknown = 0;
 
 	os_memset(elems, 0, sizeof(*elems));
@@ -257,3 +257,70 @@ ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
 
 	return unknown ? ParseUnknown : ParseOK;
 }
+
+
+int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
+{
+	int count = 0;
+	const u8 *pos, *end;
+
+	if (ies == NULL)
+		return 0;
+
+	pos = ies;
+	end = ies + ies_len;
+
+	while (pos + 2 <= end) {
+		if (pos + 2 + pos[1] > end)
+			break;
+		count++;
+		pos += 2 + pos[1];
+	}
+
+	return count;
+}
+
+
+struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
+					    u32 oui_type)
+{
+	struct wpabuf *buf;
+	const u8 *end, *pos, *ie;
+
+	pos = ies;
+	end = ies + ies_len;
+	ie = NULL;
+
+	while (pos + 1 < end) {
+		if (pos + 2 + pos[1] > end)
+			return NULL;
+		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
+		    WPA_GET_BE32(&pos[2]) == oui_type) {
+			ie = pos;
+			break;
+		}
+		pos += 2 + pos[1];
+	}
+
+	if (ie == NULL)
+		return NULL; /* No specified vendor IE found */
+
+	buf = wpabuf_alloc(ies_len);
+	if (buf == NULL)
+		return NULL;
+
+	/*
+	 * There may be multiple vendor IEs in the message, so need to
+	 * concatenate their data fields.
+	 */
+	while (pos + 1 < end) {
+		if (pos + 2 + pos[1] > end)
+			break;
+		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
+		    WPA_GET_BE32(&pos[2]) == oui_type)
+			wpabuf_put_data(buf, pos + 6, pos[1] - 4);
+		pos += 2 + pos[1];
+	}
+
+	return buf;
+}
diff --git a/contrib/wpa/src/common/ieee802_11_common.h b/contrib/wpa/src/common/ieee802_11_common.h
index b7e497b6cc68..4a4f5a742cc5 100644
--- a/contrib/wpa/src/common/ieee802_11_common.h
+++ b/contrib/wpa/src/common/ieee802_11_common.h
@@ -1,6 +1,6 @@
 /*
  * IEEE 802.11 Common routines
- * Copyright (c) 2002-2008, Jouni Malinen 
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -17,58 +17,62 @@
 
 /* Parsed Information Elements */
 struct ieee802_11_elems {
-	u8 *ssid;
+	const u8 *ssid;
+	const u8 *supp_rates;
+	const u8 *fh_params;
+	const u8 *ds_params;
+	const u8 *cf_params;
+	const u8 *tim;
+	const u8 *ibss_params;
+	const u8 *challenge;
+	const u8 *erp_info;
+	const u8 *ext_supp_rates;
+	const u8 *wpa_ie;
+	const u8 *rsn_ie;
+	const u8 *wmm; /* WMM Information or Parameter Element */
+	const u8 *wmm_tspec;
+	const u8 *wps_ie;
+	const u8 *power_cap;
+	const u8 *supp_channels;
+	const u8 *mdie;
+	const u8 *ftie;
+	const u8 *timeout_int;
+	const u8 *ht_capabilities;
+	const u8 *ht_operation;
+	const u8 *vendor_ht_cap;
+
 	u8 ssid_len;
-	u8 *supp_rates;
 	u8 supp_rates_len;
-	u8 *fh_params;
 	u8 fh_params_len;
-	u8 *ds_params;
 	u8 ds_params_len;
-	u8 *cf_params;
 	u8 cf_params_len;
-	u8 *tim;
 	u8 tim_len;
-	u8 *ibss_params;
 	u8 ibss_params_len;
-	u8 *challenge;
 	u8 challenge_len;
-	u8 *erp_info;
 	u8 erp_info_len;
-	u8 *ext_supp_rates;
 	u8 ext_supp_rates_len;
-	u8 *wpa_ie;
 	u8 wpa_ie_len;
-	u8 *rsn_ie;
 	u8 rsn_ie_len;
-	u8 *wmm; /* WMM Information or Parameter Element */
 	u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */
-	u8 *wmm_tspec;
 	u8 wmm_tspec_len;
-	u8 *wps_ie;
 	u8 wps_ie_len;
-	u8 *power_cap;
 	u8 power_cap_len;
-	u8 *supp_channels;
 	u8 supp_channels_len;
-	u8 *mdie;
 	u8 mdie_len;
-	u8 *ftie;
 	u8 ftie_len;
-	u8 *timeout_int;
 	u8 timeout_int_len;
-	u8 *ht_capabilities;
 	u8 ht_capabilities_len;
-	u8 *ht_operation;
 	u8 ht_operation_len;
-	u8 *vendor_ht_cap;
 	u8 vendor_ht_cap_len;
 };
 
 typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
 
-ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
+ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
 				struct ieee802_11_elems *elems,
 				int show_errors);
+int ieee802_11_ie_count(const u8 *ies, size_t ies_len);
+struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
+					    u32 oui_type);
 
 #endif /* IEEE802_11_COMMON_H */
diff --git a/contrib/wpa/src/common/ieee802_11_defs.h b/contrib/wpa/src/common/ieee802_11_defs.h
index d9e54a99ed50..4881e39a01a8 100644
--- a/contrib/wpa/src/common/ieee802_11_defs.h
+++ b/contrib/wpa/src/common/ieee802_11_defs.h
@@ -1,6 +1,6 @@
 /*
  * IEEE 802.11 Frame type definitions
- * Copyright (c) 2002-2007, Jouni Malinen 
+ * Copyright (c) 2002-2009, Jouni Malinen 
  * Copyright (c) 2007-2008 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
@@ -116,9 +116,13 @@
 #define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
 #define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
 #define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
+#define WLAN_STATUS_R0KH_UNREACHABLE 28
 /* IEEE 802.11w */
 #define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
 #define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
+#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32
+#define WLAN_STATUS_REQUEST_DECLINED 37
+#define WLAN_STATUS_INVALID_PARAMETERS 38
 /* IEEE 802.11i */
 #define WLAN_STATUS_INVALID_IE 40
 #define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
@@ -233,6 +237,25 @@
 #pragma pack(push, 1)
 #endif /* _MSC_VER */
 
+struct ieee80211_hdr {
+	le16 frame_control;
+	le16 duration_id;
+	u8 addr1[6];
+	u8 addr2[6];
+	u8 addr3[6];
+	le16 seq_ctrl;
+	/* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame
+	 */
+} STRUCT_PACKED;
+
+#define IEEE80211_DA_FROMDS addr1
+#define IEEE80211_BSSID_FROMDS addr2
+#define IEEE80211_SA_FROMDS addr3
+
+#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))
+
+#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
+
 struct ieee80211_mgmt {
 	le16 frame_control;
 	le16 duration;
@@ -337,45 +360,14 @@ struct ieee80211_mgmt {
 	} u;
 } STRUCT_PACKED;
 
-#ifdef _MSC_VER
-#pragma pack(pop)
-#endif /* _MSC_VER */
 
-#define ERP_INFO_NON_ERP_PRESENT BIT(0)
-#define ERP_INFO_USE_PROTECTION BIT(1)
-#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2)
-
-
-/* HT Capability element */
-
-enum {
-	MAX_RX_AMPDU_FACTOR_8KB = 0,
-	MAX_RX_AMPDU_FACTOR_16KB,
-	MAX_RX_AMPDU_FACTOR_32KB,
-	MAX_RX_AMPDU_FACTOR_64KB
-};
-
-enum {
-	CALIBRATION_NOT_SUPPORTED = 0,
-	CALIBRATION_CANNOT_INIT,
-	CALIBRATION_CAN_INIT,
-	CALIBRATION_FULL_SUPPORT
-};
-
-enum {
-	MCS_FEEDBACK_NOT_PROVIDED = 0,
-	MCS_FEEDBACK_UNSOLICITED,
-	MCS_FEEDBACK_MRQ_RESPONSE
-};
-
-
-struct ieee80211_ht_capability {
-	le16 capabilities_info;
-	u8 mac_ht_params_info;
+struct ieee80211_ht_capabilities {
+	le16 ht_capabilities_info;
+	u8 a_mpdu_params;
 	u8 supported_mcs_set[16];
-	le16 extended_ht_capability_info;
-	le32 tx_BF_capability_info;
-	u8 antenna_selection_info;
+	le16 ht_extended_capabilities;
+	le32 tx_bf_capability_info;
+	u8 asel_capabilities;
 } STRUCT_PACKED;
 
 
@@ -387,47 +379,13 @@ struct ieee80211_ht_operation {
 	u8 basic_set[16];
 } STRUCT_PACKED;
 
-/* auxiliary bit manipulation macros FIXME: move it to common later... */
-#define SET_2BIT_U8(_ptr_, _shift_, _val_)				\
-	((*(_ptr_) &= ~(3 << (_shift_))),				\
-	 (*(_ptr_) |= (*(_ptr_) & (((u8)3) << (_shift_))) |		\
-		      (((u8)(_val_) & 3) << _shift_)))
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
-#define GET_2BIT_U8(_var_, _shift_)	\
-	(((_var_) & (((u8)3) << (_shift_))) >> (_shift_))
-
-#define SET_2BIT_LE16(_u16ptr_, _shift_, _val_)				\
-	((*(_u16ptr_) &= ~(3 << (_shift_))),				\
-	 (*(_u16ptr_) |= 						\
-		(((*(_u16ptr_)) & (((u16)3) << ((u16)_shift_))) |	\
-		(((u16)(_val_) & (u16)3) << (u16)(_shift_)))))
-
-#define GET_2BIT_LE16(_var_, _shift_)	\
-	(((_var_) & (((u16)3) << (_shift_))) >> (_shift_))
-
-#define SET_2BIT_LE32(_u32ptr_, _shift_, _val_)				\
-	((*(_u32ptr_) &= ~(3 << (_shift_))),				\
-	 (*(_u32ptr_) |= (((*(_u32ptr_)) & (((u32)3) << (_shift_))) |	\
-			(((u32)(_val_) & 3) << _shift_))))
-
-#define GET_2BIT_LE32(_var_, _shift_)	\
-	(((_var_) & (((u32)3) << (_shift_))) >> (_shift_))
-
-#define SET_3BIT_LE16(_u16ptr_, _shift_, _val_)				\
-	((*(_u16ptr_) &= ~(7 << (_shift_))),				\
-	(*(_u16ptr_) |= (((*(_u16ptr_)) & (((u16)7) << (_shift_))) |	\
-			(((u16)(_val_) & 7) << _shift_))))
-
-#define GET_3BIT_LE16(_var_, _shift_)	\
-	(((_var_) & (((u16)7) << (_shift_))) >> (_shift_))
-
-#define SET_3BIT_LE32(_u32ptr_, _shift_, _val_)				\
-	((*(_u32ptr_) &= ~(7 << (_shift_))),				\
-	 (*(_u32ptr_) |= (((*(_u32ptr_)) & (((u32)7) << (_shift_))) |	\
-			(((u32)(_val_) & 7) << _shift_))))
-
-#define GET_3BIT_LE32(_var_, _shift_)	\
-	(((_var_) & (((u32)7) << (_shift_))) >> (_shift_))
+#define ERP_INFO_NON_ERP_PRESENT BIT(0)
+#define ERP_INFO_USE_PROTECTION BIT(1)
+#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2)
 
 
 #define HT_CAP_INFO_LDPC_CODING_CAP		((u16) BIT(0))
@@ -452,9 +410,6 @@ struct ieee80211_ht_operation {
 #define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT	((u16) BIT(15))
 
 
-#define MAC_HT_PARAM_INFO_MAX_RX_AMPDU_FACTOR_OFFSET	0
-#define MAC_HT_PARAM_INFO_MAX_MPDU_DENSITY_OFFSET	2
-
 #define EXT_HT_CAP_INFO_PCO			((u16) BIT(0))
 #define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET	1
 #define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET	8
@@ -490,22 +445,6 @@ struct ieee80211_ht_operation {
 #define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5))
 #define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6))
 
-
-struct ht_cap_ie {
-	u8 id;
-	u8 length;
-	struct ieee80211_ht_capability data;
-} STRUCT_PACKED;
-
-
-#define REC_TRANS_CHNL_WIDTH_20     0
-#define REC_TRANS_CHNL_WIDTH_ANY    1
-
-#define OP_MODE_PURE                    0
-#define OP_MODE_MAY_BE_LEGACY_STAS      1
-#define OP_MODE_20MHZ_HT_STA_ASSOCED    2
-#define OP_MODE_MIXED                   3
-
 #define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK	((u8) BIT(0) | BIT(1))
 #define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE		((u8) BIT(0))
 #define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW		((u8) BIT(0) | BIT(1))
@@ -514,6 +453,12 @@ struct ht_cap_ie {
 #define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY		((u8) BIT(4))
 #define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY	((u8) BIT(5))
 
+
+#define OP_MODE_PURE                    0
+#define OP_MODE_MAY_BE_LEGACY_STAS      1
+#define OP_MODE_20MHZ_HT_STA_ASSOCED    2
+#define OP_MODE_MIXED                   3
+
 #define HT_INFO_OPERATION_MODE_OP_MODE_MASK	\
 		((le16) (0x0001 | 0x0002))
 #define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET		0
@@ -529,39 +474,10 @@ struct ht_cap_ie {
 #define HT_INFO_STBC_PARAM_PCO_PHASE			((u16) BIT(11))
 
 
-/* Secondary channel offset element */
-#define SECONDARY_CHANNEL_OFFSET_NONE	0
-#define SECONDARY_CHANNEL_OFFSET_ABOVE	1
-#define SECONDARY_CHANNEL_OFFSET_BELOW	3
-struct secondary_channel_offset_ie {
-	u8 id;
-	u8 length;
-	u8 secondary_offset_offset;
-} STRUCT_PACKED;
-
-
-/* body of Recommended Transmit Channel Width action frame */
-#define CHANNEL_WIDTH_20	0
-#define CHANNEL_WIDTH_ANY	1
-struct recommended_tx_channel_width_action {
-	u8 category;
-	u8 action;
-	u8 channel_width;
-} STRUCT_PACKED;
-
-/* body of MIMO Power Save action frame */
-#define PWR_SAVE_MODE_STATIC	0
-#define PWR_SAVE_MODE_DYNAMIC	1
-struct mimo_pwr_save_action {
-	u8 category;
-	u8 action;
-	u8 enable;
-	u8 mode;
-} STRUCT_PACKED;
-
-
 #define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
 				* 00:50:F2 */
+#define WPA_IE_VENDOR_TYPE 0x0050f201
+#define WPS_IE_VENDOR_TYPE 0x0050f204
 
 #define WMM_OUI_TYPE 2
 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
@@ -585,9 +501,107 @@ struct mimo_pwr_save_action {
 /* 2 - Reserved */
 #define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3
 
+/*
+ * WMM Information Element (used in (Re)Association Request frames; may also be
+ * used in Beacon frames)
+ */
+struct wmm_information_element {
+	/* Element ID: 221 (0xdd); Length: 7 */
+	/* required fields for WMM version 1 */
+	u8 oui[3]; /* 00:50:f2 */
+	u8 oui_type; /* 2 */
+	u8 oui_subtype; /* 0 */
+	u8 version; /* 1 for WMM version 1.0 */
+	u8 qos_info; /* AP/STA specific QoS info */
+
+} STRUCT_PACKED;
+
+#define WMM_AC_AIFSN_MASK 0x0f
+#define WMM_AC_AIFNS_SHIFT 0
+#define WMM_AC_ACM 0x10
+#define WMM_AC_ACI_MASK 0x60
+#define WMM_AC_ACI_SHIFT 5
+
+#define WMM_AC_ECWMIN_MASK 0x0f
+#define WMM_AC_ECWMIN_SHIFT 0
+#define WMM_AC_ECWMAX_MASK 0xf0
+#define WMM_AC_ECWMAX_SHIFT 4
+
+struct wmm_ac_parameter {
+	u8 aci_aifsn; /* AIFSN, ACM, ACI */
+	u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
+	le16 txop_limit;
+}  STRUCT_PACKED;
+
+/*
+ * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association
+ * Response frmaes)
+ */
+struct wmm_parameter_element {
+	/* Element ID: 221 (0xdd); Length: 24 */
+	/* required fields for WMM version 1 */
+	u8 oui[3]; /* 00:50:f2 */
+	u8 oui_type; /* 2 */
+	u8 oui_subtype; /* 1 */
+	u8 version; /* 1 for WMM version 1.0 */
+	u8 qos_info; /* AP/STA specif QoS info */
+	u8 reserved; /* 0 */
+	struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
+
+} STRUCT_PACKED;
+
+/* WMM TSPEC Element */
+struct wmm_tspec_element {
+	u8 eid; /* 221 = 0xdd */
+	u8 length; /* 6 + 55 = 61 */
+	u8 oui[3]; /* 00:50:f2 */
+	u8 oui_type; /* 2 */
+	u8 oui_subtype; /* 2 */
+	u8 version; /* 1 */
+	/* WMM TSPEC body (55 octets): */
+	u8 ts_info[3];
+	le16 nominal_msdu_size;
+	le16 maximum_msdu_size;
+	le32 minimum_service_interval;
+	le32 maximum_service_interval;
+	le32 inactivity_interval;
+	le32 suspension_interval;
+	le32 service_start_time;
+	le32 minimum_data_rate;
+	le32 mean_data_rate;
+	le32 peak_data_rate;
+	le32 maximum_burst_size;
+	le32 delay_bound;
+	le32 minimum_phy_rate;
+	le16 surplus_bandwidth_allowance;
+	le16 medium_time;
+} STRUCT_PACKED;
+
+
+/* Access Categories / ACI to AC coding */
+enum {
+	WMM_AC_BE = 0 /* Best Effort */,
+	WMM_AC_BK = 1 /* Background */,
+	WMM_AC_VI = 2 /* Video */,
+	WMM_AC_VO = 3 /* Voice */
+};
+
 
 #define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
 
 #define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
 
+/* cipher suite selectors */
+#define WLAN_CIPHER_SUITE_USE_GROUP	0x000FAC00
+#define WLAN_CIPHER_SUITE_WEP40		0x000FAC01
+#define WLAN_CIPHER_SUITE_TKIP		0x000FAC02
+/* reserved: 				0x000FAC03 */
+#define WLAN_CIPHER_SUITE_CCMP		0x000FAC04
+#define WLAN_CIPHER_SUITE_WEP104	0x000FAC05
+#define WLAN_CIPHER_SUITE_AES_CMAC	0x000FAC06
+
+/* AKM suite selectors */
+#define WLAN_AKM_SUITE_8021X		0x000FAC01
+#define WLAN_AKM_SUITE_PSK		0x000FAC02
+
 #endif /* IEEE802_11_DEFS_H */
diff --git a/contrib/wpa/src/common/nl80211_copy.h b/contrib/wpa/src/common/nl80211_copy.h
deleted file mode 100644
index 45db17f81aa3..000000000000
--- a/contrib/wpa/src/common/nl80211_copy.h
+++ /dev/null
@@ -1,1434 +0,0 @@
-#ifndef __LINUX_NL80211_H
-#define __LINUX_NL80211_H
-/*
- * 802.11 netlink interface public header
- *
- * Copyright 2006, 2007, 2008 Johannes Berg 
- * Copyright 2008 Michael Wu 
- * Copyright 2008 Luis Carlos Cobo 
- * Copyright 2008 Michael Buesch 
- * Copyright 2008, 2009 Luis R. Rodriguez 
- * Copyright 2008 Jouni Malinen 
- * Copyright 2008 Colin McCabe 
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include 
-
-/**
- * DOC: Station handling
- *
- * Stations are added per interface, but a special case exists with VLAN
- * interfaces. When a station is bound to an AP interface, it may be moved
- * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN).
- * The station is still assumed to belong to the AP interface it was added
- * to.
- *
- * TODO: need more info?
- */
-
-/**
- * enum nl80211_commands - supported nl80211 commands
- *
- * @NL80211_CMD_UNSPEC: unspecified command to catch errors
- *
- * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request
- *	to get a list of all present wiphys.
- * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
- *	%NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
- *	%NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ,
- *	%NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
- *	%NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
- *	and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
- * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
- *	or rename notification. Has attributes %NL80211_ATTR_WIPHY and
- *	%NL80211_ATTR_WIPHY_NAME.
- * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes
- *	%NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME.
- *
- * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration;
- *	either a dump request on a %NL80211_ATTR_WIPHY or a specific get
- *	on an %NL80211_ATTR_IFINDEX is supported.
- * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires
- *	%NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE.
- * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response
- *	to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX,
- *	%NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also
- *	be sent from userspace to request creation of a new virtual interface,
- *	then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and
- *	%NL80211_ATTR_IFNAME.
- * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes
- *	%NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from
- *	userspace to request deletion of a virtual interface, then requires
- *	attribute %NL80211_ATTR_IFINDEX.
- *
- * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
- *	by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
- * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT,
- *	%NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD.
- * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA,
- *	%NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER,
- *	and %NL80211_ATTR_KEY_SEQ attributes.
- * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
- *	or %NL80211_ATTR_MAC.
- *
- * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a
- *	%NL80222_CMD_NEW_BEACON message)
- * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface
- *	using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD,
- *	%NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes.
- * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface,
- *	parameters are like for %NL80211_CMD_SET_BEACON.
- * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it
- *
- * @NL80211_CMD_GET_STATION: Get station attributes for station identified by
- *	%NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX.
- * @NL80211_CMD_SET_STATION: Set station attributes for station identified by
- *	%NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX.
- * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the
- *	the interface identified by %NL80211_ATTR_IFINDEX.
- * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC
- *	or, if no MAC address given, all stations, on the interface identified
- *	by %NL80211_ATTR_IFINDEX.
- *
- * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to
- * 	destination %NL80211_ATTR_MAC on the interface identified by
- * 	%NL80211_ATTR_IFINDEX.
- * @NL80211_CMD_SET_MPATH:  Set mesh path attributes for mesh path to
- * 	destination %NL80211_ATTR_MAC on the interface identified by
- * 	%NL80211_ATTR_IFINDEX.
- * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the
- *	the interface identified by %NL80211_ATTR_IFINDEX.
- * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC
- *	or, if no MAC address given, all mesh paths, on the interface identified
- *	by %NL80211_ATTR_IFINDEX.
- * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by
- *	%NL80211_ATTR_IFINDEX.
- *
- * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set
- * 	regulatory domain.
- * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command
- *	after being queried by the kernel. CRDA replies by sending a regulatory
- *	domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our
- *	current alpha2 if it found a match. It also provides
- * 	NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each
- * 	regulatory rule is a nested set of attributes  given by
- * 	%NL80211_ATTR_REG_RULE_FREQ_[START|END] and
- * 	%NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by
- * 	%NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and
- * 	%NL80211_ATTR_REG_RULE_POWER_MAX_EIRP.
- * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain
- * 	to the the specified ISO/IEC 3166-1 alpha2 country code. The core will
- * 	store this as a valid request and then query userspace for it.
- *
- * @NL80211_CMD_GET_MESH_PARAMS: Get mesh networking properties for the
- *	interface identified by %NL80211_ATTR_IFINDEX
- *
- * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the
- *      interface identified by %NL80211_ATTR_IFINDEX
- *
- * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The
- *	interface is identified with %NL80211_ATTR_IFINDEX and the management
- *	frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be
- *	added to the end of the specified management frame is specified with
- *	%NL80211_ATTR_IE. If the command succeeds, the requested data will be
- *	added to all specified management frames generated by
- *	kernel/firmware/driver.
- *	Note: This command has been removed and it is only reserved at this
- *	point to avoid re-using existing command number. The functionality this
- *	command was planned for has been provided with cleaner design with the
- *	option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN,
- *	NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE,
- *	NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE.
- *
- * @NL80211_CMD_GET_SCAN: get scan results
- * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters
- * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to
- *	NL80211_CMD_GET_SCAN and on the "scan" multicast group)
- * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons,
- *	partial scan results may be available
- *
- * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation
- *      or noise level
- * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
- *	NL80211_CMD_GET_SURVEY and on the "scan" multicast group)
- *
- * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain
- * 	has been changed and provides details of the request information
- * 	that caused the change such as who initiated the regulatory request
- * 	(%NL80211_ATTR_REG_INITIATOR), the wiphy_idx
- * 	(%NL80211_ATTR_REG_ALPHA2) on which the request was made from if
- * 	the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or
- * 	%NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain
- * 	set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is
- * 	%NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on
- * 	to (%NL80211_ATTR_REG_ALPHA2).
- * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon
- * 	has been found while world roaming thus enabling active scan or
- * 	any mode of operation that initiates TX (beacons) on a channel
- * 	where we would not have been able to do either before. As an example
- * 	if you are world roaming (regulatory domain set to world or if your
- * 	driver is using a custom world roaming regulatory domain) and while
- * 	doing a passive scan on the 5 GHz band you find an AP there (if not
- * 	on a DFS channel) you will now be able to actively scan for that AP
- * 	or use AP mode on your card on that same channel. Note that this will
- * 	never be used for channels 1-11 on the 2 GHz band as they are always
- * 	enabled world wide. This beacon hint is only sent if your device had
- * 	either disabled active scanning or beaconing on a channel. We send to
- * 	userspace the wiphy on which we removed a restriction from
- * 	(%NL80211_ATTR_WIPHY) and the channel on which this occurred
- * 	before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER)
- * 	the beacon hint was processed.
- *
- * @NL80211_CMD_AUTHENTICATE: authentication request and notification.
- *	This command is used both as a command (request to authenticate) and
- *	as an event on the "mlme" multicast group indicating completion of the
- *	authentication process.
- *	When used as a command, %NL80211_ATTR_IFINDEX is used to identify the
- *	interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and
- *	BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify
- *	the SSID (mainly for association, but is included in authentication
- *	request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used
- *	to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE
- *	is used to specify the authentication type. %NL80211_ATTR_IE is used to
- *	define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs)
- *	to be added to the frame.
- *	When used as an event, this reports reception of an Authentication
- *	frame in station and IBSS modes when the local MLME processed the
- *	frame, i.e., it was for the local STA and was received in correct
- *	state. This is similar to MLME-AUTHENTICATE.confirm primitive in the
- *	MLME SAP interface (kernel providing MLME, userspace SME). The
- *	included %NL80211_ATTR_FRAME attribute contains the management frame
- *	(including both the header and frame body, but not FCS). This event is
- *	also used to indicate if the authentication attempt timed out. In that
- *	case the %NL80211_ATTR_FRAME attribute is replaced with a
- *	%NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which
- *	pending authentication timed out).
- * @NL80211_CMD_ASSOCIATE: association request and notification; like
- *	NL80211_CMD_AUTHENTICATE but for Association and Reassociation
- *	(similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request,
- *	MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives).
- * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like
- *	NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to
- *	MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication
- *	primitives).
- * @NL80211_CMD_DISASSOCIATE: disassociation request and notification; like
- *	NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to
- *	MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives).
- *
- * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael
- *	MIC (part of TKIP) failure; sent on the "mlme" multicast group; the
- *	event includes %NL80211_ATTR_MAC to describe the source MAC address of
- *	the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key
- *	type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and
- *	%NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this
- *	event matches with MLME-MICHAELMICFAILURE.indication() primitive
- *
- * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a
- *	FREQ attribute (for the initial frequency if no peer can be found)
- *	and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those
- *	should be fixed rather than automatically determined. Can only be
- *	executed on a network interface that is UP, and fixed BSSID/FREQ
- *	may be rejected. Another optional parameter is the beacon interval,
- *	given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not
- *	given defaults to 100 TU (102.4ms).
- * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is
- *	determined by the network interface.
- *
- * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute
- *	to identify the device, and the TESTDATA blob attribute to pass through
- *	to the driver.
- *
- * @NL80211_CMD_CONNECT: connection request and notification; this command
- *	requests to connect to a specified network but without separating
- *	auth and assoc steps. For this, you need to specify the SSID in a
- *	%NL80211_ATTR_SSID attribute, and can optionally specify the association
- *	IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC,
- *	%NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_CONTROL_PORT.
- *	It is also sent as an event, with the BSSID and response IEs when the
- *	connection is established or failed to be established. This can be
- *	determined by the STATUS_CODE attribute.
- * @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
- *	sent as an event when the card/driver roamed by itself.
- * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
- *	userspace that a connection was dropped by the AP or due to other
- *	reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and
- *	%NL80211_ATTR_REASON_CODE attributes are used.
- *
- * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices
- *	associated with this wiphy must be down and will follow.
- *
- * @NL80211_CMD_MAX: highest used command number
- * @__NL80211_CMD_AFTER_LAST: internal use
- */
-enum nl80211_commands {
-/* don't change the order or add anything inbetween, this is ABI! */
-	NL80211_CMD_UNSPEC,
-
-	NL80211_CMD_GET_WIPHY,		/* can dump */
-	NL80211_CMD_SET_WIPHY,
-	NL80211_CMD_NEW_WIPHY,
-	NL80211_CMD_DEL_WIPHY,
-
-	NL80211_CMD_GET_INTERFACE,	/* can dump */
-	NL80211_CMD_SET_INTERFACE,
-	NL80211_CMD_NEW_INTERFACE,
-	NL80211_CMD_DEL_INTERFACE,
-
-	NL80211_CMD_GET_KEY,
-	NL80211_CMD_SET_KEY,
-	NL80211_CMD_NEW_KEY,
-	NL80211_CMD_DEL_KEY,
-
-	NL80211_CMD_GET_BEACON,
-	NL80211_CMD_SET_BEACON,
-	NL80211_CMD_NEW_BEACON,
-	NL80211_CMD_DEL_BEACON,
-
-	NL80211_CMD_GET_STATION,
-	NL80211_CMD_SET_STATION,
-	NL80211_CMD_NEW_STATION,
-	NL80211_CMD_DEL_STATION,
-
-	NL80211_CMD_GET_MPATH,
-	NL80211_CMD_SET_MPATH,
-	NL80211_CMD_NEW_MPATH,
-	NL80211_CMD_DEL_MPATH,
-
-	NL80211_CMD_SET_BSS,
-
-	NL80211_CMD_SET_REG,
-	NL80211_CMD_REQ_SET_REG,
-
-	NL80211_CMD_GET_MESH_PARAMS,
-	NL80211_CMD_SET_MESH_PARAMS,
-
-	NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */,
-
-	NL80211_CMD_GET_REG,
-
-	NL80211_CMD_GET_SCAN,
-	NL80211_CMD_TRIGGER_SCAN,
-	NL80211_CMD_NEW_SCAN_RESULTS,
-	NL80211_CMD_SCAN_ABORTED,
-
-	NL80211_CMD_REG_CHANGE,
-
-	NL80211_CMD_AUTHENTICATE,
-	NL80211_CMD_ASSOCIATE,
-	NL80211_CMD_DEAUTHENTICATE,
-	NL80211_CMD_DISASSOCIATE,
-
-	NL80211_CMD_MICHAEL_MIC_FAILURE,
-
-	NL80211_CMD_REG_BEACON_HINT,
-
-	NL80211_CMD_JOIN_IBSS,
-	NL80211_CMD_LEAVE_IBSS,
-
-	NL80211_CMD_TESTMODE,
-
-	NL80211_CMD_CONNECT,
-	NL80211_CMD_ROAM,
-	NL80211_CMD_DISCONNECT,
-
-	NL80211_CMD_SET_WIPHY_NETNS,
-
-	NL80211_CMD_GET_SURVEY,
-	NL80211_CMD_NEW_SURVEY_RESULTS,
-
-	/* add new commands above here */
-
-	/* used to define NL80211_CMD_MAX below */
-	__NL80211_CMD_AFTER_LAST,
-	NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
-};
-
-/*
- * Allow user space programs to use #ifdef on new commands by defining them
- * here
- */
-#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS
-#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE
-#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE
-#define NL80211_CMD_AUTHENTICATE NL80211_CMD_AUTHENTICATE
-#define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE
-#define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE
-#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE
-#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT
-
-/**
- * enum nl80211_attrs - nl80211 netlink attributes
- *
- * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors
- *
- * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf.
- *	/sys/class/ieee80211//index
- * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming)
- * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters
- * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz
- * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ
- *	if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included):
- *	NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including
- *		this attribute)
- *	NL80211_CHAN_HT20 = HT20 only
- *	NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel
- *	NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel
- * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is
- *	less than or equal to the RTS threshold; allowed range: 1..255;
- *	dot11ShortRetryLimit; u8
- * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is
- *	greater than the RTS threshold; allowed range: 1..255;
- *	dot11ShortLongLimit; u8
- * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum
- *	length in octets for frames; allowed range: 256..8000, disable
- *	fragmentation with (u32)-1; dot11FragmentationThreshold; u32
- * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length
- *	larger than or equal to this use RTS/CTS handshake); allowed range:
- *	0..65536, disable with (u32)-1; dot11RTSThreshold; u32
- *
- * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
- * @NL80211_ATTR_IFNAME: network interface name
- * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype
- *
- * @NL80211_ATTR_MAC: MAC address (various uses)
- *
- * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of
- *	16 bytes encryption key followed by 8 bytes each for TX and RX MIC
- *	keys
- * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3)
- * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
- *	section 7.3.2.25.1, e.g. 0x000FAC04)
- * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
- *	CCMP keys, each six bytes in little endian
- *
- * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU
- * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing
- * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE
- * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE
- *
- * @NL80211_ATTR_STA_AID: Association ID for the station (u16)
- * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of
- *	&enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2)
- * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by
- *	IEEE 802.11 7.3.1.6 (u16).
- * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported
- *	rates as defined by IEEE 802.11 7.3.2.2 but without the length
- *	restriction (at most %NL80211_MAX_SUPP_RATES).
- * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
- *	to, or the AP interface the station was originally added to to.
- * @NL80211_ATTR_STA_INFO: information about a station, part of station info
- *	given for %NL80211_CMD_GET_STATION, nested attribute containing
- *	info as possible, see &enum nl80211_sta_info.
- *
- * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands,
- *	consisting of a nested array.
- *
- * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).
- * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link.
- * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
- * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
- * 	info given for %NL80211_CMD_GET_MPATH, nested attribute described at
- *	&enum nl80211_mpath_info.
- *
- * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
- *      &enum nl80211_mntr_flags.
- *
- * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the
- * 	current regulatory domain should be set to or is already set to.
- * 	For example, 'CR', for Costa Rica. This attribute is used by the kernel
- * 	to query the CRDA to retrieve one regulatory domain. This attribute can
- * 	also be used by userspace to query the kernel for the currently set
- * 	regulatory domain. We chose an alpha2 as that is also used by the
- * 	IEEE-802.11d country information element to identify a country.
- * 	Users can also simply ask the wireless core to set regulatory domain
- * 	to a specific alpha2.
- * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory
- *	rules.
- *
- * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1)
- * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled
- *	(u8, 0 or 1)
- * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled
- *	(u8, 0 or 1)
- * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic
- *	rates in format defined by IEEE 802.11 7.3.2.2 but without the length
- *	restriction (at most %NL80211_MAX_SUPP_RATES).
- *
- * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from
- *	association request when used with NL80211_CMD_NEW_STATION)
- *
- * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all
- *	supported interface types, each a flag attribute with the number
- *	of the interface mode.
- *
- * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for
- *	%NL80211_CMD_SET_MGMT_EXTRA_IE.
- *
- * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with
- *	%NL80211_CMD_SET_MGMT_EXTRA_IE).
- *
- * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with
- *	a single scan request, a wiphy attribute.
- * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements
- *	that can be added to a scan request
- *
- * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
- * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
- *	scanning and include a zero-length SSID (wildcard) for wildcard scan
- * @NL80211_ATTR_BSS: scan result BSS
- *
- * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
- * 	currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_*
- * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently
- * 	set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*)
- *
- * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies
- *	an array of command numbers (i.e. a mapping index to command number)
- *	that the driver for the given wiphy supports.
- *
- * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header
- *	and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and
- *	NL80211_CMD_ASSOCIATE events
- * @NL80211_ATTR_SSID: SSID (binary attribute, 0..32 octets)
- * @NL80211_ATTR_AUTH_TYPE: AuthenticationType, see &enum nl80211_auth_type,
- *	represented as a u32
- * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and
- *	%NL80211_CMD_DISASSOCIATE, u16
- *
- * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as
- *	a u32
- *
- * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change
- * 	due to considerations from a beacon hint. This attribute reflects
- * 	the state of the channel _before_ the beacon hint processing. This
- * 	attributes consists of a nested attribute containing
- * 	NL80211_FREQUENCY_ATTR_*
- * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change
- * 	due to considerations from a beacon hint. This attribute reflects
- * 	the state of the channel _after_ the beacon hint processing. This
- * 	attributes consists of a nested attribute containing
- * 	NL80211_FREQUENCY_ATTR_*
- *
- * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported
- *	cipher suites
- *
- * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look
- *	for other networks on different channels
- *
- * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this
- *	is used, e.g., with %NL80211_CMD_AUTHENTICATE event
- *
- * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is
- *	used for the association (&enum nl80211_mfp, represented as a u32);
- *	this attribute can be used
- *	with %NL80211_CMD_ASSOCIATE request
- *
- * @NL80211_ATTR_STA_FLAGS2: Attribute containing a
- *	&struct nl80211_sta_flag_update.
- *
- * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls
- *	IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in
- *	station mode. If the flag is included in %NL80211_CMD_ASSOCIATE
- *	request, the driver will assume that the port is unauthorized until
- *	authorized by user space. Otherwise, port is marked authorized by
- *	default in station mode.
- *
- * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
- *	We recommend using nested, driver-specific attributes within this.
- *
- * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT
- *	event was due to the AP disconnecting the station, and not due to
- *	a local disconnect request.
- * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT
- *	event (u16)
- * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating
- *	that protected APs should be used.
- *
- * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to
- *	indicate which unicast key ciphers will be used with the connection
- *	(an array of u32).
- * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate
- *	which group key cipher will be used with the connection (a u32).
- * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate
- *	which WPA version(s) the AP we want to associate with is using
- *	(a u32 with flags from &enum nl80211_wpa_versions).
- * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate
- *	which key management algorithm(s) to use (an array of u32).
- *
- * @NL80211_ATTR_REQ_IE: (Re)association request information elements as
- *	sent out by the card, for ROAM and successful CONNECT events.
- * @NL80211_ATTR_RESP_IE: (Re)association response information elements as
- *	sent by peer, for ROAM and successful CONNECT events.
- *
- * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE
- *	commands to specify using a reassociate frame
- *
- * @NL80211_ATTR_KEY: key information in a nested attribute with
- *	%NL80211_KEY_* sub-attributes
- * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect()
- *	and join_ibss(), key information is in a nested attribute each
- *	with %NL80211_KEY_* sub-attributes
- *
- * @NL80211_ATTR_PID: Process ID of a network namespace.
- *
- * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for
- *	dumps. This number increases whenever the object list being
- *	dumped changes, and as such userspace can verify that it has
- *	obtained a complete and consistent snapshot by verifying that
- *	all dump messages contain the same generation number. If it
- *	changed then the list changed and the dump should be repeated
- *	completely from scratch.
- *
- * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface
- *
- * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of
- *      the survey response for %NL80211_CMD_GET_SURVEY, nested attribute
- *      containing info as possible, see &enum survey_info.
- *
- * @NL80211_ATTR_MAX: highest attribute number currently defined
- * @__NL80211_ATTR_AFTER_LAST: internal use
- */
-enum nl80211_attrs {
-/* don't change the order or add anything inbetween, this is ABI! */
-	NL80211_ATTR_UNSPEC,
-
-	NL80211_ATTR_WIPHY,
-	NL80211_ATTR_WIPHY_NAME,
-
-	NL80211_ATTR_IFINDEX,
-	NL80211_ATTR_IFNAME,
-	NL80211_ATTR_IFTYPE,
-
-	NL80211_ATTR_MAC,
-
-	NL80211_ATTR_KEY_DATA,
-	NL80211_ATTR_KEY_IDX,
-	NL80211_ATTR_KEY_CIPHER,
-	NL80211_ATTR_KEY_SEQ,
-	NL80211_ATTR_KEY_DEFAULT,
-
-	NL80211_ATTR_BEACON_INTERVAL,
-	NL80211_ATTR_DTIM_PERIOD,
-	NL80211_ATTR_BEACON_HEAD,
-	NL80211_ATTR_BEACON_TAIL,
-
-	NL80211_ATTR_STA_AID,
-	NL80211_ATTR_STA_FLAGS,
-	NL80211_ATTR_STA_LISTEN_INTERVAL,
-	NL80211_ATTR_STA_SUPPORTED_RATES,
-	NL80211_ATTR_STA_VLAN,
-	NL80211_ATTR_STA_INFO,
-
-	NL80211_ATTR_WIPHY_BANDS,
-
-	NL80211_ATTR_MNTR_FLAGS,
-
-	NL80211_ATTR_MESH_ID,
-	NL80211_ATTR_STA_PLINK_ACTION,
-	NL80211_ATTR_MPATH_NEXT_HOP,
-	NL80211_ATTR_MPATH_INFO,
-
-	NL80211_ATTR_BSS_CTS_PROT,
-	NL80211_ATTR_BSS_SHORT_PREAMBLE,
-	NL80211_ATTR_BSS_SHORT_SLOT_TIME,
-
-	NL80211_ATTR_HT_CAPABILITY,
-
-	NL80211_ATTR_SUPPORTED_IFTYPES,
-
-	NL80211_ATTR_REG_ALPHA2,
-	NL80211_ATTR_REG_RULES,
-
-	NL80211_ATTR_MESH_PARAMS,
-
-	NL80211_ATTR_BSS_BASIC_RATES,
-
-	NL80211_ATTR_WIPHY_TXQ_PARAMS,
-	NL80211_ATTR_WIPHY_FREQ,
-	NL80211_ATTR_WIPHY_CHANNEL_TYPE,
-
-	NL80211_ATTR_KEY_DEFAULT_MGMT,
-
-	NL80211_ATTR_MGMT_SUBTYPE,
-	NL80211_ATTR_IE,
-
-	NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
-
-	NL80211_ATTR_SCAN_FREQUENCIES,
-	NL80211_ATTR_SCAN_SSIDS,
-	NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */
-	NL80211_ATTR_BSS,
-
-	NL80211_ATTR_REG_INITIATOR,
-	NL80211_ATTR_REG_TYPE,
-
-	NL80211_ATTR_SUPPORTED_COMMANDS,
-
-	NL80211_ATTR_FRAME,
-	NL80211_ATTR_SSID,
-	NL80211_ATTR_AUTH_TYPE,
-	NL80211_ATTR_REASON_CODE,
-
-	NL80211_ATTR_KEY_TYPE,
-
-	NL80211_ATTR_MAX_SCAN_IE_LEN,
-	NL80211_ATTR_CIPHER_SUITES,
-
-	NL80211_ATTR_FREQ_BEFORE,
-	NL80211_ATTR_FREQ_AFTER,
-
-	NL80211_ATTR_FREQ_FIXED,
-
-
-	NL80211_ATTR_WIPHY_RETRY_SHORT,
-	NL80211_ATTR_WIPHY_RETRY_LONG,
-	NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
-	NL80211_ATTR_WIPHY_RTS_THRESHOLD,
-
-	NL80211_ATTR_TIMED_OUT,
-
-	NL80211_ATTR_USE_MFP,
-
-	NL80211_ATTR_STA_FLAGS2,
-
-	NL80211_ATTR_CONTROL_PORT,
-
-	NL80211_ATTR_TESTDATA,
-
-	NL80211_ATTR_PRIVACY,
-
-	NL80211_ATTR_DISCONNECTED_BY_AP,
-	NL80211_ATTR_STATUS_CODE,
-
-	NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
-	NL80211_ATTR_CIPHER_SUITE_GROUP,
-	NL80211_ATTR_WPA_VERSIONS,
-	NL80211_ATTR_AKM_SUITES,
-
-	NL80211_ATTR_REQ_IE,
-	NL80211_ATTR_RESP_IE,
-
-	NL80211_ATTR_PREV_BSSID,
-
-	NL80211_ATTR_KEY,
-	NL80211_ATTR_KEYS,
-
-	NL80211_ATTR_PID,
-
-	NL80211_ATTR_4ADDR,
-
-	NL80211_ATTR_SURVEY_INFO,
-
-	/* add attributes here, update the policy in nl80211.c */
-
-	__NL80211_ATTR_AFTER_LAST,
-	NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
-};
-
-/* source-level API compatibility */
-#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
-
-/*
- * Allow user space programs to use #ifdef on new attributes by defining them
- * here
- */
-#define NL80211_CMD_CONNECT NL80211_CMD_CONNECT
-#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY
-#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES
-#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS
-#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ
-#define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE
-#define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE
-#define NL80211_ATTR_IE NL80211_ATTR_IE
-#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR
-#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE
-#define NL80211_ATTR_FRAME NL80211_ATTR_FRAME
-#define NL80211_ATTR_SSID NL80211_ATTR_SSID
-#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE
-#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE
-#define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE
-#define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP
-#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS
-#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES
-#define NL80211_ATTR_KEY NL80211_ATTR_KEY
-#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
-
-#define NL80211_MAX_SUPP_RATES			32
-#define NL80211_MAX_SUPP_REG_RULES		32
-#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY	0
-#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY	16
-#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY	24
-#define NL80211_HT_CAPABILITY_LEN		26
-
-#define NL80211_MAX_NR_CIPHER_SUITES		5
-#define NL80211_MAX_NR_AKM_SUITES		2
-
-/**
- * enum nl80211_iftype - (virtual) interface types
- *
- * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides
- * @NL80211_IFTYPE_ADHOC: independent BSS member
- * @NL80211_IFTYPE_STATION: managed BSS member
- * @NL80211_IFTYPE_AP: access point
- * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points
- * @NL80211_IFTYPE_WDS: wireless distribution interface
- * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
- * @NL80211_IFTYPE_MESH_POINT: mesh point
- * @NL80211_IFTYPE_MAX: highest interface type number currently defined
- * @__NL80211_IFTYPE_AFTER_LAST: internal use
- *
- * These values are used with the %NL80211_ATTR_IFTYPE
- * to set the type of an interface.
- *
- */
-enum nl80211_iftype {
-	NL80211_IFTYPE_UNSPECIFIED,
-	NL80211_IFTYPE_ADHOC,
-	NL80211_IFTYPE_STATION,
-	NL80211_IFTYPE_AP,
-	NL80211_IFTYPE_AP_VLAN,
-	NL80211_IFTYPE_WDS,
-	NL80211_IFTYPE_MONITOR,
-	NL80211_IFTYPE_MESH_POINT,
-
-	/* keep last */
-	__NL80211_IFTYPE_AFTER_LAST,
-	NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_sta_flags - station flags
- *
- * Station flags. When a station is added to an AP interface, it is
- * assumed to be already associated (and hence authenticated.)
- *
- * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X)
- * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames
- *	with short barker preamble
- * @NL80211_STA_FLAG_WME: station is WME/QoS capable
- * @NL80211_STA_FLAG_MFP: station uses management frame protection
- */
-enum nl80211_sta_flags {
-	__NL80211_STA_FLAG_INVALID,
-	NL80211_STA_FLAG_AUTHORIZED,
-	NL80211_STA_FLAG_SHORT_PREAMBLE,
-	NL80211_STA_FLAG_WME,
-	NL80211_STA_FLAG_MFP,
-
-	/* keep last */
-	__NL80211_STA_FLAG_AFTER_LAST,
-	NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1
-};
-
-/**
- * struct nl80211_sta_flag_update - station flags mask/set
- * @mask: mask of station flags to set
- * @set: which values to set them to
- *
- * Both mask and set contain bits as per &enum nl80211_sta_flags.
- */
-struct nl80211_sta_flag_update {
-	__u32 mask;
-	__u32 set;
-} __attribute__((packed));
-
-/**
- * enum nl80211_rate_info - bitrate information
- *
- * These attribute types are used with %NL80211_STA_INFO_TXRATE
- * when getting information about the bitrate of a station.
- *
- * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
- * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
- * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
- * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
- * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
- * @__NL80211_RATE_INFO_AFTER_LAST: internal use
- */
-enum nl80211_rate_info {
-	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_BITRATE,
-	NL80211_RATE_INFO_MCS,
-	NL80211_RATE_INFO_40_MHZ_WIDTH,
-	NL80211_RATE_INFO_SHORT_GI,
-
-	/* keep last */
-	__NL80211_RATE_INFO_AFTER_LAST,
-	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_sta_info - station information
- *
- * These attribute types are used with %NL80211_ATTR_STA_INFO
- * when getting information about a station.
- *
- * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs)
- * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station)
- * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
- * @__NL80211_STA_INFO_AFTER_LAST: internal
- * @NL80211_STA_INFO_MAX: highest possible station info attribute
- * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
- * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
- * 	containing info as possible, see &enum nl80211_sta_info_txrate.
- * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station)
- * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this
- *	station)
- */
-enum nl80211_sta_info {
-	__NL80211_STA_INFO_INVALID,
-	NL80211_STA_INFO_INACTIVE_TIME,
-	NL80211_STA_INFO_RX_BYTES,
-	NL80211_STA_INFO_TX_BYTES,
-	NL80211_STA_INFO_LLID,
-	NL80211_STA_INFO_PLID,
-	NL80211_STA_INFO_PLINK_STATE,
-	NL80211_STA_INFO_SIGNAL,
-	NL80211_STA_INFO_TX_BITRATE,
-	NL80211_STA_INFO_RX_PACKETS,
-	NL80211_STA_INFO_TX_PACKETS,
-
-	/* keep last */
-	__NL80211_STA_INFO_AFTER_LAST,
-	NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_mpath_flags - nl80211 mesh path flags
- *
- * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active
- * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running
- * @NL80211_MPATH_FLAG_SN_VALID: the mesh path contains a valid SN
- * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set
- * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded
- */
-enum nl80211_mpath_flags {
-	NL80211_MPATH_FLAG_ACTIVE =	1<<0,
-	NL80211_MPATH_FLAG_RESOLVING =	1<<1,
-	NL80211_MPATH_FLAG_SN_VALID =	1<<2,
-	NL80211_MPATH_FLAG_FIXED =	1<<3,
-	NL80211_MPATH_FLAG_RESOLVED =	1<<4,
-};
-
-/**
- * enum nl80211_mpath_info - mesh path information
- *
- * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting
- * information about a mesh path.
- *
- * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination
- * @NL80211_ATTR_MPATH_SN: destination sequence number
- * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path
- * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now
- * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in
- * 	&enum nl80211_mpath_flags;
- * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec
- * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries
- */
-enum nl80211_mpath_info {
-	__NL80211_MPATH_INFO_INVALID,
-	NL80211_MPATH_INFO_FRAME_QLEN,
-	NL80211_MPATH_INFO_SN,
-	NL80211_MPATH_INFO_METRIC,
-	NL80211_MPATH_INFO_EXPTIME,
-	NL80211_MPATH_INFO_FLAGS,
-	NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
-	NL80211_MPATH_INFO_DISCOVERY_RETRIES,
-
-	/* keep last */
-	__NL80211_MPATH_INFO_AFTER_LAST,
-	NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_band_attr - band attributes
- * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved
- * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band,
- *	an array of nested frequency attributes
- * @NL80211_BAND_ATTR_RATES: supported bitrates in this band,
- *	an array of nested bitrate attributes
- * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as
- *	defined in 802.11n
- * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE
- * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n
- * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n
- */
-enum nl80211_band_attr {
-	__NL80211_BAND_ATTR_INVALID,
-	NL80211_BAND_ATTR_FREQS,
-	NL80211_BAND_ATTR_RATES,
-
-	NL80211_BAND_ATTR_HT_MCS_SET,
-	NL80211_BAND_ATTR_HT_CAPA,
-	NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
-	NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
-
-	/* keep last */
-	__NL80211_BAND_ATTR_AFTER_LAST,
-	NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
-};
-
-#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
-
-/**
- * enum nl80211_frequency_attr - frequency attributes
- * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
- * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
- *	regulatory domain.
- * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is
- *	permitted on this channel in current regulatory domain.
- * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted
- *	on this channel in current regulatory domain.
- * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
- *	on this channel in current regulatory domain.
- * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
- *	(100 * dBm).
- */
-enum nl80211_frequency_attr {
-	__NL80211_FREQUENCY_ATTR_INVALID,
-	NL80211_FREQUENCY_ATTR_FREQ,
-	NL80211_FREQUENCY_ATTR_DISABLED,
-	NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
-	NL80211_FREQUENCY_ATTR_NO_IBSS,
-	NL80211_FREQUENCY_ATTR_RADAR,
-	NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
-
-	/* keep last */
-	__NL80211_FREQUENCY_ATTR_AFTER_LAST,
-	NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
-};
-
-#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
-
-/**
- * enum nl80211_bitrate_attr - bitrate attributes
- * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps
- * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported
- *	in 2.4 GHz band.
- */
-enum nl80211_bitrate_attr {
-	__NL80211_BITRATE_ATTR_INVALID,
-	NL80211_BITRATE_ATTR_RATE,
-	NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE,
-
-	/* keep last */
-	__NL80211_BITRATE_ATTR_AFTER_LAST,
-	NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_initiator - Indicates the initiator of a reg domain request
- * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world
- * 	regulatory domain.
- * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the
- * 	regulatory domain.
- * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the
- * 	wireless core it thinks its knows the regulatory domain we should be in.
- * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an
- * 	802.11 country information element with regulatory information it
- * 	thinks we should consider.
- */
-enum nl80211_reg_initiator {
-	NL80211_REGDOM_SET_BY_CORE,
-	NL80211_REGDOM_SET_BY_USER,
-	NL80211_REGDOM_SET_BY_DRIVER,
-	NL80211_REGDOM_SET_BY_COUNTRY_IE,
-};
-
-/**
- * enum nl80211_reg_type - specifies the type of regulatory domain
- * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains
- *	to a specific country. When this is set you can count on the
- *	ISO / IEC 3166 alpha2 country code being valid.
- * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory
- * 	domain.
- * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom
- * 	driver specific world regulatory domain. These do not apply system-wide
- * 	and are only applicable to the individual devices which have requested
- * 	them to be applied.
- * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product
- *	of an intersection between two regulatory domains -- the previously
- *	set regulatory domain on the system and the last accepted regulatory
- *	domain request to be processed.
- */
-enum nl80211_reg_type {
-	NL80211_REGDOM_TYPE_COUNTRY,
-	NL80211_REGDOM_TYPE_WORLD,
-	NL80211_REGDOM_TYPE_CUSTOM_WORLD,
-	NL80211_REGDOM_TYPE_INTERSECTION,
-};
-
-/**
- * enum nl80211_reg_rule_attr - regulatory rule attributes
- * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional
- * 	considerations for a given frequency range. These are the
- * 	&enum nl80211_reg_rule_flags.
- * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory
- * 	rule in KHz. This is not a center of frequency but an actual regulatory
- * 	band edge.
- * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule
- * 	in KHz. This is not a center a frequency but an actual regulatory
- * 	band edge.
- * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this
- * 	frequency range, in KHz.
- * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain
- * 	for a given frequency range. The value is in mBi (100 * dBi).
- * 	If you don't have one then don't send this.
- * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
- * 	a given frequency range. The value is in mBm (100 * dBm).
- */
-enum nl80211_reg_rule_attr {
-	__NL80211_REG_RULE_ATTR_INVALID,
-	NL80211_ATTR_REG_RULE_FLAGS,
-
-	NL80211_ATTR_FREQ_RANGE_START,
-	NL80211_ATTR_FREQ_RANGE_END,
-	NL80211_ATTR_FREQ_RANGE_MAX_BW,
-
-	NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
-	NL80211_ATTR_POWER_RULE_MAX_EIRP,
-
-	/* keep last */
-	__NL80211_REG_RULE_ATTR_AFTER_LAST,
-	NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_reg_rule_flags - regulatory rule flags
- *
- * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed
- * @NL80211_RRF_NO_CCK: CCK modulation not allowed
- * @NL80211_RRF_NO_INDOOR: indoor operation not allowed
- * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed
- * @NL80211_RRF_DFS: DFS support is required to be used
- * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
- * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
- * @NL80211_RRF_PASSIVE_SCAN: passive scan is required
- * @NL80211_RRF_NO_IBSS: no IBSS is allowed
- */
-enum nl80211_reg_rule_flags {
-	NL80211_RRF_NO_OFDM		= 1<<0,
-	NL80211_RRF_NO_CCK		= 1<<1,
-	NL80211_RRF_NO_INDOOR		= 1<<2,
-	NL80211_RRF_NO_OUTDOOR		= 1<<3,
-	NL80211_RRF_DFS			= 1<<4,
-	NL80211_RRF_PTP_ONLY		= 1<<5,
-	NL80211_RRF_PTMP_ONLY		= 1<<6,
-	NL80211_RRF_PASSIVE_SCAN	= 1<<7,
-	NL80211_RRF_NO_IBSS		= 1<<8,
-};
-
-/**
- * enum nl80211_survey_info - survey information
- *
- * These attribute types are used with %NL80211_ATTR_SURVEY_INFO
- * when getting information about a survey.
- *
- * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel
- * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
- */
-enum nl80211_survey_info {
-	__NL80211_SURVEY_INFO_INVALID,
-	NL80211_SURVEY_INFO_FREQUENCY,
-	NL80211_SURVEY_INFO_NOISE,
-
-	/* keep last */
-	__NL80211_SURVEY_INFO_AFTER_LAST,
-	NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_mntr_flags - monitor configuration flags
- *
- * Monitor configuration flags.
- *
- * @__NL80211_MNTR_FLAG_INVALID: reserved
- *
- * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS
- * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP
- * @NL80211_MNTR_FLAG_CONTROL: pass control frames
- * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering
- * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing.
- *	overrides all other flags.
- *
- * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
- * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
- */
-enum nl80211_mntr_flags {
-	__NL80211_MNTR_FLAG_INVALID,
-	NL80211_MNTR_FLAG_FCSFAIL,
-	NL80211_MNTR_FLAG_PLCPFAIL,
-	NL80211_MNTR_FLAG_CONTROL,
-	NL80211_MNTR_FLAG_OTHER_BSS,
-	NL80211_MNTR_FLAG_COOK_FRAMES,
-
-	/* keep last */
-	__NL80211_MNTR_FLAG_AFTER_LAST,
-	NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_meshconf_params - mesh configuration parameters
- *
- * Mesh configuration parameters
- *
- * @__NL80211_MESHCONF_INVALID: internal use
- *
- * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in
- * millisecond units, used by the Peer Link Open message
- *
- * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the inital confirm timeout, in
- * millisecond units, used by the peer link management to close a peer link
- *
- * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in
- * millisecond units
- *
- * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed
- * on this mesh interface
- *
- * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link
- * open retries that can be sent to establish a new peer link instance in a
- * mesh
- *
- * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh
- * point.
- *
- * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically
- * open peer links when we detect compatible mesh peers.
- *
- * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames
- * containing a PREQ that an MP can send to a particular destination (path
- * target)
- *
- * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths
- * (in milliseconds)
- *
- * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait
- * until giving up on a path discovery (in milliseconds)
- *
- * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh
- * points receiving a PREQ shall consider the forwarding information from the
- * root to be valid. (TU = time unit)
- *
- * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in
- * TUs) during which an MP can send only one action frame containing a PREQ
- * reference element
- *
- * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs)
- * that it takes for an HWMP information element to propagate across the mesh
- *
- * @NL80211_MESHCONF_ROOTMODE: whether root mode is enabled or not
- *
- * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
- *
- * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
- */
-enum nl80211_meshconf_params {
-	__NL80211_MESHCONF_INVALID,
-	NL80211_MESHCONF_RETRY_TIMEOUT,
-	NL80211_MESHCONF_CONFIRM_TIMEOUT,
-	NL80211_MESHCONF_HOLDING_TIMEOUT,
-	NL80211_MESHCONF_MAX_PEER_LINKS,
-	NL80211_MESHCONF_MAX_RETRIES,
-	NL80211_MESHCONF_TTL,
-	NL80211_MESHCONF_AUTO_OPEN_PLINKS,
-	NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
-	NL80211_MESHCONF_PATH_REFRESH_TIME,
-	NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
-	NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
-	NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
-	NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
-	NL80211_MESHCONF_HWMP_ROOTMODE,
-
-	/* keep last */
-	__NL80211_MESHCONF_ATTR_AFTER_LAST,
-	NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_txq_attr - TX queue parameter attributes
- * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved
- * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*)
- * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning
- *	disabled
- * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form
- *	2^n-1 in the range 1..32767]
- * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form
- *	2^n-1 in the range 1..32767]
- * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255]
- * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal
- * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number
- */
-enum nl80211_txq_attr {
-	__NL80211_TXQ_ATTR_INVALID,
-	NL80211_TXQ_ATTR_QUEUE,
-	NL80211_TXQ_ATTR_TXOP,
-	NL80211_TXQ_ATTR_CWMIN,
-	NL80211_TXQ_ATTR_CWMAX,
-	NL80211_TXQ_ATTR_AIFS,
-
-	/* keep last */
-	__NL80211_TXQ_ATTR_AFTER_LAST,
-	NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1
-};
-
-enum nl80211_txq_q {
-	NL80211_TXQ_Q_VO,
-	NL80211_TXQ_Q_VI,
-	NL80211_TXQ_Q_BE,
-	NL80211_TXQ_Q_BK
-};
-
-enum nl80211_channel_type {
-	NL80211_CHAN_NO_HT,
-	NL80211_CHAN_HT20,
-	NL80211_CHAN_HT40MINUS,
-	NL80211_CHAN_HT40PLUS
-};
-
-/**
- * enum nl80211_bss - netlink attributes for a BSS
- *
- * @__NL80211_BSS_INVALID: invalid
- * @NL80211_BSS_FREQUENCY: frequency in MHz (u32)
- * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64)
- * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16)
- * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16)
- * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the
- *	raw information elements from the probe response/beacon (bin)
- * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon
- *	in mBm (100 * dBm) (s32)
- * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
- *	in unspecified units, scaled to 0..100 (u8)
- * @NL80211_BSS_STATUS: status, if this BSS is "used"
- * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms
- * @__NL80211_BSS_AFTER_LAST: internal
- * @NL80211_BSS_MAX: highest BSS attribute
- */
-enum nl80211_bss {
-	__NL80211_BSS_INVALID,
-	NL80211_BSS_BSSID,
-	NL80211_BSS_FREQUENCY,
-	NL80211_BSS_TSF,
-	NL80211_BSS_BEACON_INTERVAL,
-	NL80211_BSS_CAPABILITY,
-	NL80211_BSS_INFORMATION_ELEMENTS,
-	NL80211_BSS_SIGNAL_MBM,
-	NL80211_BSS_SIGNAL_UNSPEC,
-	NL80211_BSS_STATUS,
-	NL80211_BSS_SEEN_MS_AGO,
-
-	/* keep last */
-	__NL80211_BSS_AFTER_LAST,
-	NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1
-};
-
-/**
- * enum nl80211_bss_status - BSS "status"
- */
-enum nl80211_bss_status {
-	NL80211_BSS_STATUS_AUTHENTICATED,
-	NL80211_BSS_STATUS_ASSOCIATED,
-	NL80211_BSS_STATUS_IBSS_JOINED,
-};
-
-/**
- * enum nl80211_auth_type - AuthenticationType
- *
- * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication
- * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only)
- * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r)
- * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP)
- * @__NL80211_AUTHTYPE_NUM: internal
- * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm
- * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by
- *	trying multiple times); this is invalid in netlink -- leave out
- *	the attribute for this on CONNECT commands.
- */
-enum nl80211_auth_type {
-	NL80211_AUTHTYPE_OPEN_SYSTEM,
-	NL80211_AUTHTYPE_SHARED_KEY,
-	NL80211_AUTHTYPE_FT,
-	NL80211_AUTHTYPE_NETWORK_EAP,
-
-	/* keep last */
-	__NL80211_AUTHTYPE_NUM,
-	NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1,
-	NL80211_AUTHTYPE_AUTOMATIC
-};
-
-/**
- * enum nl80211_key_type - Key Type
- * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key
- * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key
- * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS)
- */
-enum nl80211_key_type {
-	NL80211_KEYTYPE_GROUP,
-	NL80211_KEYTYPE_PAIRWISE,
-	NL80211_KEYTYPE_PEERKEY,
-};
-
-/**
- * enum nl80211_mfp - Management frame protection state
- * @NL80211_MFP_NO: Management frame protection not used
- * @NL80211_MFP_REQUIRED: Management frame protection required
- */
-enum nl80211_mfp {
-	NL80211_MFP_NO,
-	NL80211_MFP_REQUIRED,
-};
-
-enum nl80211_wpa_versions {
-	NL80211_WPA_VERSION_1 = 1 << 0,
-	NL80211_WPA_VERSION_2 = 1 << 1,
-};
-
-/**
- * enum nl80211_key_attributes - key attributes
- * @__NL80211_KEY_INVALID: invalid
- * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of
- *	16 bytes encryption key followed by 8 bytes each for TX and RX MIC
- *	keys
- * @NL80211_KEY_IDX: key ID (u8, 0-3)
- * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11
- *	section 7.3.2.25.1, e.g. 0x000FAC04)
- * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
- *	CCMP keys, each six bytes in little endian
- * @NL80211_KEY_DEFAULT: flag indicating default key
- * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key
- * @__NL80211_KEY_AFTER_LAST: internal
- * @NL80211_KEY_MAX: highest key attribute
- */
-enum nl80211_key_attributes {
-	__NL80211_KEY_INVALID,
-	NL80211_KEY_DATA,
-	NL80211_KEY_IDX,
-	NL80211_KEY_CIPHER,
-	NL80211_KEY_SEQ,
-	NL80211_KEY_DEFAULT,
-	NL80211_KEY_DEFAULT_MGMT,
-
-	/* keep last */
-	__NL80211_KEY_AFTER_LAST,
-	NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
-};
-
-#endif /* __LINUX_NL80211_H */
diff --git a/contrib/wpa/src/common/privsep_commands.h b/contrib/wpa/src/common/privsep_commands.h
index 81b7f5432ecc..cc900be9d20e 100644
--- a/contrib/wpa/src/common/privsep_commands.h
+++ b/contrib/wpa/src/common/privsep_commands.h
@@ -18,7 +18,6 @@
 enum privsep_cmd {
 	PRIVSEP_CMD_REGISTER,
 	PRIVSEP_CMD_UNREGISTER,
-	PRIVSEP_CMD_SET_WPA,
 	PRIVSEP_CMD_SCAN,
 	PRIVSEP_CMD_GET_SCAN_RESULTS,
 	PRIVSEP_CMD_ASSOCIATE,
@@ -30,7 +29,6 @@ enum privsep_cmd {
 	PRIVSEP_CMD_L2_UNREGISTER,
 	PRIVSEP_CMD_L2_NOTIFY_AUTH_START,
 	PRIVSEP_CMD_L2_SEND,
-	PRIVSEP_CMD_SET_MODE,
 	PRIVSEP_CMD_SET_COUNTRY,
 };
 
@@ -72,7 +70,6 @@ enum privsep_event {
 	PRIVSEP_EVENT_STKSTART,
 	PRIVSEP_EVENT_FT_RESPONSE,
 	PRIVSEP_EVENT_RX_EAPOL,
-	PRIVSEP_EVENT_STA_RX,
 };
 
 #endif /* PRIVSEP_COMMANDS_H */
diff --git a/contrib/wpa/src/common/version.h b/contrib/wpa/src/common/version.h
index b79c4949c4da..02f34be3ab12 100644
--- a/contrib/wpa/src/common/version.h
+++ b/contrib/wpa/src/common/version.h
@@ -1,6 +1,6 @@
 #ifndef VERSION_H
 #define VERSION_H
 
-#define VERSION_STR "0.6.10"
+#define VERSION_STR "0.7.3"
 
 #endif /* VERSION_H */
diff --git a/contrib/wpa/src/common/wireless_copy.h b/contrib/wpa/src/common/wireless_copy.h
deleted file mode 100644
index ad764663766f..000000000000
--- a/contrib/wpa/src/common/wireless_copy.h
+++ /dev/null
@@ -1,1099 +0,0 @@
-/* This is based on Linux Wireless Extensions header file from WIRELESS_EXT 18.
- * I have just removed kernel related headers and added some typedefs etc. to
- * make this easier to include into user space programs.
- * Jouni Malinen, 2005-03-12.
- */
-
-
-/*
- * This file define a set of standard wireless extensions
- *
- * Version :	19	18.3.05
- *
- * Authors :	Jean Tourrilhes - HPL - 
- * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
- */
-
-#ifndef _LINUX_WIRELESS_H
-#define _LINUX_WIRELESS_H
-
-/************************** DOCUMENTATION **************************/
-/*
- * Initial APIs (1996 -> onward) :
- * -----------------------------
- * Basically, the wireless extensions are for now a set of standard ioctl
- * call + /proc/net/wireless
- *
- * The entry /proc/net/wireless give statistics and information on the
- * driver.
- * This is better than having each driver having its entry because
- * its centralised and we may remove the driver module safely.
- *
- * Ioctl are used to configure the driver and issue commands.  This is
- * better than command line options of insmod because we may want to
- * change dynamically (while the driver is running) some parameters.
- *
- * The ioctl mechanimsm are copied from standard devices ioctl.
- * We have the list of command plus a structure descibing the
- * data exchanged...
- * Note that to add these ioctl, I was obliged to modify :
- *	# net/core/dev.c (two place + add include)
- *	# net/ipv4/af_inet.c (one place + add include)
- *
- * /proc/net/wireless is a copy of /proc/net/dev.
- * We have a structure for data passed from the driver to /proc/net/wireless
- * Too add this, I've modified :
- *	# net/core/dev.c (two other places)
- *	# include/linux/netdevice.h (one place)
- *	# include/linux/proc_fs.h (one place)
- *
- * New driver API (2002 -> onward) :
- * -------------------------------
- * This file is only concerned with the user space API and common definitions.
- * The new driver API is defined and documented in :
- *	# include/net/iw_handler.h
- *
- * Note as well that /proc/net/wireless implementation has now moved in :
- *	# net/core/wireless.c
- *
- * Wireless Events (2002 -> onward) :
- * --------------------------------
- * Events are defined at the end of this file, and implemented in :
- *	# net/core/wireless.c
- *
- * Other comments :
- * --------------
- * Do not add here things that are redundant with other mechanisms
- * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
- * wireless specific.
- *
- * These wireless extensions are not magic : each driver has to provide
- * support for them...
- *
- * IMPORTANT NOTE : As everything in the kernel, this is very much a
- * work in progress. Contact me if you have ideas of improvements...
- */
-
-/***************************** INCLUDES *****************************/
-
- /* jkm - replaced linux headers with C library headers, added typedefs */
-#if 0
-/* To minimise problems in user space, I might remove those headers
- * at some point. Jean II */
-#include 		/* for "caddr_t" et al		*/
-#include 		/* for "struct sockaddr" et al	*/
-#include 			/* for IFNAMSIZ and co... */
-#else
-#include 
-#include 
-typedef __uint32_t __u32;
-typedef __int32_t __s32;
-typedef __uint16_t __u16;
-typedef __int16_t __s16;
-typedef __uint8_t __u8;
-#ifndef __user
-#define __user
-#endif /* __user */
-#endif
-
-/***************************** VERSION *****************************/
-/*
- * This constant is used to know the availability of the wireless
- * extensions and to know which version of wireless extensions it is
- * (there is some stuff that will be added in the future...)
- * I just plan to increment with each new version.
- */
-#define WIRELESS_EXT	19
-
-/*
- * Changes :
- *
- * V2 to V3
- * --------
- *	Alan Cox start some incompatibles changes. I've integrated a bit more.
- *	- Encryption renamed to Encode to avoid US regulation problems
- *	- Frequency changed from float to struct to avoid problems on old 386
- *
- * V3 to V4
- * --------
- *	- Add sensitivity
- *
- * V4 to V5
- * --------
- *	- Missing encoding definitions in range
- *	- Access points stuff
- *
- * V5 to V6
- * --------
- *	- 802.11 support (ESSID ioctls)
- *
- * V6 to V7
- * --------
- *	- define IW_ESSID_MAX_SIZE and IW_MAX_AP
- *
- * V7 to V8
- * --------
- *	- Changed my e-mail address
- *	- More 802.11 support (nickname, rate, rts, frag)
- *	- List index in frequencies
- *
- * V8 to V9
- * --------
- *	- Support for 'mode of operation' (ad-hoc, managed...)
- *	- Support for unicast and multicast power saving
- *	- Change encoding to support larger tokens (>64 bits)
- *	- Updated iw_params (disable, flags) and use it for NWID
- *	- Extracted iw_point from iwreq for clarity
- *
- * V9 to V10
- * ---------
- *	- Add PM capability to range structure
- *	- Add PM modifier : MAX/MIN/RELATIVE
- *	- Add encoding option : IW_ENCODE_NOKEY
- *	- Add TxPower ioctls (work like TxRate)
- *
- * V10 to V11
- * ----------
- *	- Add WE version in range (help backward/forward compatibility)
- *	- Add retry ioctls (work like PM)
- *
- * V11 to V12
- * ----------
- *	- Add SIOCSIWSTATS to get /proc/net/wireless programatically
- *	- Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
- *	- Add new statistics (frag, retry, beacon)
- *	- Add average quality (for user space calibration)
- *
- * V12 to V13
- * ----------
- *	- Document creation of new driver API.
- *	- Extract union iwreq_data from struct iwreq (for new driver API).
- *	- Rename SIOCSIWNAME as SIOCSIWCOMMIT
- *
- * V13 to V14
- * ----------
- *	- Wireless Events support : define struct iw_event
- *	- Define additional specific event numbers
- *	- Add "addr" and "param" fields in union iwreq_data
- *	- AP scanning stuff (SIOCSIWSCAN and friends)
- *
- * V14 to V15
- * ----------
- *	- Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
- *	- Make struct iw_freq signed (both m & e), add explicit padding
- *	- Add IWEVCUSTOM for driver specific event/scanning token
- *	- Add IW_MAX_GET_SPY for driver returning a lot of addresses
- *	- Add IW_TXPOW_RANGE for range of Tx Powers
- *	- Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
- *	- Add IW_MODE_MONITOR for passive monitor
- *
- * V15 to V16
- * ----------
- *	- Increase the number of bitrates in iw_range to 32 (for 802.11g)
- *	- Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
- *	- Reshuffle struct iw_range for increases, add filler
- *	- Increase IW_MAX_AP to 64 for driver returning a lot of addresses
- *	- Remove IW_MAX_GET_SPY because conflict with enhanced spy support
- *	- Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
- *	- Add IW_ENCODE_TEMP and iw_range->encoding_login_index
- *
- * V16 to V17
- * ----------
- *	- Add flags to frequency -> auto/fixed
- *	- Document (struct iw_quality *)->updated, add new flags (INVALID)
- *	- Wireless Event capability in struct iw_range
- *	- Add support for relative TxPower (yick !)
- *
- * V17 to V18 (From Jouni Malinen )
- * ----------
- *	- Add support for WPA/WPA2
- *	- Add extended encoding configuration (SIOCSIWENCODEEXT and
- *	  SIOCGIWENCODEEXT)
- *	- Add SIOCSIWGENIE/SIOCGIWGENIE
- *	- Add SIOCSIWMLME
- *	- Add SIOCSIWPMKSA
- *	- Add struct iw_range bit field for supported encoding capabilities
- *	- Add optional scan request parameters for SIOCSIWSCAN
- *	- Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
- *	  related parameters (extensible up to 4096 parameter values)
- *	- Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
- *	  IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
- *
- * V18 to V19
- * ----------
- *	- Remove (struct iw_point *)->pointer from events and streams
- *	- Remove header includes to help user space
- *	- Increase IW_ENCODING_TOKEN_MAX from 32 to 64
- *	- Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
- *	- Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
- *	- Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
- */
-
-/**************************** CONSTANTS ****************************/
-
-/* -------------------------- IOCTL LIST -------------------------- */
-
-/* Wireless Identification */
-#define SIOCSIWCOMMIT	0x8B00		/* Commit pending changes to driver */
-#define SIOCGIWNAME	0x8B01		/* get name == wireless protocol */
-/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
- * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
- * Don't put the name of your driver there, it's useless. */
-
-/* Basic operations */
-#define SIOCSIWNWID	0x8B02		/* set network id (pre-802.11) */
-#define SIOCGIWNWID	0x8B03		/* get network id (the cell) */
-#define SIOCSIWFREQ	0x8B04		/* set channel/frequency (Hz) */
-#define SIOCGIWFREQ	0x8B05		/* get channel/frequency (Hz) */
-#define SIOCSIWMODE	0x8B06		/* set operation mode */
-#define SIOCGIWMODE	0x8B07		/* get operation mode */
-#define SIOCSIWSENS	0x8B08		/* set sensitivity (dBm) */
-#define SIOCGIWSENS	0x8B09		/* get sensitivity (dBm) */
-
-/* Informative stuff */
-#define SIOCSIWRANGE	0x8B0A		/* Unused */
-#define SIOCGIWRANGE	0x8B0B		/* Get range of parameters */
-#define SIOCSIWPRIV	0x8B0C		/* Unused */
-#define SIOCGIWPRIV	0x8B0D		/* get private ioctl interface info */
-#define SIOCSIWSTATS	0x8B0E		/* Unused */
-#define SIOCGIWSTATS	0x8B0F		/* Get /proc/net/wireless stats */
-/* SIOCGIWSTATS is strictly used between user space and the kernel, and
- * is never passed to the driver (i.e. the driver will never see it). */
-
-/* Spy support (statistics per MAC address - used for Mobile IP support) */
-#define SIOCSIWSPY	0x8B10		/* set spy addresses */
-#define SIOCGIWSPY	0x8B11		/* get spy info (quality of link) */
-#define SIOCSIWTHRSPY	0x8B12		/* set spy threshold (spy event) */
-#define SIOCGIWTHRSPY	0x8B13		/* get spy threshold */
-
-/* Access Point manipulation */
-#define SIOCSIWAP	0x8B14		/* set access point MAC addresses */
-#define SIOCGIWAP	0x8B15		/* get access point MAC addresses */
-#define SIOCGIWAPLIST	0x8B17		/* Deprecated in favor of scanning */
-#define SIOCSIWSCAN	0x8B18		/* trigger scanning (list cells) */
-#define SIOCGIWSCAN	0x8B19		/* get scanning results */
-
-/* 802.11 specific support */
-#define SIOCSIWESSID	0x8B1A		/* set ESSID (network name) */
-#define SIOCGIWESSID	0x8B1B		/* get ESSID */
-#define SIOCSIWNICKN	0x8B1C		/* set node name/nickname */
-#define SIOCGIWNICKN	0x8B1D		/* get node name/nickname */
-/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
- * within the 'iwreq' structure, so we need to use the 'data' member to
- * point to a string in user space, like it is done for RANGE... */
-
-/* Other parameters useful in 802.11 and some other devices */
-#define SIOCSIWRATE	0x8B20		/* set default bit rate (bps) */
-#define SIOCGIWRATE	0x8B21		/* get default bit rate (bps) */
-#define SIOCSIWRTS	0x8B22		/* set RTS/CTS threshold (bytes) */
-#define SIOCGIWRTS	0x8B23		/* get RTS/CTS threshold (bytes) */
-#define SIOCSIWFRAG	0x8B24		/* set fragmentation thr (bytes) */
-#define SIOCGIWFRAG	0x8B25		/* get fragmentation thr (bytes) */
-#define SIOCSIWTXPOW	0x8B26		/* set transmit power (dBm) */
-#define SIOCGIWTXPOW	0x8B27		/* get transmit power (dBm) */
-#define SIOCSIWRETRY	0x8B28		/* set retry limits and lifetime */
-#define SIOCGIWRETRY	0x8B29		/* get retry limits and lifetime */
-
-/* Encoding stuff (scrambling, hardware security, WEP...) */
-#define SIOCSIWENCODE	0x8B2A		/* set encoding token & mode */
-#define SIOCGIWENCODE	0x8B2B		/* get encoding token & mode */
-/* Power saving stuff (power management, unicast and multicast) */
-#define SIOCSIWPOWER	0x8B2C		/* set Power Management settings */
-#define SIOCGIWPOWER	0x8B2D		/* get Power Management settings */
-
-/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
- * This ioctl uses struct iw_point and data buffer that includes IE id and len
- * fields. More than one IE may be included in the request. Setting the generic
- * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
- * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
- * are required to report the used IE as a wireless event, e.g., when
- * associating with an AP. */
-#define SIOCSIWGENIE	0x8B30		/* set generic IE */
-#define SIOCGIWGENIE	0x8B31		/* get generic IE */
-
-/* WPA : IEEE 802.11 MLME requests */
-#define SIOCSIWMLME	0x8B16		/* request MLME operation; uses
-					 * struct iw_mlme */
-/* WPA : Authentication mode parameters */
-#define SIOCSIWAUTH	0x8B32		/* set authentication mode params */
-#define SIOCGIWAUTH	0x8B33		/* get authentication mode params */
-
-/* WPA : Extended version of encoding configuration */
-#define SIOCSIWENCODEEXT 0x8B34		/* set encoding token & mode */
-#define SIOCGIWENCODEEXT 0x8B35		/* get encoding token & mode */
-
-/* WPA2 : PMKSA cache management */
-#define SIOCSIWPMKSA	0x8B36		/* PMKSA cache operation */
-
-/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
-
-/* These 32 ioctl are wireless device private, for 16 commands.
- * Each driver is free to use them for whatever purpose it chooses,
- * however the driver *must* export the description of those ioctls
- * with SIOCGIWPRIV and *must* use arguments as defined below.
- * If you don't follow those rules, DaveM is going to hate you (reason :
- * it make mixed 32/64bit operation impossible).
- */
-#define SIOCIWFIRSTPRIV	0x8BE0
-#define SIOCIWLASTPRIV	0x8BFF
-/* Previously, we were using SIOCDEVPRIVATE, but we now have our
- * separate range because of collisions with other tools such as
- * 'mii-tool'.
- * We now have 32 commands, so a bit more space ;-).
- * Also, all 'odd' commands are only usable by root and don't return the
- * content of ifr/iwr to user (but you are not obliged to use the set/get
- * convention, just use every other two command). More details in iwpriv.c.
- * And I repeat : you are not forced to use them with iwpriv, but you
- * must be compliant with it.
- */
-
-/* ------------------------- IOCTL STUFF ------------------------- */
-
-/* The first and the last (range) */
-#define SIOCIWFIRST	0x8B00
-#define SIOCIWLAST	SIOCIWLASTPRIV		/* 0x8BFF */
-#define IW_IOCTL_IDX(cmd)	((cmd) - SIOCIWFIRST)
-
-/* Even : get (world access), odd : set (root access) */
-#define IW_IS_SET(cmd)	(!((cmd) & 0x1))
-#define IW_IS_GET(cmd)	((cmd) & 0x1)
-
-/* ----------------------- WIRELESS EVENTS ----------------------- */
-/* Those are *NOT* ioctls, do not issue request on them !!! */
-/* Most events use the same identifier as ioctl requests */
-
-#define IWEVTXDROP	0x8C00		/* Packet dropped to excessive retry */
-#define IWEVQUAL	0x8C01		/* Quality part of statistics (scan) */
-#define IWEVCUSTOM	0x8C02		/* Driver specific ascii string */
-#define IWEVREGISTERED	0x8C03		/* Discovered a new node (AP mode) */
-#define IWEVEXPIRED	0x8C04		/* Expired a node (AP mode) */
-#define IWEVGENIE	0x8C05		/* Generic IE (WPA, RSN, WMM, ..)
-					 * (scan results); This includes id and
-					 * length fields. One IWEVGENIE may
-					 * contain more than one IE. Scan
-					 * results may contain one or more
-					 * IWEVGENIE events. */
-#define IWEVMICHAELMICFAILURE 0x8C06	/* Michael MIC failure
-					 * (struct iw_michaelmicfailure)
-					 */
-#define IWEVASSOCREQIE	0x8C07		/* IEs used in (Re)Association Request.
-					 * The data includes id and length
-					 * fields and may contain more than one
-					 * IE. This event is required in
-					 * Managed mode if the driver
-					 * generates its own WPA/RSN IE. This
-					 * should be sent just before
-					 * IWEVREGISTERED event for the
-					 * association. */
-#define IWEVASSOCRESPIE	0x8C08		/* IEs used in (Re)Association
-					 * Response. The data includes id and
-					 * length fields and may contain more
-					 * than one IE. This may be sent
-					 * between IWEVASSOCREQIE and
-					 * IWEVREGISTERED events for the
-					 * association. */
-#define IWEVPMKIDCAND	0x8C09		/* PMKID candidate for RSN
-					 * pre-authentication
-					 * (struct iw_pmkid_cand) */
-
-#define IWEVFIRST	0x8C00
-#define IW_EVENT_IDX(cmd)	((cmd) - IWEVFIRST)
-
-/* ------------------------- PRIVATE INFO ------------------------- */
-/*
- * The following is used with SIOCGIWPRIV. It allow a driver to define
- * the interface (name, type of data) for its private ioctl.
- * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
- */
-
-#define IW_PRIV_TYPE_MASK	0x7000	/* Type of arguments */
-#define IW_PRIV_TYPE_NONE	0x0000
-#define IW_PRIV_TYPE_BYTE	0x1000	/* Char as number */
-#define IW_PRIV_TYPE_CHAR	0x2000	/* Char as character */
-#define IW_PRIV_TYPE_INT	0x4000	/* 32 bits int */
-#define IW_PRIV_TYPE_FLOAT	0x5000	/* struct iw_freq */
-#define IW_PRIV_TYPE_ADDR	0x6000	/* struct sockaddr */
-
-#define IW_PRIV_SIZE_FIXED	0x0800	/* Variable or fixed number of args */
-
-#define IW_PRIV_SIZE_MASK	0x07FF	/* Max number of those args */
-
-/*
- * Note : if the number of args is fixed and the size < 16 octets,
- * instead of passing a pointer we will put args in the iwreq struct...
- */
-
-/* ----------------------- OTHER CONSTANTS ----------------------- */
-
-/* Maximum frequencies in the range struct */
-#define IW_MAX_FREQUENCIES	32
-/* Note : if you have something like 80 frequencies,
- * don't increase this constant and don't fill the frequency list.
- * The user will be able to set by channel anyway... */
-
-/* Maximum bit rates in the range struct */
-#define IW_MAX_BITRATES		32
-
-/* Maximum tx powers in the range struct */
-#define IW_MAX_TXPOWER		8
-/* Note : if you more than 8 TXPowers, just set the max and min or
- * a few of them in the struct iw_range. */
-
-/* Maximum of address that you may set with SPY */
-#define IW_MAX_SPY		8
-
-/* Maximum of address that you may get in the
-   list of access points in range */
-#define IW_MAX_AP		64
-
-/* Maximum size of the ESSID and NICKN strings */
-#define IW_ESSID_MAX_SIZE	32
-
-/* Modes of operation */
-#define IW_MODE_AUTO	0	/* Let the driver decides */
-#define IW_MODE_ADHOC	1	/* Single cell network */
-#define IW_MODE_INFRA	2	/* Multi cell network, roaming, ... */
-#define IW_MODE_MASTER	3	/* Synchronisation master or Access Point */
-#define IW_MODE_REPEAT	4	/* Wireless Repeater (forwarder) */
-#define IW_MODE_SECOND	5	/* Secondary master/repeater (backup) */
-#define IW_MODE_MONITOR	6	/* Passive monitor (listen only) */
-
-/* Statistics flags (bitmask in updated) */
-#define IW_QUAL_QUAL_UPDATED	0x01	/* Value was updated since last read */
-#define IW_QUAL_LEVEL_UPDATED	0x02
-#define IW_QUAL_NOISE_UPDATED	0x04
-#define IW_QUAL_ALL_UPDATED	0x07
-#define IW_QUAL_DBM		0x08	/* Level + Noise are dBm */
-#define IW_QUAL_QUAL_INVALID	0x10	/* Driver doesn't provide value */
-#define IW_QUAL_LEVEL_INVALID	0x20
-#define IW_QUAL_NOISE_INVALID	0x40
-#define IW_QUAL_ALL_INVALID	0x70
-
-/* Frequency flags */
-#define IW_FREQ_AUTO		0x00	/* Let the driver decides */
-#define IW_FREQ_FIXED		0x01	/* Force a specific value */
-
-/* Maximum number of size of encoding token available
- * they are listed in the range structure */
-#define IW_MAX_ENCODING_SIZES	8
-
-/* Maximum size of the encoding token in bytes */
-#define IW_ENCODING_TOKEN_MAX	64	/* 512 bits (for now) */
-
-/* Flags for encoding (along with the token) */
-#define IW_ENCODE_INDEX		0x00FF	/* Token index (if needed) */
-#define IW_ENCODE_FLAGS		0xFF00	/* Flags defined below */
-#define IW_ENCODE_MODE		0xF000	/* Modes defined below */
-#define IW_ENCODE_DISABLED	0x8000	/* Encoding disabled */
-#define IW_ENCODE_ENABLED	0x0000	/* Encoding enabled */
-#define IW_ENCODE_RESTRICTED	0x4000	/* Refuse non-encoded packets */
-#define IW_ENCODE_OPEN		0x2000	/* Accept non-encoded packets */
-#define IW_ENCODE_NOKEY		0x0800  /* Key is write only, so not present */
-#define IW_ENCODE_TEMP		0x0400  /* Temporary key */
-
-/* Power management flags available (along with the value, if any) */
-#define IW_POWER_ON		0x0000	/* No details... */
-#define IW_POWER_TYPE		0xF000	/* Type of parameter */
-#define IW_POWER_PERIOD		0x1000	/* Value is a period/duration of  */
-#define IW_POWER_TIMEOUT	0x2000	/* Value is a timeout (to go asleep) */
-#define IW_POWER_MODE		0x0F00	/* Power Management mode */
-#define IW_POWER_UNICAST_R	0x0100	/* Receive only unicast messages */
-#define IW_POWER_MULTICAST_R	0x0200	/* Receive only multicast messages */
-#define IW_POWER_ALL_R		0x0300	/* Receive all messages though PM */
-#define IW_POWER_FORCE_S	0x0400	/* Force PM procedure for sending unicast */
-#define IW_POWER_REPEATER	0x0800	/* Repeat broadcast messages in PM period */
-#define IW_POWER_MODIFIER	0x000F	/* Modify a parameter */
-#define IW_POWER_MIN		0x0001	/* Value is a minimum  */
-#define IW_POWER_MAX		0x0002	/* Value is a maximum */
-#define IW_POWER_RELATIVE	0x0004	/* Value is not in seconds/ms/us */
-
-/* Transmit Power flags available */
-#define IW_TXPOW_TYPE		0x00FF	/* Type of value */
-#define IW_TXPOW_DBM		0x0000	/* Value is in dBm */
-#define IW_TXPOW_MWATT		0x0001	/* Value is in mW */
-#define IW_TXPOW_RELATIVE	0x0002	/* Value is in arbitrary units */
-#define IW_TXPOW_RANGE		0x1000	/* Range of value between min/max */
-
-/* Retry limits and lifetime flags available */
-#define IW_RETRY_ON		0x0000	/* No details... */
-#define IW_RETRY_TYPE		0xF000	/* Type of parameter */
-#define IW_RETRY_LIMIT		0x1000	/* Maximum number of retries*/
-#define IW_RETRY_LIFETIME	0x2000	/* Maximum duration of retries in us */
-#define IW_RETRY_MODIFIER	0x000F	/* Modify a parameter */
-#define IW_RETRY_MIN		0x0001	/* Value is a minimum  */
-#define IW_RETRY_MAX		0x0002	/* Value is a maximum */
-#define IW_RETRY_RELATIVE	0x0004	/* Value is not in seconds/ms/us */
-
-/* Scanning request flags */
-#define IW_SCAN_DEFAULT		0x0000	/* Default scan of the driver */
-#define IW_SCAN_ALL_ESSID	0x0001	/* Scan all ESSIDs */
-#define IW_SCAN_THIS_ESSID	0x0002	/* Scan only this ESSID */
-#define IW_SCAN_ALL_FREQ	0x0004	/* Scan all Frequencies */
-#define IW_SCAN_THIS_FREQ	0x0008	/* Scan only this Frequency */
-#define IW_SCAN_ALL_MODE	0x0010	/* Scan all Modes */
-#define IW_SCAN_THIS_MODE	0x0020	/* Scan only this Mode */
-#define IW_SCAN_ALL_RATE	0x0040	/* Scan all Bit-Rates */
-#define IW_SCAN_THIS_RATE	0x0080	/* Scan only this Bit-Rate */
-/* struct iw_scan_req scan_type */
-#define IW_SCAN_TYPE_ACTIVE 0
-#define IW_SCAN_TYPE_PASSIVE 1
-/* Maximum size of returned data */
-#define IW_SCAN_MAX_DATA	4096	/* In bytes */
-
-/* Max number of char in custom event - use multiple of them if needed */
-#define IW_CUSTOM_MAX		256	/* In bytes */
-
-/* Generic information element */
-#define IW_GENERIC_IE_MAX	1024
-
-/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
-#define IW_MLME_DEAUTH		0
-#define IW_MLME_DISASSOC	1
-
-/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
-#define IW_AUTH_INDEX		0x0FFF
-#define IW_AUTH_FLAGS		0xF000
-/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
- * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
- * parameter that is being set/get to; value will be read/written to
- * struct iw_param value field) */
-#define IW_AUTH_WPA_VERSION		0
-#define IW_AUTH_CIPHER_PAIRWISE		1
-#define IW_AUTH_CIPHER_GROUP		2
-#define IW_AUTH_KEY_MGMT		3
-#define IW_AUTH_TKIP_COUNTERMEASURES	4
-#define IW_AUTH_DROP_UNENCRYPTED	5
-#define IW_AUTH_80211_AUTH_ALG		6
-#define IW_AUTH_WPA_ENABLED		7
-#define IW_AUTH_RX_UNENCRYPTED_EAPOL	8
-#define IW_AUTH_ROAMING_CONTROL		9
-#define IW_AUTH_PRIVACY_INVOKED		10
-#define IW_AUTH_CIPHER_GROUP_MGMT	11
-#define IW_AUTH_MFP			12
-
-/* IW_AUTH_WPA_VERSION values (bit field) */
-#define IW_AUTH_WPA_VERSION_DISABLED	0x00000001
-#define IW_AUTH_WPA_VERSION_WPA		0x00000002
-#define IW_AUTH_WPA_VERSION_WPA2	0x00000004
-
-/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
-#define IW_AUTH_CIPHER_NONE	0x00000001
-#define IW_AUTH_CIPHER_WEP40	0x00000002
-#define IW_AUTH_CIPHER_TKIP	0x00000004
-#define IW_AUTH_CIPHER_CCMP	0x00000008
-#define IW_AUTH_CIPHER_WEP104	0x00000010
-
-/* IW_AUTH_KEY_MGMT values (bit field) */
-#define IW_AUTH_KEY_MGMT_802_1X	1
-#define IW_AUTH_KEY_MGMT_PSK	2
-
-/* IW_AUTH_80211_AUTH_ALG values (bit field) */
-#define IW_AUTH_ALG_OPEN_SYSTEM	0x00000001
-#define IW_AUTH_ALG_SHARED_KEY	0x00000002
-#define IW_AUTH_ALG_LEAP	0x00000004
-
-/* IW_AUTH_ROAMING_CONTROL values */
-#define IW_AUTH_ROAMING_ENABLE	0	/* driver/firmware based roaming */
-#define IW_AUTH_ROAMING_DISABLE	1	/* user space program used for roaming
-					 * control */
-
-/* IW_AUTH_MFP (management frame protection) values */
-#define IW_AUTH_MFP_DISABLED	0	/* MFP disabled */
-#define IW_AUTH_MFP_OPTIONAL	1	/* MFP optional */
-#define IW_AUTH_MFP_REQUIRED	2	/* MFP required */
-
-/* SIOCSIWENCODEEXT definitions */
-#define IW_ENCODE_SEQ_MAX_SIZE	8
-/* struct iw_encode_ext ->alg */
-#define IW_ENCODE_ALG_NONE	0
-#define IW_ENCODE_ALG_WEP	1
-#define IW_ENCODE_ALG_TKIP	2
-#define IW_ENCODE_ALG_CCMP	3
-#define IW_ENCODE_ALG_PMK	4
-#define IW_ENCODE_ALG_AES_CMAC	5
-/* struct iw_encode_ext ->ext_flags */
-#define IW_ENCODE_EXT_TX_SEQ_VALID	0x00000001
-#define IW_ENCODE_EXT_RX_SEQ_VALID	0x00000002
-#define IW_ENCODE_EXT_GROUP_KEY		0x00000004
-#define IW_ENCODE_EXT_SET_TX_KEY	0x00000008
-
-/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
-#define IW_MICFAILURE_KEY_ID	0x00000003 /* Key ID 0..3 */
-#define IW_MICFAILURE_GROUP	0x00000004
-#define IW_MICFAILURE_PAIRWISE	0x00000008
-#define IW_MICFAILURE_STAKEY	0x00000010
-#define IW_MICFAILURE_COUNT	0x00000060 /* 1 or 2 (0 = count not supported)
-					    */
-
-/* Bit field values for enc_capa in struct iw_range */
-#define IW_ENC_CAPA_WPA		0x00000001
-#define IW_ENC_CAPA_WPA2	0x00000002
-#define IW_ENC_CAPA_CIPHER_TKIP	0x00000004
-#define IW_ENC_CAPA_CIPHER_CCMP	0x00000008
-#define IW_ENC_CAPA_4WAY_HANDSHAKE	0x00000010
-
-/* Event capability macros - in (struct iw_range *)->event_capa
- * Because we have more than 32 possible events, we use an array of
- * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
-#define IW_EVENT_CAPA_BASE(cmd)		((cmd >= SIOCIWFIRSTPRIV) ? \
-					 (cmd - SIOCIWFIRSTPRIV + 0x60) : \
-					 (cmd - SIOCSIWCOMMIT))
-#define IW_EVENT_CAPA_INDEX(cmd)	(IW_EVENT_CAPA_BASE(cmd) >> 5)
-#define IW_EVENT_CAPA_MASK(cmd)		(1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
-/* Event capability constants - event autogenerated by the kernel
- * This list is valid for most 802.11 devices, customise as needed... */
-#define IW_EVENT_CAPA_K_0	(IW_EVENT_CAPA_MASK(0x8B04) | \
-				 IW_EVENT_CAPA_MASK(0x8B06) | \
-				 IW_EVENT_CAPA_MASK(0x8B1A))
-#define IW_EVENT_CAPA_K_1	(IW_EVENT_CAPA_MASK(0x8B2A))
-/* "Easy" macro to set events in iw_range (less efficient) */
-#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
-#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
-
-
-/****************************** TYPES ******************************/
-
-/* --------------------------- SUBTYPES --------------------------- */
-/*
- *	Generic format for most parameters that fit in an int
- */
-struct	iw_param
-{
-  __s32		value;		/* The value of the parameter itself */
-  __u8		fixed;		/* Hardware should not use auto select */
-  __u8		disabled;	/* Disable the feature */
-  __u16		flags;		/* Various specifc flags (if any) */
-};
-
-/*
- *	For all data larger than 16 octets, we need to use a
- *	pointer to memory allocated in user space.
- */
-struct	iw_point
-{
-  void __user	*pointer;	/* Pointer to the data  (in user space) */
-  __u16		length;		/* number of fields or size in bytes */
-  __u16		flags;		/* Optional params */
-};
-
-/*
- *	A frequency
- *	For numbers lower than 10^9, we encode the number in 'm' and
- *	set 'e' to 0
- *	For number greater than 10^9, we divide it by the lowest power
- *	of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
- *	The power of 10 is in 'e', the result of the division is in 'm'.
- */
-struct	iw_freq
-{
-	__s32		m;		/* Mantissa */
-	__s16		e;		/* Exponent */
-	__u8		i;		/* List index (when in range struct) */
-	__u8		flags;		/* Flags (fixed/auto) */
-};
-
-/*
- *	Quality of the link
- */
-struct	iw_quality
-{
-	__u8		qual;		/* link quality (%retries, SNR,
-					   %missed beacons or better...) */
-	__u8		level;		/* signal level (dBm) */
-	__u8		noise;		/* noise level (dBm) */
-	__u8		updated;	/* Flags to know if updated */
-};
-
-/*
- *	Packet discarded in the wireless adapter due to
- *	"wireless" specific problems...
- *	Note : the list of counter and statistics in net_device_stats
- *	is already pretty exhaustive, and you should use that first.
- *	This is only additional stats...
- */
-struct	iw_discarded
-{
-	__u32		nwid;		/* Rx : Wrong nwid/essid */
-	__u32		code;		/* Rx : Unable to code/decode (WEP) */
-	__u32		fragment;	/* Rx : Can't perform MAC reassembly */
-	__u32		retries;	/* Tx : Max MAC retries num reached */
-	__u32		misc;		/* Others cases */
-};
-
-/*
- *	Packet/Time period missed in the wireless adapter due to
- *	"wireless" specific problems...
- */
-struct	iw_missed
-{
-	__u32		beacon;		/* Missed beacons/superframe */
-};
-
-/*
- *	Quality range (for spy threshold)
- */
-struct	iw_thrspy
-{
-	struct sockaddr		addr;		/* Source address (hw/mac) */
-	struct iw_quality	qual;		/* Quality of the link */
-	struct iw_quality	low;		/* Low threshold */
-	struct iw_quality	high;		/* High threshold */
-};
-
-/*
- *	Optional data for scan request
- *
- *	Note: these optional parameters are controlling parameters for the
- *	scanning behavior, these do not apply to getting scan results
- *	(SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
- *	provide a merged results with all BSSes even if the previous scan
- *	request limited scanning to a subset, e.g., by specifying an SSID.
- *	Especially, scan results are required to include an entry for the
- *	current BSS if the driver is in Managed mode and associated with an AP.
- */
-struct	iw_scan_req
-{
-	__u8		scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
-	__u8		essid_len;
-	__u8		num_channels; /* num entries in channel_list;
-				       * 0 = scan all allowed channels */
-	__u8		flags; /* reserved as padding; use zero, this may
-				* be used in the future for adding flags
-				* to request different scan behavior */
-	struct sockaddr	bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
-				* individual address of a specific BSS */
-
-	/*
-	 * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
-	 * the current ESSID. This allows scan requests for specific ESSID
-	 * without having to change the current ESSID and potentially breaking
-	 * the current association.
-	 */
-	__u8		essid[IW_ESSID_MAX_SIZE];
-
-	/*
-	 * Optional parameters for changing the default scanning behavior.
-	 * These are based on the MLME-SCAN.request from IEEE Std 802.11.
-	 * TU is 1.024 ms. If these are set to 0, driver is expected to use
-	 * reasonable default values. min_channel_time defines the time that
-	 * will be used to wait for the first reply on each channel. If no
-	 * replies are received, next channel will be scanned after this. If
-	 * replies are received, total time waited on the channel is defined by
-	 * max_channel_time.
-	 */
-	__u32		min_channel_time; /* in TU */
-	__u32		max_channel_time; /* in TU */
-
-	struct iw_freq	channel_list[IW_MAX_FREQUENCIES];
-};
-
-/* ------------------------- WPA SUPPORT ------------------------- */
-
-/*
- *	Extended data structure for get/set encoding (this is used with
- *	SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
- *	flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
- *	only the data contents changes (key data -> this structure, including
- *	key data).
- *
- *	If the new key is the first group key, it will be set as the default
- *	TX key. Otherwise, default TX key index is only changed if
- *	IW_ENCODE_EXT_SET_TX_KEY flag is set.
- *
- *	Key will be changed with SIOCSIWENCODEEXT in all cases except for
- *	special "change TX key index" operation which is indicated by setting
- *	key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
- *
- *	tx_seq/rx_seq are only used when respective
- *	IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
- *	TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
- *	TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
- *	used only by an Authenticator (AP or an IBSS station) to get the
- *	current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
- *	RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
- *	debugging/testing.
- */
-struct	iw_encode_ext
-{
-	__u32		ext_flags; /* IW_ENCODE_EXT_* */
-	__u8		tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
-	__u8		rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
-	struct sockaddr	addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
-			       * (group) keys or unicast address for
-			       * individual keys */
-	__u16		alg; /* IW_ENCODE_ALG_* */
-	__u16		key_len;
-	__u8		key[0];
-};
-
-/* SIOCSIWMLME data */
-struct	iw_mlme
-{
-	__u16		cmd; /* IW_MLME_* */
-	__u16		reason_code;
-	struct sockaddr	addr;
-};
-
-/* SIOCSIWPMKSA data */
-#define IW_PMKSA_ADD		1
-#define IW_PMKSA_REMOVE		2
-#define IW_PMKSA_FLUSH		3
-
-#define IW_PMKID_LEN	16
-
-struct	iw_pmksa
-{
-	__u32		cmd; /* IW_PMKSA_* */
-	struct sockaddr	bssid;
-	__u8		pmkid[IW_PMKID_LEN];
-};
-
-/* IWEVMICHAELMICFAILURE data */
-struct	iw_michaelmicfailure
-{
-	__u32		flags;
-	struct sockaddr	src_addr;
-	__u8		tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
-};
-
-/* IWEVPMKIDCAND data */
-#define IW_PMKID_CAND_PREAUTH	0x00000001 /* RNS pre-authentication enabled */
-struct	iw_pmkid_cand
-{
-	__u32		flags; /* IW_PMKID_CAND_* */
-	__u32		index; /* the smaller the index, the higher the
-				* priority */
-	struct sockaddr	bssid;
-};
-
-/* ------------------------ WIRELESS STATS ------------------------ */
-/*
- * Wireless statistics (used for /proc/net/wireless)
- */
-struct	iw_statistics
-{
-	__u16		status;		/* Status
-					 * - device dependent for now */
-
-	struct iw_quality	qual;		/* Quality of the link
-						 * (instant/mean/max) */
-	struct iw_discarded	discard;	/* Packet discarded counts */
-	struct iw_missed	miss;		/* Packet missed counts */
-};
-
-/* ------------------------ IOCTL REQUEST ------------------------ */
-/*
- * This structure defines the payload of an ioctl, and is used 
- * below.
- *
- * Note that this structure should fit on the memory footprint
- * of iwreq (which is the same as ifreq), which mean a max size of
- * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
- * You should check this when increasing the structures defined
- * above in this file...
- */
-union	iwreq_data
-{
-	/* Config - generic */
-	char		name[IFNAMSIZ];
-	/* Name : used to verify the presence of  wireless extensions.
-	 * Name of the protocol/provider... */
-
-	struct iw_point	essid;		/* Extended network name */
-	struct iw_param	nwid;		/* network id (or domain - the cell) */
-	struct iw_freq	freq;		/* frequency or channel :
-					 * 0-1000 = channel
-					 * > 1000 = frequency in Hz */
-
-	struct iw_param	sens;		/* signal level threshold */
-	struct iw_param	bitrate;	/* default bit rate */
-	struct iw_param	txpower;	/* default transmit power */
-	struct iw_param	rts;		/* RTS threshold threshold */
-	struct iw_param	frag;		/* Fragmentation threshold */
-	__u32		mode;		/* Operation mode */
-	struct iw_param	retry;		/* Retry limits & lifetime */
-
-	struct iw_point	encoding;	/* Encoding stuff : tokens */
-	struct iw_param	power;		/* PM duration/timeout */
-	struct iw_quality qual;		/* Quality part of statistics */
-
-	struct sockaddr	ap_addr;	/* Access point address */
-	struct sockaddr	addr;		/* Destination address (hw/mac) */
-
-	struct iw_param	param;		/* Other small parameters */
-	struct iw_point	data;		/* Other large parameters */
-};
-
-/*
- * The structure to exchange data for ioctl.
- * This structure is the same as 'struct ifreq', but (re)defined for
- * convenience...
- * Do I need to remind you about structure size (32 octets) ?
- */
-struct	iwreq 
-{
-	union
-	{
-		char	ifrn_name[IFNAMSIZ];	/* if name, e.g. "eth0" */
-	} ifr_ifrn;
-
-	/* Data part (defined just above) */
-	union	iwreq_data	u;
-};
-
-/* -------------------------- IOCTL DATA -------------------------- */
-/*
- *	For those ioctl which want to exchange mode data that what could
- *	fit in the above structure...
- */
-
-/*
- *	Range of parameters
- */
-
-struct	iw_range
-{
-	/* Informative stuff (to choose between different interface) */
-	__u32		throughput;	/* To give an idea... */
-	/* In theory this value should be the maximum benchmarked
-	 * TCP/IP throughput, because with most of these devices the
-	 * bit rate is meaningless (overhead an co) to estimate how
-	 * fast the connection will go and pick the fastest one.
-	 * I suggest people to play with Netperf or any benchmark...
-	 */
-
-	/* NWID (or domain id) */
-	__u32		min_nwid;	/* Minimal NWID we are able to set */
-	__u32		max_nwid;	/* Maximal NWID we are able to set */
-
-	/* Old Frequency (backward compat - moved lower ) */
-	__u16		old_num_channels;
-	__u8		old_num_frequency;
-
-	/* Wireless event capability bitmasks */
-	__u32		event_capa[6];
-
-	/* signal level threshold range */
-	__s32		sensitivity;
-
-	/* Quality of link & SNR stuff */
-	/* Quality range (link, level, noise)
-	 * If the quality is absolute, it will be in the range [0 ; max_qual],
-	 * if the quality is dBm, it will be in the range [max_qual ; 0].
-	 * Don't forget that we use 8 bit arithmetics... */
-	struct iw_quality	max_qual;	/* Quality of the link */
-	/* This should contain the average/typical values of the quality
-	 * indicator. This should be the threshold between a "good" and
-	 * a "bad" link (example : monitor going from green to orange).
-	 * Currently, user space apps like quality monitors don't have any
-	 * way to calibrate the measurement. With this, they can split
-	 * the range between 0 and max_qual in different quality level
-	 * (using a geometric subdivision centered on the average).
-	 * I expect that people doing the user space apps will feedback
-	 * us on which value we need to put in each driver... */
-	struct iw_quality	avg_qual;	/* Quality of the link */
-
-	/* Rates */
-	__u8		num_bitrates;	/* Number of entries in the list */
-	__s32		bitrate[IW_MAX_BITRATES];	/* list, in bps */
-
-	/* RTS threshold */
-	__s32		min_rts;	/* Minimal RTS threshold */
-	__s32		max_rts;	/* Maximal RTS threshold */
-
-	/* Frag threshold */
-	__s32		min_frag;	/* Minimal frag threshold */
-	__s32		max_frag;	/* Maximal frag threshold */
-
-	/* Power Management duration & timeout */
-	__s32		min_pmp;	/* Minimal PM period */
-	__s32		max_pmp;	/* Maximal PM period */
-	__s32		min_pmt;	/* Minimal PM timeout */
-	__s32		max_pmt;	/* Maximal PM timeout */
-	__u16		pmp_flags;	/* How to decode max/min PM period */
-	__u16		pmt_flags;	/* How to decode max/min PM timeout */
-	__u16		pm_capa;	/* What PM options are supported */
-
-	/* Encoder stuff */
-	__u16	encoding_size[IW_MAX_ENCODING_SIZES];	/* Different token sizes */
-	__u8	num_encoding_sizes;	/* Number of entry in the list */
-	__u8	max_encoding_tokens;	/* Max number of tokens */
-	/* For drivers that need a "login/passwd" form */
-	__u8	encoding_login_index;	/* token index for login token */
-
-	/* Transmit power */
-	__u16		txpower_capa;	/* What options are supported */
-	__u8		num_txpower;	/* Number of entries in the list */
-	__s32		txpower[IW_MAX_TXPOWER];	/* list, in bps */
-
-	/* Wireless Extension version info */
-	__u8		we_version_compiled;	/* Must be WIRELESS_EXT */
-	__u8		we_version_source;	/* Last update of source */
-
-	/* Retry limits and lifetime */
-	__u16		retry_capa;	/* What retry options are supported */
-	__u16		retry_flags;	/* How to decode max/min retry limit */
-	__u16		r_time_flags;	/* How to decode max/min retry life */
-	__s32		min_retry;	/* Minimal number of retries */
-	__s32		max_retry;	/* Maximal number of retries */
-	__s32		min_r_time;	/* Minimal retry lifetime */
-	__s32		max_r_time;	/* Maximal retry lifetime */
-
-	/* Frequency */
-	__u16		num_channels;	/* Number of channels [0; num - 1] */
-	__u8		num_frequency;	/* Number of entry in the list */
-	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */
-	/* Note : this frequency list doesn't need to fit channel numbers,
-	 * because each entry contain its channel index */
-
-	__u32		enc_capa; /* IW_ENC_CAPA_* bit field */
-};
-
-/*
- * Private ioctl interface information
- */
- 
-struct	iw_priv_args
-{
-	__u32		cmd;		/* Number of the ioctl to issue */
-	__u16		set_args;	/* Type and number of args */
-	__u16		get_args;	/* Type and number of args */
-	char		name[IFNAMSIZ];	/* Name of the extension */
-};
-
-/* ----------------------- WIRELESS EVENTS ----------------------- */
-/*
- * Wireless events are carried through the rtnetlink socket to user
- * space. They are encapsulated in the IFLA_WIRELESS field of
- * a RTM_NEWLINK message.
- */
-
-/*
- * A Wireless Event. Contains basically the same data as the ioctl...
- */
-struct iw_event
-{
-	__u16		len;			/* Real lenght of this stuff */
-	__u16		cmd;			/* Wireless IOCTL */
-	union iwreq_data	u;		/* IOCTL fixed payload */
-};
-
-/* Size of the Event prefix (including padding and alignement junk) */
-#define IW_EV_LCP_LEN	(sizeof(struct iw_event) - sizeof(union iwreq_data))
-/* Size of the various events */
-#define IW_EV_CHAR_LEN	(IW_EV_LCP_LEN + IFNAMSIZ)
-#define IW_EV_UINT_LEN	(IW_EV_LCP_LEN + sizeof(__u32))
-#define IW_EV_FREQ_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_freq))
-#define IW_EV_PARAM_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_param))
-#define IW_EV_ADDR_LEN	(IW_EV_LCP_LEN + sizeof(struct sockaddr))
-#define IW_EV_QUAL_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_quality))
-
-/* iw_point events are special. First, the payload (extra data) come at
- * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
- * we omit the pointer, so start at an offset. */
-#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
-			  (char *) NULL)
-#define IW_EV_POINT_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_point) - \
-			 IW_EV_POINT_OFF)
-
-#endif	/* _LINUX_WIRELESS_H */
diff --git a/contrib/wpa/src/common/wpa_common.c b/contrib/wpa/src/common/wpa_common.c
index 074cb8064060..b295f315624a 100644
--- a/contrib/wpa/src/common/wpa_common.c
+++ b/contrib/wpa/src/common/wpa_common.c
@@ -15,11 +15,11 @@
 #include "includes.h"
 
 #include "common.h"
-#include "md5.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "aes_wrap.h"
-#include "crypto.h"
+#include "crypto/md5.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/crypto.h"
 #include "ieee802_11_defs.h"
 #include "defs.h"
 #include "wpa_common.h"
@@ -50,10 +50,10 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
 
 	switch (ver) {
 	case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
-		hmac_md5(key, 16, buf, len, mic);
-		break;
+		return hmac_md5(key, 16, buf, len, mic);
 	case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
-		hmac_sha1(key, 16, buf, len, hash);
+		if (hmac_sha1(key, 16, buf, len, hash))
+			return -1;
 		os_memcpy(mic, hash, MD5_MAC_LEN);
 		break;
 #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
@@ -568,3 +568,220 @@ void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
 }
 
 #endif /* CONFIG_IEEE80211R */
+
+
+/**
+ * rsn_pmkid - Calculate PMK identifier
+ * @pmk: Pairwise master key
+ * @pmk_len: Length of pmk in bytes
+ * @aa: Authenticator address
+ * @spa: Supplicant address
+ * @pmkid: Buffer for PMKID
+ * @use_sha256: Whether to use SHA256-based KDF
+ *
+ * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
+ * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
+ */
+void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
+	       u8 *pmkid, int use_sha256)
+{
+	char *title = "PMK Name";
+	const u8 *addr[3];
+	const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
+	unsigned char hash[SHA256_MAC_LEN];
+
+	addr[0] = (u8 *) title;
+	addr[1] = aa;
+	addr[2] = spa;
+
+#ifdef CONFIG_IEEE80211W
+	if (use_sha256)
+		hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
+	else
+#endif /* CONFIG_IEEE80211W */
+		hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
+	os_memcpy(pmkid, hash, PMKID_LEN);
+}
+
+
+/**
+ * wpa_cipher_txt - Convert cipher suite to a text string
+ * @cipher: Cipher suite (WPA_CIPHER_* enum)
+ * Returns: Pointer to a text string of the cipher suite name
+ */
+const char * wpa_cipher_txt(int cipher)
+{
+	switch (cipher) {
+	case WPA_CIPHER_NONE:
+		return "NONE";
+	case WPA_CIPHER_WEP40:
+		return "WEP-40";
+	case WPA_CIPHER_WEP104:
+		return "WEP-104";
+	case WPA_CIPHER_TKIP:
+		return "TKIP";
+	case WPA_CIPHER_CCMP:
+		return "CCMP";
+	case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
+		return "CCMP+TKIP";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+
+/**
+ * wpa_key_mgmt_txt - Convert key management suite to a text string
+ * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
+ * @proto: WPA/WPA2 version (WPA_PROTO_*)
+ * Returns: Pointer to a text string of the key management suite name
+ */
+const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
+{
+	switch (key_mgmt) {
+	case WPA_KEY_MGMT_IEEE8021X:
+		if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
+			return "WPA2+WPA/IEEE 802.1X/EAP";
+		return proto == WPA_PROTO_RSN ?
+			"WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
+	case WPA_KEY_MGMT_PSK:
+		if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
+			return "WPA2-PSK+WPA-PSK";
+		return proto == WPA_PROTO_RSN ?
+			"WPA2-PSK" : "WPA-PSK";
+	case WPA_KEY_MGMT_NONE:
+		return "NONE";
+	case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
+		return "IEEE 802.1X (no WPA)";
+#ifdef CONFIG_IEEE80211R
+	case WPA_KEY_MGMT_FT_IEEE8021X:
+		return "FT-EAP";
+	case WPA_KEY_MGMT_FT_PSK:
+		return "FT-PSK";
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211W
+	case WPA_KEY_MGMT_IEEE8021X_SHA256:
+		return "WPA2-EAP-SHA256";
+	case WPA_KEY_MGMT_PSK_SHA256:
+		return "WPA2-PSK-SHA256";
+#endif /* CONFIG_IEEE80211W */
+	default:
+		return "UNKNOWN";
+	}
+}
+
+
+int wpa_compare_rsn_ie(int ft_initial_assoc,
+		       const u8 *ie1, size_t ie1len,
+		       const u8 *ie2, size_t ie2len)
+{
+	if (ie1 == NULL || ie2 == NULL)
+		return -1;
+
+	if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
+		return 0; /* identical IEs */
+
+#ifdef CONFIG_IEEE80211R
+	if (ft_initial_assoc) {
+		struct wpa_ie_data ie1d, ie2d;
+		/*
+		 * The PMKID-List in RSN IE is different between Beacon/Probe
+		 * Response/(Re)Association Request frames and EAPOL-Key
+		 * messages in FT initial mobility domain association. Allow
+		 * for this, but verify that other parts of the RSN IEs are
+		 * identical.
+		 */
+		if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
+		    wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
+			return -1;
+		if (ie1d.proto == ie2d.proto &&
+		    ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
+		    ie1d.group_cipher == ie2d.group_cipher &&
+		    ie1d.key_mgmt == ie2d.key_mgmt &&
+		    ie1d.capabilities == ie2d.capabilities &&
+		    ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
+			return 0;
+	}
+#endif /* CONFIG_IEEE80211R */
+
+	return -1;
+}
+
+
+#ifdef CONFIG_IEEE80211R
+int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
+{
+	u8 *start, *end, *rpos, *rend;
+	int added = 0;
+
+	start = ies;
+	end = ies + ies_len;
+
+	while (start < end) {
+		if (*start == WLAN_EID_RSN)
+			break;
+		start += 2 + start[1];
+	}
+	if (start >= end) {
+		wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
+			   "IEs data");
+		return -1;
+	}
+	wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
+		    start, 2 + start[1]);
+
+	/* Find start of PMKID-Count */
+	rpos = start + 2;
+	rend = rpos + start[1];
+
+	/* Skip Version and Group Data Cipher Suite */
+	rpos += 2 + 4;
+	/* Skip Pairwise Cipher Suite Count and List */
+	rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
+	/* Skip AKM Suite Count and List */
+	rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
+
+	if (rpos == rend) {
+		/* Add RSN Capabilities */
+		os_memmove(rpos + 2, rpos, end - rpos);
+		*rpos++ = 0;
+		*rpos++ = 0;
+	} else {
+		/* Skip RSN Capabilities */
+		rpos += 2;
+		if (rpos > rend) {
+			wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
+				   "IEs data");
+			return -1;
+		}
+	}
+
+	if (rpos == rend) {
+		/* No PMKID-Count field included; add it */
+		os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
+		WPA_PUT_LE16(rpos, 1);
+		rpos += 2;
+		os_memcpy(rpos, pmkid, PMKID_LEN);
+		added += 2 + PMKID_LEN;
+		start[1] += 2 + PMKID_LEN;
+	} else {
+		/* PMKID-Count was included; use it */
+		if (WPA_GET_LE16(rpos) != 0) {
+			wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
+				   "in RSN IE in EAPOL-Key data");
+			return -1;
+		}
+		WPA_PUT_LE16(rpos, 1);
+		rpos += 2;
+		os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
+		os_memcpy(rpos, pmkid, PMKID_LEN);
+		added += PMKID_LEN;
+		start[1] += PMKID_LEN;
+	}
+
+	wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
+		    "(PMKID inserted)", start, 2 + start[1]);
+
+	return added;
+}
+#endif /* CONFIG_IEEE80211R */
diff --git a/contrib/wpa/src/common/wpa_common.h b/contrib/wpa/src/common/wpa_common.h
index 3074cd44a136..fd8a79fd602e 100644
--- a/contrib/wpa/src/common/wpa_common.h
+++ b/contrib/wpa/src/common/wpa_common.h
@@ -282,6 +282,12 @@ struct rsn_ftie {
 #define FTIE_SUBELEM_R0KH_ID 3
 #define FTIE_SUBELEM_IGTK 4
 
+struct rsn_rdie {
+	u8 id;
+	u8 descr_count;
+	le16 status_code;
+} STRUCT_PACKED;
+
 #endif /* CONFIG_IEEE80211R */
 
 #ifdef _MSC_VER
@@ -332,4 +338,14 @@ struct wpa_ie_data {
 int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
 			 struct wpa_ie_data *data);
 
+void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
+	       u8 *pmkid, int use_sha256);
+
+const char * wpa_cipher_txt(int cipher);
+const char * wpa_key_mgmt_txt(int key_mgmt, int proto);
+int wpa_compare_rsn_ie(int ft_initial_assoc,
+		       const u8 *ie1, size_t ie1len,
+		       const u8 *ie2, size_t ie2len);
+int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid);
+
 #endif /* WPA_COMMON_H */
diff --git a/contrib/wpa/src/common/wpa_ctrl.h b/contrib/wpa/src/common/wpa_ctrl.h
index 1bfc0d645346..d770fd42d94f 100644
--- a/contrib/wpa/src/common/wpa_ctrl.h
+++ b/contrib/wpa/src/common/wpa_ctrl.h
@@ -40,14 +40,24 @@ extern "C" {
 #define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION "
 /** EAP authentication started (EAP-Request/Identity received) */
 #define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED "
+/** EAP method proposed by the server */
+#define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD "
 /** EAP method selected */
 #define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD "
+/** EAP peer certificate from TLS */
+#define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT "
+/** EAP TLS certificate chain validation error */
+#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR "
 /** EAP authentication completed successfully */
 #define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
 /** EAP authentication failed (EAP-Failure received) */
 #define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
 /** New scan results available */
 #define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
+/** A new BSS entry was added (followed by BSS entry id and BSSID) */
+#define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED "
+/** A BSS entry was removed (followed by BSS entry id and BSSID) */
+#define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED "
 
 /** WPS overlap detected in PBC mode */
 #define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED "
@@ -69,11 +79,24 @@ extern "C" {
 /** WPS enrollment attempt timed out and was terminated */
 #define WPS_EVENT_TIMEOUT "WPS-TIMEOUT "
 
+#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN "
+
+/* WPS ER events */
+#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD "
+#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE "
+#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD "
+#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE "
+
 /* hostapd control interface - fixed message prefixes */
 #define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
 #define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS "
 #define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS "
 #define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED "
+#define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED "
+#define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED "
+#define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED "
+#define AP_STA_CONNECTED "AP-STA-CONNECTED "
+#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
 
 
 /* wpa_supplicant/hostapd control interface access */
diff --git a/contrib/wpa/src/crypto/.gitignore b/contrib/wpa/src/crypto/.gitignore
new file mode 100644
index 000000000000..ee606048c417
--- /dev/null
+++ b/contrib/wpa/src/crypto/.gitignore
@@ -0,0 +1 @@
+libcrypto.a
diff --git a/contrib/wpa/src/crypto/Makefile b/contrib/wpa/src/crypto/Makefile
index cffba620da04..69aa16ac66b0 100644
--- a/contrib/wpa/src/crypto/Makefile
+++ b/contrib/wpa/src/crypto/Makefile
@@ -1,9 +1,56 @@
-all:
-	@echo Nothing to be made.
+all: libcrypto.a
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
-	rm -f *~ *.o *.d
+	rm -f *~ *.o *.d libcrypto.a
 
 install:
 	@echo Nothing to be made.
+
+
+include ../lib.rules
+
+CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
+CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
+#CFLAGS += -DALL_DH_GROUPS
+
+LIB_OBJS= \
+	aes-cbc.o \
+	aes-ctr.o \
+	aes-eax.o \
+	aes-encblock.o \
+	aes-internal.o \
+	aes-internal-dec.o \
+	aes-internal-enc.o \
+	aes-omac1.o \
+	aes-unwrap.o \
+	aes-wrap.o \
+	des-internal.o \
+	dh_group5.o \
+	dh_groups.o \
+	md4-internal.o \
+	md5.o \
+	md5-internal.o \
+	md5-non-fips.o \
+	milenage.o \
+	ms_funcs.o \
+	rc4.o \
+	sha1.o \
+	sha1-internal.o \
+	sha1-pbkdf2.o \
+	sha1-tlsprf.o \
+	sha1-tprf.o \
+	sha256.o \
+	sha256-internal.o
+
+LIB_OBJS += crypto_internal.o
+LIB_OBJS += crypto_internal-cipher.o
+LIB_OBJS += crypto_internal-modexp.o
+LIB_OBJS += crypto_internal-rsa.o
+LIB_OBJS += tls_internal.o
+LIB_OBJS += fips_prf_internal.o
+
+
+libcrypto.a: $(LIB_OBJS)
+	$(AR) crT $@ $?
+
+-include $(OBJS:%.o=%.d)
diff --git a/contrib/wpa/src/crypto/aes-cbc.c b/contrib/wpa/src/crypto/aes-cbc.c
new file mode 100644
index 000000000000..bd74769905e1
--- /dev/null
+++ b/contrib/wpa/src/crypto/aes-cbc.c
@@ -0,0 +1,86 @@
+/*
+ * AES-128 CBC
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen 
+ *
+ * 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 "aes.h"
+#include "aes_wrap.h"
+
+/**
+ * aes_128_cbc_encrypt - AES-128 CBC encryption
+ * @key: Encryption key
+ * @iv: Encryption IV for CBC mode (16 bytes)
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes (must be divisible by 16)
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
+{
+	void *ctx;
+	u8 cbc[AES_BLOCK_SIZE];
+	u8 *pos = data;
+	int i, j, blocks;
+
+	ctx = aes_encrypt_init(key, 16);
+	if (ctx == NULL)
+		return -1;
+	os_memcpy(cbc, iv, AES_BLOCK_SIZE);
+
+	blocks = data_len / AES_BLOCK_SIZE;
+	for (i = 0; i < blocks; i++) {
+		for (j = 0; j < AES_BLOCK_SIZE; j++)
+			cbc[j] ^= pos[j];
+		aes_encrypt(ctx, cbc, cbc);
+		os_memcpy(pos, cbc, AES_BLOCK_SIZE);
+		pos += AES_BLOCK_SIZE;
+	}
+	aes_encrypt_deinit(ctx);
+	return 0;
+}
+
+
+/**
+ * aes_128_cbc_decrypt - AES-128 CBC decryption
+ * @key: Decryption key
+ * @iv: Decryption IV for CBC mode (16 bytes)
+ * @data: Data to decrypt in-place
+ * @data_len: Length of data in bytes (must be divisible by 16)
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
+{
+	void *ctx;
+	u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
+	u8 *pos = data;
+	int i, j, blocks;
+
+	ctx = aes_decrypt_init(key, 16);
+	if (ctx == NULL)
+		return -1;
+	os_memcpy(cbc, iv, AES_BLOCK_SIZE);
+
+	blocks = data_len / AES_BLOCK_SIZE;
+	for (i = 0; i < blocks; i++) {
+		os_memcpy(tmp, pos, AES_BLOCK_SIZE);
+		aes_decrypt(ctx, pos, pos);
+		for (j = 0; j < AES_BLOCK_SIZE; j++)
+			pos[j] ^= cbc[j];
+		os_memcpy(cbc, tmp, AES_BLOCK_SIZE);
+		pos += AES_BLOCK_SIZE;
+	}
+	aes_decrypt_deinit(ctx);
+	return 0;
+}
diff --git a/contrib/wpa/src/crypto/aes-ctr.c b/contrib/wpa/src/crypto/aes-ctr.c
new file mode 100644
index 000000000000..468f87741199
--- /dev/null
+++ b/contrib/wpa/src/crypto/aes-ctr.c
@@ -0,0 +1,61 @@
+/*
+ * AES-128 CTR
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen 
+ *
+ * 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 "aes.h"
+#include "aes_wrap.h"
+
+/**
+ * aes_128_ctr_encrypt - AES-128 CTR mode encryption
+ * @key: Key for encryption (16 bytes)
+ * @nonce: Nonce for counter mode (16 bytes)
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
+			u8 *data, size_t data_len)
+{
+	void *ctx;
+	size_t j, len, left = data_len;
+	int i;
+	u8 *pos = data;
+	u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE];
+
+	ctx = aes_encrypt_init(key, 16);
+	if (ctx == NULL)
+		return -1;
+	os_memcpy(counter, nonce, AES_BLOCK_SIZE);
+
+	while (left > 0) {
+		aes_encrypt(ctx, counter, buf);
+
+		len = (left < AES_BLOCK_SIZE) ? left : AES_BLOCK_SIZE;
+		for (j = 0; j < len; j++)
+			pos[j] ^= buf[j];
+		pos += len;
+		left -= len;
+
+		for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
+			counter[i]++;
+			if (counter[i])
+				break;
+		}
+	}
+	aes_encrypt_deinit(ctx);
+	return 0;
+}
diff --git a/contrib/wpa/src/crypto/aes-eax.c b/contrib/wpa/src/crypto/aes-eax.c
new file mode 100644
index 000000000000..d5c397151d2e
--- /dev/null
+++ b/contrib/wpa/src/crypto/aes-eax.c
@@ -0,0 +1,151 @@
+/*
+ * AES-128 EAX
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen 
+ *
+ * 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 "aes.h"
+#include "aes_wrap.h"
+
+/**
+ * aes_128_eax_encrypt - AES-128 EAX mode encryption
+ * @key: Key for encryption (16 bytes)
+ * @nonce: Nonce for counter mode
+ * @nonce_len: Nonce length in bytes
+ * @hdr: Header data to be authenticity protected
+ * @hdr_len: Length of the header data bytes
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes
+ * @tag: 16-byte tag value
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
+			const u8 *hdr, size_t hdr_len,
+			u8 *data, size_t data_len, u8 *tag)
+{
+	u8 *buf;
+	size_t buf_len;
+	u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
+		data_mac[AES_BLOCK_SIZE];
+	int i, ret = -1;
+
+	if (nonce_len > data_len)
+		buf_len = nonce_len;
+	else
+		buf_len = data_len;
+	if (hdr_len > buf_len)
+		buf_len = hdr_len;
+	buf_len += 16;
+
+	buf = os_malloc(buf_len);
+	if (buf == NULL)
+		return -1;
+
+	os_memset(buf, 0, 15);
+
+	buf[15] = 0;
+	os_memcpy(buf + 16, nonce, nonce_len);
+	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac))
+		goto fail;
+
+	buf[15] = 1;
+	os_memcpy(buf + 16, hdr, hdr_len);
+	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac))
+		goto fail;
+
+	if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len))
+		goto fail;
+	buf[15] = 2;
+	os_memcpy(buf + 16, data, data_len);
+	if (omac1_aes_128(key, buf, 16 + data_len, data_mac))
+		goto fail;
+
+	for (i = 0; i < AES_BLOCK_SIZE; i++)
+		tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
+
+	ret = 0;
+fail:
+	os_free(buf);
+
+	return ret;
+}
+
+
+/**
+ * aes_128_eax_decrypt - AES-128 EAX mode decryption
+ * @key: Key for decryption (16 bytes)
+ * @nonce: Nonce for counter mode
+ * @nonce_len: Nonce length in bytes
+ * @hdr: Header data to be authenticity protected
+ * @hdr_len: Length of the header data bytes
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes
+ * @tag: 16-byte tag value
+ * Returns: 0 on success, -1 on failure, -2 if tag does not match
+ */
+int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
+			const u8 *hdr, size_t hdr_len,
+			u8 *data, size_t data_len, const u8 *tag)
+{
+	u8 *buf;
+	size_t buf_len;
+	u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE],
+		data_mac[AES_BLOCK_SIZE];
+	int i;
+
+	if (nonce_len > data_len)
+		buf_len = nonce_len;
+	else
+		buf_len = data_len;
+	if (hdr_len > buf_len)
+		buf_len = hdr_len;
+	buf_len += 16;
+
+	buf = os_malloc(buf_len);
+	if (buf == NULL)
+		return -1;
+
+	os_memset(buf, 0, 15);
+
+	buf[15] = 0;
+	os_memcpy(buf + 16, nonce, nonce_len);
+	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) {
+		os_free(buf);
+		return -1;
+	}
+
+	buf[15] = 1;
+	os_memcpy(buf + 16, hdr, hdr_len);
+	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) {
+		os_free(buf);
+		return -1;
+	}
+
+	buf[15] = 2;
+	os_memcpy(buf + 16, data, data_len);
+	if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) {
+		os_free(buf);
+		return -1;
+	}
+
+	os_free(buf);
+
+	for (i = 0; i < AES_BLOCK_SIZE; i++) {
+		if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]))
+			return -2;
+	}
+
+	return aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
+}
diff --git a/contrib/wpa/src/crypto/aes-encblock.c b/contrib/wpa/src/crypto/aes-encblock.c
new file mode 100644
index 000000000000..8f35caa221e2
--- /dev/null
+++ b/contrib/wpa/src/crypto/aes-encblock.c
@@ -0,0 +1,38 @@
+/*
+ * AES encrypt_block
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen 
+ *
+ * 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 "aes.h"
+#include "aes_wrap.h"
+
+/**
+ * aes_128_encrypt_block - Perform one AES 128-bit block operation
+ * @key: Key for AES
+ * @in: Input data (16 bytes)
+ * @out: Output of the AES block operation (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
+{
+	void *ctx;
+	ctx = aes_encrypt_init(key, 16);
+	if (ctx == NULL)
+		return -1;
+	aes_encrypt(ctx, in, out);
+	aes_encrypt_deinit(ctx);
+	return 0;
+}
diff --git a/contrib/wpa/src/crypto/aes-internal-dec.c b/contrib/wpa/src/crypto/aes-internal-dec.c
new file mode 100644
index 000000000000..2d32c03fbf4c
--- /dev/null
+++ b/contrib/wpa/src/crypto/aes-internal-dec.c
@@ -0,0 +1,151 @@
+/*
+ * AES (Rijndael) cipher - decrypt
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ *   cost of reduced throughput (quite small difference on Pentium 4,
+ *   10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen 
+ *
+ * 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.h"
+#include "aes_i.h"
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ *
+ * @return	the number of rounds for the given cipher key size.
+ */
+void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])
+{
+	int Nr = 10, i, j;
+	u32 temp;
+
+	/* expand the cipher key: */
+	rijndaelKeySetupEnc(rk, cipherKey);
+	/* invert the order of the round keys: */
+	for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
+		temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
+		temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+		temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+		temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+	}
+	/* apply the inverse MixColumn transform to all round keys but the
+	 * first and the last: */
+	for (i = 1; i < Nr; i++) {
+		rk += 4;
+		for (j = 0; j < 4; j++) {
+			rk[j] = TD0_(TE4((rk[j] >> 24)       )) ^
+				TD1_(TE4((rk[j] >> 16) & 0xff)) ^
+				TD2_(TE4((rk[j] >>  8) & 0xff)) ^
+				TD3_(TE4((rk[j]      ) & 0xff));
+		}
+	}
+}
+
+void * aes_decrypt_init(const u8 *key, size_t len)
+{
+	u32 *rk;
+	if (len != 16)
+		return NULL;
+	rk = os_malloc(AES_PRIV_SIZE);
+	if (rk == NULL)
+		return NULL;
+	rijndaelKeySetupDec(rk, key);
+	return rk;
+}
+
+static void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16])
+{
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+	const int Nr = 10;
+#ifndef FULL_UNROLL
+	int r;
+#endif /* ?FULL_UNROLL */
+
+	/*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+	s0 = GETU32(ct     ) ^ rk[0];
+	s1 = GETU32(ct +  4) ^ rk[1];
+	s2 = GETU32(ct +  8) ^ rk[2];
+	s3 = GETU32(ct + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \
+d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \
+d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \
+d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
+
+#ifdef FULL_UNROLL
+
+	ROUND(1,t,s);
+	ROUND(2,s,t);
+	ROUND(3,t,s);
+	ROUND(4,s,t);
+	ROUND(5,t,s);
+	ROUND(6,s,t);
+	ROUND(7,t,s);
+	ROUND(8,s,t);
+	ROUND(9,t,s);
+
+	rk += Nr << 2;
+
+#else  /* !FULL_UNROLL */
+
+	/* Nr - 1 full rounds: */
+	r = Nr >> 1;
+	for (;;) {
+		ROUND(1,t,s);
+		rk += 8;
+		if (--r == 0)
+			break;
+		ROUND(0,s,t);
+	}
+
+#endif /* ?FULL_UNROLL */
+
+#undef ROUND
+
+	/*
+	 * apply last round and
+	 * map cipher state to byte array block:
+	 */
+	s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0];
+	PUTU32(pt     , s0);
+	s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1];
+	PUTU32(pt +  4, s1);
+	s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2];
+	PUTU32(pt +  8, s2);
+	s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3];
+	PUTU32(pt + 12, s3);
+}
+
+void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
+{
+	rijndaelDecrypt(ctx, crypt, plain);
+}
+
+
+void aes_decrypt_deinit(void *ctx)
+{
+	os_memset(ctx, 0, AES_PRIV_SIZE);
+	os_free(ctx);
+}
diff --git a/contrib/wpa/src/crypto/aes-internal-enc.c b/contrib/wpa/src/crypto/aes-internal-enc.c
new file mode 100644
index 000000000000..2f198263bb84
--- /dev/null
+++ b/contrib/wpa/src/crypto/aes-internal-enc.c
@@ -0,0 +1,121 @@
+/*
+ * AES (Rijndael) cipher - encrypt
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ *   cost of reduced throughput (quite small difference on Pentium 4,
+ *   10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen 
+ *
+ * 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.h"
+#include "aes_i.h"
+
+void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
+{
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+	const int Nr = 10;
+#ifndef FULL_UNROLL
+	int r;
+#endif /* ?FULL_UNROLL */
+
+	/*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+	s0 = GETU32(pt     ) ^ rk[0];
+	s1 = GETU32(pt +  4) ^ rk[1];
+	s2 = GETU32(pt +  8) ^ rk[2];
+	s3 = GETU32(pt + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
+d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
+d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
+d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
+
+#ifdef FULL_UNROLL
+
+	ROUND(1,t,s);
+	ROUND(2,s,t);
+	ROUND(3,t,s);
+	ROUND(4,s,t);
+	ROUND(5,t,s);
+	ROUND(6,s,t);
+	ROUND(7,t,s);
+	ROUND(8,s,t);
+	ROUND(9,t,s);
+
+	rk += Nr << 2;
+
+#else  /* !FULL_UNROLL */
+
+	/* Nr - 1 full rounds: */
+	r = Nr >> 1;
+	for (;;) {
+		ROUND(1,t,s);
+		rk += 8;
+		if (--r == 0)
+			break;
+		ROUND(0,s,t);
+	}
+
+#endif /* ?FULL_UNROLL */
+
+#undef ROUND
+
+	/*
+	 * apply last round and
+	 * map cipher state to byte array block:
+	 */
+	s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
+	PUTU32(ct     , s0);
+	s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
+	PUTU32(ct +  4, s1);
+	s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
+	PUTU32(ct +  8, s2);
+	s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
+	PUTU32(ct + 12, s3);
+}
+
+
+void * aes_encrypt_init(const u8 *key, size_t len)
+{
+	u32 *rk;
+	if (len != 16)
+		return NULL;
+	rk = os_malloc(AES_PRIV_SIZE);
+	if (rk == NULL)
+		return NULL;
+	rijndaelKeySetupEnc(rk, key);
+	return rk;
+}
+
+
+void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
+{
+	rijndaelEncrypt(ctx, plain, crypt);
+}
+
+
+void aes_encrypt_deinit(void *ctx)
+{
+	os_memset(ctx, 0, AES_PRIV_SIZE);
+	os_free(ctx);
+}
diff --git a/contrib/wpa/src/crypto/aes.c b/contrib/wpa/src/crypto/aes-internal.c
similarity index 82%
rename from contrib/wpa/src/crypto/aes.c
rename to contrib/wpa/src/crypto/aes-internal.c
index 8b8f2a04dee2..416122022066 100644
--- a/contrib/wpa/src/crypto/aes.c
+++ b/contrib/wpa/src/crypto/aes-internal.c
@@ -24,10 +24,8 @@
 #include "includes.h"
 
 #include "common.h"
-
-#ifdef INTERNAL_AES
-
 #include "crypto.h"
+#include "aes_i.h"
 
 /*
  * rijndael-alg-fst.c
@@ -55,9 +53,6 @@
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/* #define FULL_UNROLL */
-#define AES_SMALL_TABLES
-
 
 /*
 Te0[x] = S [x].[02, 01, 01, 03];
@@ -73,7 +68,7 @@ Td3[x] = Si[x].[09, 0d, 0b, 0e];
 Td4[x] = Si[x].[01, 01, 01, 01];
 */
 
-static const u32 Te0[256] = {
+const u32 Te0[256] = {
     0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
     0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
     0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
@@ -140,7 +135,7 @@ static const u32 Te0[256] = {
     0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
 };
 #ifndef AES_SMALL_TABLES
-static const u32 Te1[256] = {
+const u32 Te1[256] = {
     0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
     0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
     0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
@@ -206,7 +201,7 @@ static const u32 Te1[256] = {
     0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
     0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
 };
-static const u32 Te2[256] = {
+const u32 Te2[256] = {
     0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
     0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
     0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
@@ -272,7 +267,7 @@ static const u32 Te2[256] = {
     0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
     0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
 };
-static const u32 Te3[256] = {
+const u32 Te3[256] = {
 
     0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
     0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
@@ -339,7 +334,7 @@ static const u32 Te3[256] = {
     0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
     0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
 };
-static const u32 Te4[256] = {
+const u32 Te4[256] = {
     0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
     0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
     0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
@@ -406,7 +401,7 @@ static const u32 Te4[256] = {
     0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
 };
 #endif /* AES_SMALL_TABLES */
-static const u32 Td0[256] = {
+const u32 Td0[256] = {
     0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
     0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
     0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
@@ -473,7 +468,7 @@ static const u32 Td0[256] = {
     0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
 };
 #ifndef AES_SMALL_TABLES
-static const u32 Td1[256] = {
+const u32 Td1[256] = {
     0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
     0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
     0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
@@ -539,7 +534,7 @@ static const u32 Td1[256] = {
     0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
     0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
 };
-static const u32 Td2[256] = {
+const u32 Td2[256] = {
     0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
     0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
     0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
@@ -606,7 +601,7 @@ static const u32 Td2[256] = {
     0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
     0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
 };
-static const u32 Td3[256] = {
+const u32 Td3[256] = {
     0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
     0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
     0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
@@ -672,7 +667,7 @@ static const u32 Td3[256] = {
     0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
     0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
 };
-static const u32 Td4[256] = {
+const u32 Td4[256] = {
     0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
     0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
     0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
@@ -738,13 +733,13 @@ static const u32 Td4[256] = {
     0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
     0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
 };
-static const u32 rcon[] = {
+const u32 rcon[] = {
 	0x01000000, 0x02000000, 0x04000000, 0x08000000,
 	0x10000000, 0x20000000, 0x40000000, 0x80000000,
 	0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
 };
 #else /* AES_SMALL_TABLES */
-static const u8 Td4s[256] = {
+const u8 Td4s[256] = {
     0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
     0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
     0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
@@ -778,95 +773,11 @@ static const u8 Td4s[256] = {
     0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
     0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
 };
-static const u8 rcons[] = {
+const u8 rcons[] = {
 	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
 	/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
 };
 #endif /* AES_SMALL_TABLES */
-
-
-#ifndef AES_SMALL_TABLES
-
-#define RCON(i) rcon[(i)]
-
-#define TE0(i) Te0[((i) >> 24) & 0xff]
-#define TE1(i) Te1[((i) >> 16) & 0xff]
-#define TE2(i) Te2[((i) >> 8) & 0xff]
-#define TE3(i) Te3[(i) & 0xff]
-#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
-#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
-#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
-#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff)
-#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000)
-#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000)
-#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00)
-#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff)
-#define TE4(i) (Te4[(i)] & 0x000000ff)
-
-#define TD0(i) Td0[((i) >> 24) & 0xff]
-#define TD1(i) Td1[((i) >> 16) & 0xff]
-#define TD2(i) Td2[((i) >> 8) & 0xff]
-#define TD3(i) Td3[(i) & 0xff]
-#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000)
-#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000)
-#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00)
-#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff)
-#define TD0_(i) Td0[(i) & 0xff]
-#define TD1_(i) Td1[(i) & 0xff]
-#define TD2_(i) Td2[(i) & 0xff]
-#define TD3_(i) Td3[(i) & 0xff]
-
-#else /* AES_SMALL_TABLES */
-
-#define RCON(i) (rcons[(i)] << 24)
-
-static inline u32 rotr(u32 val, int bits)
-{
-	return (val >> bits) | (val << (32 - bits));
-}
-
-#define TE0(i) Te0[((i) >> 24) & 0xff]
-#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
-#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
-#define TE3(i) rotr(Te0[(i) & 0xff], 24)
-#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
-#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
-#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
-#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
-#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
-#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
-#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
-#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
-#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
-
-#define TD0(i) Td0[((i) >> 24) & 0xff]
-#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
-#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
-#define TD3(i) rotr(Td0[(i) & 0xff], 24)
-#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
-#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
-#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
-#define TD44(i) (Td4s[(i) & 0xff])
-#define TD0_(i) Td0[(i) & 0xff]
-#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
-#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
-#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
-
-#endif /* AES_SMALL_TABLES */
-
-#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
-
-#ifdef _MSC_VER
-#define GETU32(p) SWAP(*((u32 *)(p)))
-#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
-#else
-#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \
-((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
-#define PUTU32(ct, st) { \
-(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \
-(ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
-#endif
-
 /**
  * Expand the cipher key into the encryption key schedule.
  *
@@ -892,236 +803,3 @@ void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
 		rk += 4;
 	}
 }
-
-#ifndef CONFIG_NO_AES_DECRYPT
-/**
- * Expand the cipher key into the decryption key schedule.
- *
- * @return	the number of rounds for the given cipher key size.
- */
-void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])
-{
-	int Nr = 10, i, j;
-	u32 temp;
-
-	/* expand the cipher key: */
-	rijndaelKeySetupEnc(rk, cipherKey);
-	/* invert the order of the round keys: */
-	for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
-		temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
-		temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
-		temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
-		temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
-	}
-	/* apply the inverse MixColumn transform to all round keys but the
-	 * first and the last: */
-	for (i = 1; i < Nr; i++) {
-		rk += 4;
-		for (j = 0; j < 4; j++) {
-			rk[j] = TD0_(TE4((rk[j] >> 24)       )) ^
-				TD1_(TE4((rk[j] >> 16) & 0xff)) ^
-				TD2_(TE4((rk[j] >>  8) & 0xff)) ^
-				TD3_(TE4((rk[j]      ) & 0xff));
-		}
-	}
-}
-#endif /* CONFIG_NO_AES_DECRYPT */
-
-#ifndef CONFIG_NO_AES_ENCRYPT
-void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
-{
-	u32 s0, s1, s2, s3, t0, t1, t2, t3;
-	const int Nr = 10;
-#ifndef FULL_UNROLL
-	int r;
-#endif /* ?FULL_UNROLL */
-
-	/*
-	 * map byte array block to cipher state
-	 * and add initial round key:
-	 */
-	s0 = GETU32(pt     ) ^ rk[0];
-	s1 = GETU32(pt +  4) ^ rk[1];
-	s2 = GETU32(pt +  8) ^ rk[2];
-	s3 = GETU32(pt + 12) ^ rk[3];
-
-#define ROUND(i,d,s) \
-d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
-d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
-d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
-d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
-
-#ifdef FULL_UNROLL
-
-	ROUND(1,t,s);
-	ROUND(2,s,t);
-	ROUND(3,t,s);
-	ROUND(4,s,t);
-	ROUND(5,t,s);
-	ROUND(6,s,t);
-	ROUND(7,t,s);
-	ROUND(8,s,t);
-	ROUND(9,t,s);
-
-	rk += Nr << 2;
-
-#else  /* !FULL_UNROLL */
-
-	/* Nr - 1 full rounds: */
-	r = Nr >> 1;
-	for (;;) {
-		ROUND(1,t,s);
-		rk += 8;
-		if (--r == 0)
-			break;
-		ROUND(0,s,t);
-	}
-
-#endif /* ?FULL_UNROLL */
-
-#undef ROUND
-
-	/*
-	 * apply last round and
-	 * map cipher state to byte array block:
-	 */
-	s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
-	PUTU32(ct     , s0);
-	s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
-	PUTU32(ct +  4, s1);
-	s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
-	PUTU32(ct +  8, s2);
-	s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
-	PUTU32(ct + 12, s3);
-}
-#endif /* CONFIG_NO_AES_ENCRYPT */
-
-void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16])
-{
-	u32 s0, s1, s2, s3, t0, t1, t2, t3;
-	const int Nr = 10;
-#ifndef FULL_UNROLL
-	int r;
-#endif /* ?FULL_UNROLL */
-
-	/*
-	 * map byte array block to cipher state
-	 * and add initial round key:
-	 */
-	s0 = GETU32(ct     ) ^ rk[0];
-	s1 = GETU32(ct +  4) ^ rk[1];
-	s2 = GETU32(ct +  8) ^ rk[2];
-	s3 = GETU32(ct + 12) ^ rk[3];
-
-#define ROUND(i,d,s) \
-d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \
-d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \
-d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \
-d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
-
-#ifdef FULL_UNROLL
-
-	ROUND(1,t,s);
-	ROUND(2,s,t);
-	ROUND(3,t,s);
-	ROUND(4,s,t);
-	ROUND(5,t,s);
-	ROUND(6,s,t);
-	ROUND(7,t,s);
-	ROUND(8,s,t);
-	ROUND(9,t,s);
-
-	rk += Nr << 2;
-
-#else  /* !FULL_UNROLL */
-
-	/* Nr - 1 full rounds: */
-	r = Nr >> 1;
-	for (;;) {
-		ROUND(1,t,s);
-		rk += 8;
-		if (--r == 0)
-			break;
-		ROUND(0,s,t);
-	}
-
-#endif /* ?FULL_UNROLL */
-
-#undef ROUND
-
-	/*
-	 * apply last round and
-	 * map cipher state to byte array block:
-	 */
-	s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0];
-	PUTU32(pt     , s0);
-	s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1];
-	PUTU32(pt +  4, s1);
-	s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2];
-	PUTU32(pt +  8, s2);
-	s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3];
-	PUTU32(pt + 12, s3);
-}
-
-
-
-/* Generic wrapper functions for AES functions */
-
-#define AES_PRIV_SIZE (4 * 44)
-
-#ifndef CONFIG_NO_AES_ENCRYPT
-void * aes_encrypt_init(const u8 *key, size_t len)
-{
-	u32 *rk;
-	if (len != 16)
-		return NULL;
-	rk = os_malloc(AES_PRIV_SIZE);
-	if (rk == NULL)
-		return NULL;
-	rijndaelKeySetupEnc(rk, key);
-	return rk;
-}
-
-
-void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
-{
-	rijndaelEncrypt(ctx, plain, crypt);
-}
-
-
-void aes_encrypt_deinit(void *ctx)
-{
-	os_memset(ctx, 0, AES_PRIV_SIZE);
-	os_free(ctx);
-}
-#endif /* CONFIG_NO_AES_ENCRYPT */
-
-
-#ifndef CONFIG_NO_AES_DECRYPT
-void * aes_decrypt_init(const u8 *key, size_t len)
-{
-	u32 *rk;
-	if (len != 16)
-		return NULL;
-	rk = os_malloc(AES_PRIV_SIZE);
-	if (rk == NULL)
-		return NULL;
-	rijndaelKeySetupDec(rk, key);
-	return rk;
-}
-
-
-void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
-{
-	rijndaelDecrypt(ctx, crypt, plain);
-}
-
-
-void aes_decrypt_deinit(void *ctx)
-{
-	os_memset(ctx, 0, AES_PRIV_SIZE);
-	os_free(ctx);
-}
-#endif /* CONFIG_NO_AES_DECRYPT */
-
-#endif /* INTERNAL_AES */
diff --git a/contrib/wpa/src/crypto/aes-omac1.c b/contrib/wpa/src/crypto/aes-omac1.c
new file mode 100644
index 000000000000..f77529617a31
--- /dev/null
+++ b/contrib/wpa/src/crypto/aes-omac1.c
@@ -0,0 +1,124 @@
+/*
+ * One-key CBC MAC (OMAC1) hash with AES-128
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen 
+ *
+ * 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 "aes.h"
+#include "aes_wrap.h"
+
+static void gf_mulx(u8 *pad)
+{
+	int i, carry;
+
+	carry = pad[0] & 0x80;
+	for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
+		pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
+	pad[AES_BLOCK_SIZE - 1] <<= 1;
+	if (carry)
+		pad[AES_BLOCK_SIZE - 1] ^= 0x87;
+}
+
+
+/**
+ * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
+ * @key: 128-bit key for the hash operation
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is a mode for using block cipher (AES in this case) for authentication.
+ * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
+ * (SP) 800-38B.
+ */
+int omac1_aes_128_vector(const u8 *key, size_t num_elem,
+			 const u8 *addr[], const size_t *len, u8 *mac)
+{
+	void *ctx;
+	u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
+	const u8 *pos, *end;
+	size_t i, e, left, total_len;
+
+	ctx = aes_encrypt_init(key, 16);
+	if (ctx == NULL)
+		return -1;
+	os_memset(cbc, 0, AES_BLOCK_SIZE);
+
+	total_len = 0;
+	for (e = 0; e < num_elem; e++)
+		total_len += len[e];
+	left = total_len;
+
+	e = 0;
+	pos = addr[0];
+	end = pos + len[0];
+
+	while (left >= AES_BLOCK_SIZE) {
+		for (i = 0; i < AES_BLOCK_SIZE; i++) {
+			cbc[i] ^= *pos++;
+			if (pos >= end) {
+				e++;
+				pos = addr[e];
+				end = pos + len[e];
+			}
+		}
+		if (left > AES_BLOCK_SIZE)
+			aes_encrypt(ctx, cbc, cbc);
+		left -= AES_BLOCK_SIZE;
+	}
+
+	os_memset(pad, 0, AES_BLOCK_SIZE);
+	aes_encrypt(ctx, pad, pad);
+	gf_mulx(pad);
+
+	if (left || total_len == 0) {
+		for (i = 0; i < left; i++) {
+			cbc[i] ^= *pos++;
+			if (pos >= end) {
+				e++;
+				pos = addr[e];
+				end = pos + len[e];
+			}
+		}
+		cbc[left] ^= 0x80;
+		gf_mulx(pad);
+	}
+
+	for (i = 0; i < AES_BLOCK_SIZE; i++)
+		pad[i] ^= cbc[i];
+	aes_encrypt(ctx, pad, mac);
+	aes_encrypt_deinit(ctx);
+	return 0;
+}
+
+
+/**
+ * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
+ * @key: 128-bit key for the hash operation
+ * @data: Data buffer for which a MAC is determined
+ * @data_len: Length of data buffer in bytes
+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is a mode for using block cipher (AES in this case) for authentication.
+ * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
+ * (SP) 800-38B.
+ */
+int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
+{
+	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
+}
diff --git a/contrib/wpa/src/crypto/aes-unwrap.c b/contrib/wpa/src/crypto/aes-unwrap.c
new file mode 100644
index 000000000000..f233ffa4c04c
--- /dev/null
+++ b/contrib/wpa/src/crypto/aes-unwrap.c
@@ -0,0 +1,79 @@
+/*
+ * AES key unwrap (128-bit KEK, RFC3394)
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen 
+ *
+ * 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 "aes.h"
+#include "aes_wrap.h"
+
+/**
+ * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * @kek: Key encryption key (KEK)
+ * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
+ * bytes
+ * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
+ * @plain: Plaintext key, n * 64 bits
+ * Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
+ */
+int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
+{
+	u8 a[8], *r, b[16];
+	int i, j;
+	void *ctx;
+
+	/* 1) Initialize variables. */
+	os_memcpy(a, cipher, 8);
+	r = plain;
+	os_memcpy(r, cipher + 8, 8 * n);
+
+	ctx = aes_decrypt_init(kek, 16);
+	if (ctx == NULL)
+		return -1;
+
+	/* 2) Compute intermediate values.
+	 * For j = 5 to 0
+	 *     For i = n to 1
+	 *         B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
+	 *         A = MSB(64, B)
+	 *         R[i] = LSB(64, B)
+	 */
+	for (j = 5; j >= 0; j--) {
+		r = plain + (n - 1) * 8;
+		for (i = n; i >= 1; i--) {
+			os_memcpy(b, a, 8);
+			b[7] ^= n * j + i;
+
+			os_memcpy(b + 8, r, 8);
+			aes_decrypt(ctx, b, b);
+			os_memcpy(a, b, 8);
+			os_memcpy(r, b + 8, 8);
+			r -= 8;
+		}
+	}
+	aes_decrypt_deinit(ctx);
+
+	/* 3) Output results.
+	 *
+	 * These are already in @plain due to the location of temporary
+	 * variables. Just verify that the IV matches with the expected value.
+	 */
+	for (i = 0; i < 8; i++) {
+		if (a[i] != 0xa6)
+			return -1;
+	}
+
+	return 0;
+}
diff --git a/contrib/wpa/src/crypto/aes-wrap.c b/contrib/wpa/src/crypto/aes-wrap.c
new file mode 100644
index 000000000000..28d0c89e88f0
--- /dev/null
+++ b/contrib/wpa/src/crypto/aes-wrap.c
@@ -0,0 +1,76 @@
+/*
+ * AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen 
+ *
+ * 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 "aes.h"
+#include "aes_wrap.h"
+
+/**
+ * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * @kek: 16-octet Key encryption key (KEK)
+ * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
+ * bytes
+ * @plain: Plaintext key to be wrapped, n * 64 bits
+ * @cipher: Wrapped key, (n + 1) * 64 bits
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
+{
+	u8 *a, *r, b[16];
+	int i, j;
+	void *ctx;
+
+	a = cipher;
+	r = cipher + 8;
+
+	/* 1) Initialize variables. */
+	os_memset(a, 0xa6, 8);
+	os_memcpy(r, plain, 8 * n);
+
+	ctx = aes_encrypt_init(kek, 16);
+	if (ctx == NULL)
+		return -1;
+
+	/* 2) Calculate intermediate values.
+	 * For j = 0 to 5
+	 *     For i=1 to n
+	 *         B = AES(K, A | R[i])
+	 *         A = MSB(64, B) ^ t where t = (n*j)+i
+	 *         R[i] = LSB(64, B)
+	 */
+	for (j = 0; j <= 5; j++) {
+		r = cipher + 8;
+		for (i = 1; i <= n; i++) {
+			os_memcpy(b, a, 8);
+			os_memcpy(b + 8, r, 8);
+			aes_encrypt(ctx, b, b);
+			os_memcpy(a, b, 8);
+			a[7] ^= n * j + i;
+			os_memcpy(r, b + 8, 8);
+			r += 8;
+		}
+	}
+	aes_encrypt_deinit(ctx);
+
+	/* 3) Output the results.
+	 *
+	 * These are already in @cipher due to the location of temporary
+	 * variables.
+	 */
+
+	return 0;
+}
diff --git a/contrib/wpa/src/crypto/aes.h b/contrib/wpa/src/crypto/aes.h
index 6b9f4147afb1..ba384a9dae37 100644
--- a/contrib/wpa/src/crypto/aes.h
+++ b/contrib/wpa/src/crypto/aes.h
@@ -15,6 +15,8 @@
 #ifndef AES_H
 #define AES_H
 
+#define AES_BLOCK_SIZE 16
+
 void * aes_encrypt_init(const u8 *key, size_t len);
 void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
 void aes_encrypt_deinit(void *ctx);
diff --git a/contrib/wpa/src/crypto/aes_i.h b/contrib/wpa/src/crypto/aes_i.h
new file mode 100644
index 000000000000..6b40bc781651
--- /dev/null
+++ b/contrib/wpa/src/crypto/aes_i.h
@@ -0,0 +1,122 @@
+/*
+ * AES (Rijndael) cipher
+ * Copyright (c) 2003-2005, Jouni Malinen 
+ *
+ * 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 AES_I_H
+#define AES_I_H
+
+#include "aes.h"
+
+/* #define FULL_UNROLL */
+#define AES_SMALL_TABLES
+
+extern const u32 Te0[256];
+extern const u32 Te1[256];
+extern const u32 Te2[256];
+extern const u32 Te3[256];
+extern const u32 Te4[256];
+extern const u32 Td0[256];
+extern const u32 Td1[256];
+extern const u32 Td2[256];
+extern const u32 Td3[256];
+extern const u32 Td4[256];
+extern const u32 rcon[10];
+extern const u8 Td4s[256];
+extern const u8 rcons[10];
+
+#ifndef AES_SMALL_TABLES
+
+#define RCON(i) rcon[(i)]
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) Te1[((i) >> 16) & 0xff]
+#define TE2(i) Te2[((i) >> 8) & 0xff]
+#define TE3(i) Te3[(i) & 0xff]
+#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
+#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff)
+#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000)
+#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff)
+#define TE4(i) (Te4[(i)] & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) Td1[((i) >> 16) & 0xff]
+#define TD2(i) Td2[((i) >> 8) & 0xff]
+#define TD3(i) Td3[(i) & 0xff]
+#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000)
+#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff)
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) Td1[(i) & 0xff]
+#define TD2_(i) Td2[(i) & 0xff]
+#define TD3_(i) Td3[(i) & 0xff]
+
+#else /* AES_SMALL_TABLES */
+
+#define RCON(i) (rcons[(i)] << 24)
+
+static inline u32 rotr(u32 val, int bits)
+{
+	return (val >> bits) | (val << (32 - bits));
+}
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
+#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
+#define TE3(i) rotr(Te0[(i) & 0xff], 24)
+#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
+#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
+#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
+#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
+#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
+#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
+#define TD3(i) rotr(Td0[(i) & 0xff], 24)
+#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
+#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
+#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
+#define TD44(i) (Td4s[(i) & 0xff])
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
+#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
+#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
+
+#endif /* AES_SMALL_TABLES */
+
+#ifdef _MSC_VER
+#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+#define GETU32(p) SWAP(*((u32 *)(p)))
+#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
+#else
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \
+((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { \
+(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \
+(ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
+#endif
+
+#define AES_PRIV_SIZE (4 * 44)
+
+void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]);
+
+#endif /* AES_I_H */
diff --git a/contrib/wpa/src/crypto/aes_wrap.c b/contrib/wpa/src/crypto/aes_wrap.c
deleted file mode 100644
index b1448b0d9a8d..000000000000
--- a/contrib/wpa/src/crypto/aes_wrap.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * AES-based functions
- *
- * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
- * - One-Key CBC MAC (OMAC1, i.e., CMAC) hash with AES-128
- * - AES-128 CTR mode encryption
- * - AES-128 EAX mode encryption/decryption
- * - AES-128 CBC
- *
- * Copyright (c) 2003-2007, Jouni Malinen 
- *
- * 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 "aes_wrap.h"
-#include "crypto.h"
-
-#ifndef CONFIG_NO_AES_WRAP
-
-/**
- * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
- * @kek: 16-octet Key encryption key (KEK)
- * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
- * bytes
- * @plain: Plaintext key to be wrapped, n * 64 bits
- * @cipher: Wrapped key, (n + 1) * 64 bits
- * Returns: 0 on success, -1 on failure
- */
-int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
-{
-	u8 *a, *r, b[16];
-	int i, j;
-	void *ctx;
-
-	a = cipher;
-	r = cipher + 8;
-
-	/* 1) Initialize variables. */
-	os_memset(a, 0xa6, 8);
-	os_memcpy(r, plain, 8 * n);
-
-	ctx = aes_encrypt_init(kek, 16);
-	if (ctx == NULL)
-		return -1;
-
-	/* 2) Calculate intermediate values.
-	 * For j = 0 to 5
-	 *     For i=1 to n
-	 *         B = AES(K, A | R[i])
-	 *         A = MSB(64, B) ^ t where t = (n*j)+i
-	 *         R[i] = LSB(64, B)
-	 */
-	for (j = 0; j <= 5; j++) {
-		r = cipher + 8;
-		for (i = 1; i <= n; i++) {
-			os_memcpy(b, a, 8);
-			os_memcpy(b + 8, r, 8);
-			aes_encrypt(ctx, b, b);
-			os_memcpy(a, b, 8);
-			a[7] ^= n * j + i;
-			os_memcpy(r, b + 8, 8);
-			r += 8;
-		}
-	}
-	aes_encrypt_deinit(ctx);
-
-	/* 3) Output the results.
-	 *
-	 * These are already in @cipher due to the location of temporary
-	 * variables.
-	 */
-
-	return 0;
-}
-
-#endif /* CONFIG_NO_AES_WRAP */
-
-
-#ifndef CONFIG_NO_AES_UNWRAP
-
-/**
- * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
- * @kek: Key encryption key (KEK)
- * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
- * bytes
- * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
- * @plain: Plaintext key, n * 64 bits
- * Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
- */
-int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
-{
-	u8 a[8], *r, b[16];
-	int i, j;
-	void *ctx;
-
-	/* 1) Initialize variables. */
-	os_memcpy(a, cipher, 8);
-	r = plain;
-	os_memcpy(r, cipher + 8, 8 * n);
-
-	ctx = aes_decrypt_init(kek, 16);
-	if (ctx == NULL)
-		return -1;
-
-	/* 2) Compute intermediate values.
-	 * For j = 5 to 0
-	 *     For i = n to 1
-	 *         B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
-	 *         A = MSB(64, B)
-	 *         R[i] = LSB(64, B)
-	 */
-	for (j = 5; j >= 0; j--) {
-		r = plain + (n - 1) * 8;
-		for (i = n; i >= 1; i--) {
-			os_memcpy(b, a, 8);
-			b[7] ^= n * j + i;
-
-			os_memcpy(b + 8, r, 8);
-			aes_decrypt(ctx, b, b);
-			os_memcpy(a, b, 8);
-			os_memcpy(r, b + 8, 8);
-			r -= 8;
-		}
-	}
-	aes_decrypt_deinit(ctx);
-
-	/* 3) Output results.
-	 *
-	 * These are already in @plain due to the location of temporary
-	 * variables. Just verify that the IV matches with the expected value.
-	 */
-	for (i = 0; i < 8; i++) {
-		if (a[i] != 0xa6)
-			return -1;
-	}
-
-	return 0;
-}
-
-#endif /* CONFIG_NO_AES_UNWRAP */
-
-
-#define BLOCK_SIZE 16
-
-#ifndef CONFIG_NO_AES_OMAC1
-
-static void gf_mulx(u8 *pad)
-{
-	int i, carry;
-
-	carry = pad[0] & 0x80;
-	for (i = 0; i < BLOCK_SIZE - 1; i++)
-		pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
-	pad[BLOCK_SIZE - 1] <<= 1;
-	if (carry)
-		pad[BLOCK_SIZE - 1] ^= 0x87;
-}
-
-
-/**
- * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
- * @key: 128-bit key for the hash operation
- * @num_elem: Number of elements in the data vector
- * @addr: Pointers to the data areas
- * @len: Lengths of the data blocks
- * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
- * Returns: 0 on success, -1 on failure
- *
- * This is a mode for using block cipher (AES in this case) for authentication.
- * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
- * (SP) 800-38B.
- */
-int omac1_aes_128_vector(const u8 *key, size_t num_elem,
-			 const u8 *addr[], const size_t *len, u8 *mac)
-{
-	void *ctx;
-	u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE];
-	const u8 *pos, *end;
-	size_t i, e, left, total_len;
-
-	ctx = aes_encrypt_init(key, 16);
-	if (ctx == NULL)
-		return -1;
-	os_memset(cbc, 0, BLOCK_SIZE);
-
-	total_len = 0;
-	for (e = 0; e < num_elem; e++)
-		total_len += len[e];
-	left = total_len;
-
-	e = 0;
-	pos = addr[0];
-	end = pos + len[0];
-
-	while (left >= BLOCK_SIZE) {
-		for (i = 0; i < BLOCK_SIZE; i++) {
-			cbc[i] ^= *pos++;
-			if (pos >= end) {
-				e++;
-				pos = addr[e];
-				end = pos + len[e];
-			}
-		}
-		if (left > BLOCK_SIZE)
-			aes_encrypt(ctx, cbc, cbc);
-		left -= BLOCK_SIZE;
-	}
-
-	os_memset(pad, 0, BLOCK_SIZE);
-	aes_encrypt(ctx, pad, pad);
-	gf_mulx(pad);
-
-	if (left || total_len == 0) {
-		for (i = 0; i < left; i++) {
-			cbc[i] ^= *pos++;
-			if (pos >= end) {
-				e++;
-				pos = addr[e];
-				end = pos + len[e];
-			}
-		}
-		cbc[left] ^= 0x80;
-		gf_mulx(pad);
-	}
-
-	for (i = 0; i < BLOCK_SIZE; i++)
-		pad[i] ^= cbc[i];
-	aes_encrypt(ctx, pad, mac);
-	aes_encrypt_deinit(ctx);
-	return 0;
-}
-
-
-/**
- * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
- * @key: 128-bit key for the hash operation
- * @data: Data buffer for which a MAC is determined
- * @data_len: Length of data buffer in bytes
- * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
- * Returns: 0 on success, -1 on failure
- *
- * This is a mode for using block cipher (AES in this case) for authentication.
- * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
- * (SP) 800-38B.
- */
-int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
-{
-	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
-}
-
-#endif /* CONFIG_NO_AES_OMAC1 */
-
-
-#ifndef CONFIG_NO_AES_ENCRYPT_BLOCK
-/**
- * aes_128_encrypt_block - Perform one AES 128-bit block operation
- * @key: Key for AES
- * @in: Input data (16 bytes)
- * @out: Output of the AES block operation (16 bytes)
- * Returns: 0 on success, -1 on failure
- */
-int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
-{
-	void *ctx;
-	ctx = aes_encrypt_init(key, 16);
-	if (ctx == NULL)
-		return -1;
-	aes_encrypt(ctx, in, out);
-	aes_encrypt_deinit(ctx);
-	return 0;
-}
-#endif /* CONFIG_NO_AES_ENCRYPT_BLOCK */
-
-
-#ifndef CONFIG_NO_AES_CTR
-
-/**
- * aes_128_ctr_encrypt - AES-128 CTR mode encryption
- * @key: Key for encryption (16 bytes)
- * @nonce: Nonce for counter mode (16 bytes)
- * @data: Data to encrypt in-place
- * @data_len: Length of data in bytes
- * Returns: 0 on success, -1 on failure
- */
-int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
-			u8 *data, size_t data_len)
-{
-	void *ctx;
-	size_t j, len, left = data_len;
-	int i;
-	u8 *pos = data;
-	u8 counter[BLOCK_SIZE], buf[BLOCK_SIZE];
-
-	ctx = aes_encrypt_init(key, 16);
-	if (ctx == NULL)
-		return -1;
-	os_memcpy(counter, nonce, BLOCK_SIZE);
-
-	while (left > 0) {
-		aes_encrypt(ctx, counter, buf);
-
-		len = (left < BLOCK_SIZE) ? left : BLOCK_SIZE;
-		for (j = 0; j < len; j++)
-			pos[j] ^= buf[j];
-		pos += len;
-		left -= len;
-
-		for (i = BLOCK_SIZE - 1; i >= 0; i--) {
-			counter[i]++;
-			if (counter[i])
-				break;
-		}
-	}
-	aes_encrypt_deinit(ctx);
-	return 0;
-}
-
-#endif /* CONFIG_NO_AES_CTR */
-
-
-#ifndef CONFIG_NO_AES_EAX
-
-/**
- * aes_128_eax_encrypt - AES-128 EAX mode encryption
- * @key: Key for encryption (16 bytes)
- * @nonce: Nonce for counter mode
- * @nonce_len: Nonce length in bytes
- * @hdr: Header data to be authenticity protected
- * @hdr_len: Length of the header data bytes
- * @data: Data to encrypt in-place
- * @data_len: Length of data in bytes
- * @tag: 16-byte tag value
- * Returns: 0 on success, -1 on failure
- */
-int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
-			const u8 *hdr, size_t hdr_len,
-			u8 *data, size_t data_len, u8 *tag)
-{
-	u8 *buf;
-	size_t buf_len;
-	u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE];
-	int i, ret = -1;
-
-	if (nonce_len > data_len)
-		buf_len = nonce_len;
-	else
-		buf_len = data_len;
-	if (hdr_len > buf_len)
-		buf_len = hdr_len;
-	buf_len += 16;
-
-	buf = os_malloc(buf_len);
-	if (buf == NULL)
-		return -1;
-
-	os_memset(buf, 0, 15);
-
-	buf[15] = 0;
-	os_memcpy(buf + 16, nonce, nonce_len);
-	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac))
-		goto fail;
-
-	buf[15] = 1;
-	os_memcpy(buf + 16, hdr, hdr_len);
-	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac))
-		goto fail;
-
-	if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len))
-		goto fail;
-	buf[15] = 2;
-	os_memcpy(buf + 16, data, data_len);
-	if (omac1_aes_128(key, buf, 16 + data_len, data_mac))
-		goto fail;
-
-	for (i = 0; i < BLOCK_SIZE; i++)
-		tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i];
-
-	ret = 0;
-fail:
-	os_free(buf);
-
-	return ret;
-}
-
-
-/**
- * aes_128_eax_decrypt - AES-128 EAX mode decryption
- * @key: Key for decryption (16 bytes)
- * @nonce: Nonce for counter mode
- * @nonce_len: Nonce length in bytes
- * @hdr: Header data to be authenticity protected
- * @hdr_len: Length of the header data bytes
- * @data: Data to encrypt in-place
- * @data_len: Length of data in bytes
- * @tag: 16-byte tag value
- * Returns: 0 on success, -1 on failure, -2 if tag does not match
- */
-int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
-			const u8 *hdr, size_t hdr_len,
-			u8 *data, size_t data_len, const u8 *tag)
-{
-	u8 *buf;
-	size_t buf_len;
-	u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE];
-	int i;
-
-	if (nonce_len > data_len)
-		buf_len = nonce_len;
-	else
-		buf_len = data_len;
-	if (hdr_len > buf_len)
-		buf_len = hdr_len;
-	buf_len += 16;
-
-	buf = os_malloc(buf_len);
-	if (buf == NULL)
-		return -1;
-
-	os_memset(buf, 0, 15);
-
-	buf[15] = 0;
-	os_memcpy(buf + 16, nonce, nonce_len);
-	if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) {
-		os_free(buf);
-		return -1;
-	}
-
-	buf[15] = 1;
-	os_memcpy(buf + 16, hdr, hdr_len);
-	if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) {
-		os_free(buf);
-		return -1;
-	}
-
-	buf[15] = 2;
-	os_memcpy(buf + 16, data, data_len);
-	if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) {
-		os_free(buf);
-		return -1;
-	}
-
-	os_free(buf);
-
-	for (i = 0; i < BLOCK_SIZE; i++) {
-		if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]))
-			return -2;
-	}
-
-	return aes_128_ctr_encrypt(key, nonce_mac, data, data_len);
-}
-
-#endif /* CONFIG_NO_AES_EAX */
-
-
-#ifndef CONFIG_NO_AES_CBC
-
-/**
- * aes_128_cbc_encrypt - AES-128 CBC encryption
- * @key: Encryption key
- * @iv: Encryption IV for CBC mode (16 bytes)
- * @data: Data to encrypt in-place
- * @data_len: Length of data in bytes (must be divisible by 16)
- * Returns: 0 on success, -1 on failure
- */
-int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
-{
-	void *ctx;
-	u8 cbc[BLOCK_SIZE];
-	u8 *pos = data;
-	int i, j, blocks;
-
-	ctx = aes_encrypt_init(key, 16);
-	if (ctx == NULL)
-		return -1;
-	os_memcpy(cbc, iv, BLOCK_SIZE);
-
-	blocks = data_len / BLOCK_SIZE;
-	for (i = 0; i < blocks; i++) {
-		for (j = 0; j < BLOCK_SIZE; j++)
-			cbc[j] ^= pos[j];
-		aes_encrypt(ctx, cbc, cbc);
-		os_memcpy(pos, cbc, BLOCK_SIZE);
-		pos += BLOCK_SIZE;
-	}
-	aes_encrypt_deinit(ctx);
-	return 0;
-}
-
-
-/**
- * aes_128_cbc_decrypt - AES-128 CBC decryption
- * @key: Decryption key
- * @iv: Decryption IV for CBC mode (16 bytes)
- * @data: Data to decrypt in-place
- * @data_len: Length of data in bytes (must be divisible by 16)
- * Returns: 0 on success, -1 on failure
- */
-int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
-{
-	void *ctx;
-	u8 cbc[BLOCK_SIZE], tmp[BLOCK_SIZE];
-	u8 *pos = data;
-	int i, j, blocks;
-
-	ctx = aes_decrypt_init(key, 16);
-	if (ctx == NULL)
-		return -1;
-	os_memcpy(cbc, iv, BLOCK_SIZE);
-
-	blocks = data_len / BLOCK_SIZE;
-	for (i = 0; i < blocks; i++) {
-		os_memcpy(tmp, pos, BLOCK_SIZE);
-		aes_decrypt(ctx, pos, pos);
-		for (j = 0; j < BLOCK_SIZE; j++)
-			pos[j] ^= cbc[j];
-		os_memcpy(cbc, tmp, BLOCK_SIZE);
-		pos += BLOCK_SIZE;
-	}
-	aes_decrypt_deinit(ctx);
-	return 0;
-}
-
-#endif /* CONFIG_NO_AES_CBC */
diff --git a/contrib/wpa/src/crypto/crypto.h b/contrib/wpa/src/crypto/crypto.h
index a5129bbd050a..587b5a95747f 100644
--- a/contrib/wpa/src/crypto/crypto.h
+++ b/contrib/wpa/src/crypto/crypto.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / wrapper functions for crypto libraries
- * Copyright (c) 2004-2007, Jouni Malinen 
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -33,8 +33,9 @@
  * @addr: Pointers to the data areas
  * @len: Lengths of the data blocks
  * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
  */
-void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
 
 /**
  * md5_vector - MD5 hash for data vector
@@ -42,8 +43,25 @@ void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
  * @addr: Pointers to the data areas
  * @len: Lengths of the data blocks
  * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
  */
-void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
+
+#ifdef CONFIG_FIPS
+/**
+ * md5_vector_non_fips_allow - MD5 hash for data vector (non-FIPS use allowed)
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
+ */
+int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[],
+			      const size_t *len, u8 *mac);
+#else /* CONFIG_FIPS */
+#define md5_vector_non_fips_allow md5_vector
+#endif /* CONFIG_FIPS */
+
 
 /**
  * sha1_vector - SHA-1 hash for data vector
@@ -51,9 +69,10 @@ void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
  * @addr: Pointers to the data areas
  * @len: Lengths of the data blocks
  * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
  */
-void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
-		 u8 *mac);
+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+		u8 *mac);
 
 /**
  * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF
@@ -76,9 +95,10 @@ int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x,
  * @addr: Pointers to the data areas
  * @len: Lengths of the data blocks
  * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 on failure
  */
-void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
-		   u8 *mac);
+int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+		  u8 *mac);
 
 /**
  * des_encrypt - Encrypt one block with DES
@@ -275,6 +295,7 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len);
  * crypto_private_key_import - Import an RSA private key
  * @key: Key buffer (DER encoded RSA private key)
  * @len: Key buffer length in bytes
+ * @passwd: Key encryption password or %NULL if key is not encrypted
  * Returns: Pointer to the private key or %NULL on failure
  *
  * This function is only used with internal TLSv1 implementation
@@ -282,7 +303,8 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len);
  * to implement this.
  */
 struct crypto_private_key * crypto_private_key_import(const u8 *key,
-						      size_t len);
+						      size_t len,
+						      const char *passwd);
 
 /**
  * crypto_public_key_from_cert - Import an RSA public key from a certificate
@@ -428,4 +450,20 @@ int __must_check crypto_mod_exp(const u8 *base, size_t base_len,
 				const u8 *modulus, size_t modulus_len,
 				u8 *result, size_t *result_len);
 
+/**
+ * rc4_skip - XOR RC4 stream to given data with skip-stream-start
+ * @key: RC4 key
+ * @keylen: RC4 key length
+ * @skip: number of bytes to skip from the beginning of the RC4 stream
+ * @data: data to be XOR'ed with RC4 stream
+ * @data_len: buf length
+ * Returns: 0 on success, -1 on failure
+ *
+ * Generate RC4 pseudo random stream for the given key, skip beginning of the
+ * stream, and XOR the end result with the data buffer to perform RC4
+ * encryption/decryption.
+ */
+int rc4_skip(const u8 *key, size_t keylen, size_t skip,
+	     u8 *data, size_t data_len);
+
 #endif /* CRYPTO_H */
diff --git a/contrib/wpa/src/crypto/crypto_cryptoapi.c b/contrib/wpa/src/crypto/crypto_cryptoapi.c
index 45333dd2e396..2a8d2001b173 100644
--- a/contrib/wpa/src/crypto/crypto_cryptoapi.c
+++ b/contrib/wpa/src/crypto/crypto_cryptoapi.c
@@ -33,7 +33,6 @@ L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
 #define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC)
 #endif
 
-#ifdef CONFIG_TLS_INTERNAL
 #ifdef __MINGW32_VERSION
 /*
  * MinGW does not yet include all the needed definitions for CryptoAPI, so
@@ -83,7 +82,6 @@ static int mingw_load_crypto_func(void)
 }
 
 #endif /* __MINGW32_VERSION */
-#endif /* CONFIG_TLS_INTERNAL */
 
 
 static void cryptoapi_report_error(const char *msg)
@@ -152,9 +150,9 @@ int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem,
 }
 
 
-void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
-	cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac);
+	return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac);
 }
 
 
@@ -223,16 +221,15 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
 }
 
 
-#ifdef EAP_TLS_FUNCS
-void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
-	cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac);
+	return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac);
 }
 
 
-void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
-	cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac);
+	return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac);
 }
 
 
@@ -349,7 +346,6 @@ void aes_decrypt_deinit(void *ctx)
 	aes_encrypt_deinit(ctx);
 }
 
-#ifdef CONFIG_TLS_INTERNAL
 
 struct crypto_hash {
 	enum crypto_hash_alg alg;
@@ -657,7 +653,8 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
 
 
 struct crypto_private_key * crypto_private_key_import(const u8 *key,
-						      size_t len)
+						      size_t len,
+						      const char *passwd)
 {
 	/* TODO */
 	return NULL;
@@ -781,6 +778,12 @@ void crypto_global_deinit(void)
 {
 }
 
-#endif /* CONFIG_TLS_INTERNAL */
 
-#endif /* EAP_TLS_FUNCS */
+int crypto_mod_exp(const u8 *base, size_t base_len,
+		   const u8 *power, size_t power_len,
+		   const u8 *modulus, size_t modulus_len,
+		   u8 *result, size_t *result_len)
+{
+	/* TODO */
+	return -1;
+}
diff --git a/contrib/wpa/src/crypto/crypto_gnutls.c b/contrib/wpa/src/crypto/crypto_gnutls.c
index 8f8611c0fb33..0998cca54672 100644
--- a/contrib/wpa/src/crypto/crypto_gnutls.c
+++ b/contrib/wpa/src/crypto/crypto_gnutls.c
@@ -18,20 +18,21 @@
 #include "common.h"
 #include "crypto.h"
 
-void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	gcry_md_hd_t hd;
 	unsigned char *p;
 	size_t i;
 
 	if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR)
-		return;
+		return -1;
 	for (i = 0; i < num_elem; i++)
 		gcry_md_write(hd, addr[i], len[i]);
 	p = gcry_md_read(hd, GCRY_MD_MD4);
 	if (p)
 		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4));
 	gcry_md_close(hd);
+	return 0;
 }
 
 
@@ -57,49 +58,42 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
 }
 
 
-void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	gcry_md_hd_t hd;
 	unsigned char *p;
 	size_t i;
 
 	if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR)
-		return;
+		return -1;
 	for (i = 0; i < num_elem; i++)
 		gcry_md_write(hd, addr[i], len[i]);
 	p = gcry_md_read(hd, GCRY_MD_MD5);
 	if (p)
 		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5));
 	gcry_md_close(hd);
+	return 0;
 }
 
 
-void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	gcry_md_hd_t hd;
 	unsigned char *p;
 	size_t i;
 
 	if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR)
-		return;
+		return -1;
 	for (i = 0; i < num_elem; i++)
 		gcry_md_write(hd, addr[i], len[i]);
 	p = gcry_md_read(hd, GCRY_MD_SHA1);
 	if (p)
 		memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1));
 	gcry_md_close(hd);
+	return 0;
 }
 
 
-#ifndef CONFIG_NO_FIPS186_2_PRF
-int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
-{
-	/* FIX: how to do this with libgcrypt? */
-	return -1;
-}
-#endif /* CONFIG_NO_FIPS186_2_PRF */
-
-
 void * aes_encrypt_init(const u8 *key, size_t len)
 {
 	gcry_cipher_hd_t hd;
diff --git a/contrib/wpa/src/crypto/crypto_internal-cipher.c b/contrib/wpa/src/crypto/crypto_internal-cipher.c
new file mode 100644
index 000000000000..75134f09a403
--- /dev/null
+++ b/contrib/wpa/src/crypto/crypto_internal-cipher.c
@@ -0,0 +1,256 @@
+/*
+ * Crypto wrapper for internal crypto implementation - Cipher wrappers
+ * Copyright (c) 2006-2009, Jouni Malinen 
+ *
+ * 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.h"
+#include "aes.h"
+#include "des_i.h"
+
+
+struct crypto_cipher {
+	enum crypto_cipher_alg alg;
+	union {
+		struct {
+			size_t used_bytes;
+			u8 key[16];
+			size_t keylen;
+		} rc4;
+		struct {
+			u8 cbc[32];
+			size_t block_size;
+			void *ctx_enc;
+			void *ctx_dec;
+		} aes;
+		struct {
+			struct des3_key_s key;
+			u8 cbc[8];
+		} des3;
+		struct {
+			u32 ek[32];
+			u32 dk[32];
+			u8 cbc[8];
+		} des;
+	} u;
+};
+
+
+struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
+					  const u8 *iv, const u8 *key,
+					  size_t key_len)
+{
+	struct crypto_cipher *ctx;
+
+	ctx = os_zalloc(sizeof(*ctx));
+	if (ctx == NULL)
+		return NULL;
+
+	ctx->alg = alg;
+
+	switch (alg) {
+	case CRYPTO_CIPHER_ALG_RC4:
+		if (key_len > sizeof(ctx->u.rc4.key)) {
+			os_free(ctx);
+			return NULL;
+		}
+		ctx->u.rc4.keylen = key_len;
+		os_memcpy(ctx->u.rc4.key, key, key_len);
+		break;
+	case CRYPTO_CIPHER_ALG_AES:
+		if (key_len > sizeof(ctx->u.aes.cbc)) {
+			os_free(ctx);
+			return NULL;
+		}
+		ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len);
+		if (ctx->u.aes.ctx_enc == NULL) {
+			os_free(ctx);
+			return NULL;
+		}
+		ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len);
+		if (ctx->u.aes.ctx_dec == NULL) {
+			aes_encrypt_deinit(ctx->u.aes.ctx_enc);
+			os_free(ctx);
+			return NULL;
+		}
+		ctx->u.aes.block_size = key_len;
+		os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size);
+		break;
+	case CRYPTO_CIPHER_ALG_3DES:
+		if (key_len != 24) {
+			os_free(ctx);
+			return NULL;
+		}
+		des3_key_setup(key, &ctx->u.des3.key);
+		os_memcpy(ctx->u.des3.cbc, iv, 8);
+		break;
+	case CRYPTO_CIPHER_ALG_DES:
+		if (key_len != 8) {
+			os_free(ctx);
+			return NULL;
+		}
+		des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk);
+		os_memcpy(ctx->u.des.cbc, iv, 8);
+		break;
+	default:
+		os_free(ctx);
+		return NULL;
+	}
+
+	return ctx;
+}
+
+
+int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
+			  u8 *crypt, size_t len)
+{
+	size_t i, j, blocks;
+
+	switch (ctx->alg) {
+	case CRYPTO_CIPHER_ALG_RC4:
+		if (plain != crypt)
+			os_memcpy(crypt, plain, len);
+		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
+			 ctx->u.rc4.used_bytes, crypt, len);
+		ctx->u.rc4.used_bytes += len;
+		break;
+	case CRYPTO_CIPHER_ALG_AES:
+		if (len % ctx->u.aes.block_size)
+			return -1;
+		blocks = len / ctx->u.aes.block_size;
+		for (i = 0; i < blocks; i++) {
+			for (j = 0; j < ctx->u.aes.block_size; j++)
+				ctx->u.aes.cbc[j] ^= plain[j];
+			aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc,
+				    ctx->u.aes.cbc);
+			os_memcpy(crypt, ctx->u.aes.cbc,
+				  ctx->u.aes.block_size);
+			plain += ctx->u.aes.block_size;
+			crypt += ctx->u.aes.block_size;
+		}
+		break;
+	case CRYPTO_CIPHER_ALG_3DES:
+		if (len % 8)
+			return -1;
+		blocks = len / 8;
+		for (i = 0; i < blocks; i++) {
+			for (j = 0; j < 8; j++)
+				ctx->u.des3.cbc[j] ^= plain[j];
+			des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key,
+				     ctx->u.des3.cbc);
+			os_memcpy(crypt, ctx->u.des3.cbc, 8);
+			plain += 8;
+			crypt += 8;
+		}
+		break;
+	case CRYPTO_CIPHER_ALG_DES:
+		if (len % 8)
+			return -1;
+		blocks = len / 8;
+		for (i = 0; i < blocks; i++) {
+			for (j = 0; j < 8; j++)
+				ctx->u.des3.cbc[j] ^= plain[j];
+			des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek,
+					  ctx->u.des.cbc);
+			os_memcpy(crypt, ctx->u.des.cbc, 8);
+			plain += 8;
+			crypt += 8;
+		}
+		break;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
+			  u8 *plain, size_t len)
+{
+	size_t i, j, blocks;
+	u8 tmp[32];
+
+	switch (ctx->alg) {
+	case CRYPTO_CIPHER_ALG_RC4:
+		if (plain != crypt)
+			os_memcpy(plain, crypt, len);
+		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
+			 ctx->u.rc4.used_bytes, plain, len);
+		ctx->u.rc4.used_bytes += len;
+		break;
+	case CRYPTO_CIPHER_ALG_AES:
+		if (len % ctx->u.aes.block_size)
+			return -1;
+		blocks = len / ctx->u.aes.block_size;
+		for (i = 0; i < blocks; i++) {
+			os_memcpy(tmp, crypt, ctx->u.aes.block_size);
+			aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain);
+			for (j = 0; j < ctx->u.aes.block_size; j++)
+				plain[j] ^= ctx->u.aes.cbc[j];
+			os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size);
+			plain += ctx->u.aes.block_size;
+			crypt += ctx->u.aes.block_size;
+		}
+		break;
+	case CRYPTO_CIPHER_ALG_3DES:
+		if (len % 8)
+			return -1;
+		blocks = len / 8;
+		for (i = 0; i < blocks; i++) {
+			os_memcpy(tmp, crypt, 8);
+			des3_decrypt(crypt, &ctx->u.des3.key, plain);
+			for (j = 0; j < 8; j++)
+				plain[j] ^= ctx->u.des3.cbc[j];
+			os_memcpy(ctx->u.des3.cbc, tmp, 8);
+			plain += 8;
+			crypt += 8;
+		}
+		break;
+	case CRYPTO_CIPHER_ALG_DES:
+		if (len % 8)
+			return -1;
+		blocks = len / 8;
+		for (i = 0; i < blocks; i++) {
+			os_memcpy(tmp, crypt, 8);
+			des_block_decrypt(crypt, ctx->u.des.dk, plain);
+			for (j = 0; j < 8; j++)
+				plain[j] ^= ctx->u.des.cbc[j];
+			os_memcpy(ctx->u.des.cbc, tmp, 8);
+			plain += 8;
+			crypt += 8;
+		}
+		break;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+
+void crypto_cipher_deinit(struct crypto_cipher *ctx)
+{
+	switch (ctx->alg) {
+	case CRYPTO_CIPHER_ALG_AES:
+		aes_encrypt_deinit(ctx->u.aes.ctx_enc);
+		aes_decrypt_deinit(ctx->u.aes.ctx_dec);
+		break;
+	case CRYPTO_CIPHER_ALG_3DES:
+		break;
+	default:
+		break;
+	}
+	os_free(ctx);
+}
diff --git a/contrib/wpa/src/crypto/crypto_internal-modexp.c b/contrib/wpa/src/crypto/crypto_internal-modexp.c
new file mode 100644
index 000000000000..3124742e87cd
--- /dev/null
+++ b/contrib/wpa/src/crypto/crypto_internal-modexp.c
@@ -0,0 +1,55 @@
+/*
+ * Crypto wrapper for internal crypto implementation - modexp
+ * Copyright (c) 2006-2009, Jouni Malinen 
+ *
+ * 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 "tls/bignum.h"
+#include "crypto.h"
+
+
+int crypto_mod_exp(const u8 *base, size_t base_len,
+		   const u8 *power, size_t power_len,
+		   const u8 *modulus, size_t modulus_len,
+		   u8 *result, size_t *result_len)
+{
+	struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result;
+	int ret = -1;
+
+	bn_base = bignum_init();
+	bn_exp = bignum_init();
+	bn_modulus = bignum_init();
+	bn_result = bignum_init();
+
+	if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
+	    bn_result == NULL)
+		goto error;
+
+	if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 ||
+	    bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 ||
+	    bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0)
+		goto error;
+
+	if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0)
+		goto error;
+
+	ret = bignum_get_unsigned_bin(bn_result, result, result_len);
+
+error:
+	bignum_deinit(bn_base);
+	bignum_deinit(bn_exp);
+	bignum_deinit(bn_modulus);
+	bignum_deinit(bn_result);
+	return ret;
+}
diff --git a/contrib/wpa/src/crypto/crypto_internal-rsa.c b/contrib/wpa/src/crypto/crypto_internal-rsa.c
new file mode 100644
index 000000000000..205042cf3631
--- /dev/null
+++ b/contrib/wpa/src/crypto/crypto_internal-rsa.c
@@ -0,0 +1,115 @@
+/*
+ * Crypto wrapper for internal crypto implementation - RSA parts
+ * Copyright (c) 2006-2009, Jouni Malinen 
+ *
+ * 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.h"
+#include "tls/rsa.h"
+#include "tls/bignum.h"
+#include "tls/pkcs1.h"
+#include "tls/pkcs8.h"
+
+/* Dummy structures; these are just typecast to struct crypto_rsa_key */
+struct crypto_public_key;
+struct crypto_private_key;
+
+
+struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
+{
+	return (struct crypto_public_key *)
+		crypto_rsa_import_public_key(key, len);
+}
+
+
+struct crypto_private_key * crypto_private_key_import(const u8 *key,
+						      size_t len,
+						      const char *passwd)
+{
+	struct crypto_private_key *res;
+
+	/* First, check for possible PKCS #8 encoding */
+	res = pkcs8_key_import(key, len);
+	if (res)
+		return res;
+
+	if (passwd) {
+		/* Try to parse as encrypted PKCS #8 */
+		res = pkcs8_enc_key_import(key, len, passwd);
+		if (res)
+			return res;
+	}
+
+	/* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */
+	wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private "
+		   "key");
+	return (struct crypto_private_key *)
+		crypto_rsa_import_private_key(key, len);
+}
+
+
+struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
+						       size_t len)
+{
+	/* No X.509 support in crypto_internal.c */
+	return NULL;
+}
+
+
+int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
+					const u8 *in, size_t inlen,
+					u8 *out, size_t *outlen)
+{
+	return pkcs1_encrypt(2, (struct crypto_rsa_key *) key,
+			     0, in, inlen, out, outlen);
+}
+
+
+int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key,
+					 const u8 *in, size_t inlen,
+					 u8 *out, size_t *outlen)
+{
+	return pkcs1_v15_private_key_decrypt((struct crypto_rsa_key *) key,
+					     in, inlen, out, outlen);
+}
+
+
+int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
+				  const u8 *in, size_t inlen,
+				  u8 *out, size_t *outlen)
+{
+	return pkcs1_encrypt(1, (struct crypto_rsa_key *) key,
+			     1, in, inlen, out, outlen);
+}
+
+
+void crypto_public_key_free(struct crypto_public_key *key)
+{
+	crypto_rsa_free((struct crypto_rsa_key *) key);
+}
+
+
+void crypto_private_key_free(struct crypto_private_key *key)
+{
+	crypto_rsa_free((struct crypto_rsa_key *) key);
+}
+
+
+int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
+				    const u8 *crypt, size_t crypt_len,
+				    u8 *plain, size_t *plain_len)
+{
+	return pkcs1_decrypt_public_key((struct crypto_rsa_key *) key,
+					crypt, crypt_len, plain, plain_len);
+}
diff --git a/contrib/wpa/src/crypto/crypto_internal.c b/contrib/wpa/src/crypto/crypto_internal.c
index cddfb4de8ea9..8fdba6580275 100644
--- a/contrib/wpa/src/crypto/crypto_internal.c
+++ b/contrib/wpa/src/crypto/crypto_internal.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / Crypto wrapper for internal crypto implementation
- * Copyright (c) 2006-2007, Jouni Malinen 
+ * Crypto wrapper for internal crypto implementation
+ * Copyright (c) 2006-2009, Jouni Malinen 
  *
  * 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
@@ -16,42 +16,8 @@
 
 #include "common.h"
 #include "crypto.h"
-#include "md5.h"
-#include "sha1.h"
-#include "rc4.h"
-#include "aes.h"
-#include "tls/rsa.h"
-#include "tls/bignum.h"
-#include "tls/asn1.h"
-
-
-#ifdef CONFIG_CRYPTO_INTERNAL
-
-#ifdef CONFIG_TLS_INTERNAL
-
-/* from des.c */
-struct des3_key_s {
-	u32 ek[3][32];
-	u32 dk[3][32];
-};
-
-void des3_key_setup(const u8 *key, struct des3_key_s *dkey);
-void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt);
-void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain);
-
-
-struct MD5Context {
-	u32 buf[4];
-	u32 bits[2];
-	u8 in[64];
-};
-
-struct SHA1Context {
-	u32 state[5];
-	u32 count[2];
-	unsigned char buffer[64];
-};
-
+#include "sha1_i.h"
+#include "md5_i.h"
 
 struct crypto_hash {
 	enum crypto_hash_alg alg;
@@ -228,559 +194,6 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
 }
 
 
-struct crypto_cipher {
-	enum crypto_cipher_alg alg;
-	union {
-		struct {
-			size_t used_bytes;
-			u8 key[16];
-			size_t keylen;
-		} rc4;
-		struct {
-			u8 cbc[32];
-			size_t block_size;
-			void *ctx_enc;
-			void *ctx_dec;
-		} aes;
-		struct {
-			struct des3_key_s key;
-			u8 cbc[8];
-		} des3;
-	} u;
-};
-
-
-struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
-					  const u8 *iv, const u8 *key,
-					  size_t key_len)
-{
-	struct crypto_cipher *ctx;
-
-	ctx = os_zalloc(sizeof(*ctx));
-	if (ctx == NULL)
-		return NULL;
-
-	ctx->alg = alg;
-
-	switch (alg) {
-	case CRYPTO_CIPHER_ALG_RC4:
-		if (key_len > sizeof(ctx->u.rc4.key)) {
-			os_free(ctx);
-			return NULL;
-		}
-		ctx->u.rc4.keylen = key_len;
-		os_memcpy(ctx->u.rc4.key, key, key_len);
-		break;
-	case CRYPTO_CIPHER_ALG_AES:
-		if (key_len > sizeof(ctx->u.aes.cbc)) {
-			os_free(ctx);
-			return NULL;
-		}
-		ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len);
-		if (ctx->u.aes.ctx_enc == NULL) {
-			os_free(ctx);
-			return NULL;
-		}
-		ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len);
-		if (ctx->u.aes.ctx_dec == NULL) {
-			aes_encrypt_deinit(ctx->u.aes.ctx_enc);
-			os_free(ctx);
-			return NULL;
-		}
-		ctx->u.aes.block_size = key_len;
-		os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size);
-		break;
-	case CRYPTO_CIPHER_ALG_3DES:
-		if (key_len != 24) {
-			os_free(ctx);
-			return NULL;
-		}
-		des3_key_setup(key, &ctx->u.des3.key);
-		os_memcpy(ctx->u.des3.cbc, iv, 8);
-		break;
-	default:
-		os_free(ctx);
-		return NULL;
-	}
-
-	return ctx;
-}
-
-
-int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
-			  u8 *crypt, size_t len)
-{
-	size_t i, j, blocks;
-
-	switch (ctx->alg) {
-	case CRYPTO_CIPHER_ALG_RC4:
-		if (plain != crypt)
-			os_memcpy(crypt, plain, len);
-		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
-			 ctx->u.rc4.used_bytes, crypt, len);
-		ctx->u.rc4.used_bytes += len;
-		break;
-	case CRYPTO_CIPHER_ALG_AES:
-		if (len % ctx->u.aes.block_size)
-			return -1;
-		blocks = len / ctx->u.aes.block_size;
-		for (i = 0; i < blocks; i++) {
-			for (j = 0; j < ctx->u.aes.block_size; j++)
-				ctx->u.aes.cbc[j] ^= plain[j];
-			aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc,
-				    ctx->u.aes.cbc);
-			os_memcpy(crypt, ctx->u.aes.cbc,
-				  ctx->u.aes.block_size);
-			plain += ctx->u.aes.block_size;
-			crypt += ctx->u.aes.block_size;
-		}
-		break;
-	case CRYPTO_CIPHER_ALG_3DES:
-		if (len % 8)
-			return -1;
-		blocks = len / 8;
-		for (i = 0; i < blocks; i++) {
-			for (j = 0; j < 8; j++)
-				ctx->u.des3.cbc[j] ^= plain[j];
-			des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key,
-				     ctx->u.des3.cbc);
-			os_memcpy(crypt, ctx->u.des3.cbc, 8);
-			plain += 8;
-			crypt += 8;
-		}
-		break;
-	default:
-		return -1;
-	}
-
-	return 0;
-}
-
-
-int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
-			  u8 *plain, size_t len)
-{
-	size_t i, j, blocks;
-	u8 tmp[32];
-
-	switch (ctx->alg) {
-	case CRYPTO_CIPHER_ALG_RC4:
-		if (plain != crypt)
-			os_memcpy(plain, crypt, len);
-		rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
-			 ctx->u.rc4.used_bytes, plain, len);
-		ctx->u.rc4.used_bytes += len;
-		break;
-	case CRYPTO_CIPHER_ALG_AES:
-		if (len % ctx->u.aes.block_size)
-			return -1;
-		blocks = len / ctx->u.aes.block_size;
-		for (i = 0; i < blocks; i++) {
-			os_memcpy(tmp, crypt, ctx->u.aes.block_size);
-			aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain);
-			for (j = 0; j < ctx->u.aes.block_size; j++)
-				plain[j] ^= ctx->u.aes.cbc[j];
-			os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size);
-			plain += ctx->u.aes.block_size;
-			crypt += ctx->u.aes.block_size;
-		}
-		break;
-	case CRYPTO_CIPHER_ALG_3DES:
-		if (len % 8)
-			return -1;
-		blocks = len / 8;
-		for (i = 0; i < blocks; i++) {
-			os_memcpy(tmp, crypt, 8);
-			des3_decrypt(crypt, &ctx->u.des3.key, plain);
-			for (j = 0; j < 8; j++)
-				plain[j] ^= ctx->u.des3.cbc[j];
-			os_memcpy(ctx->u.des3.cbc, tmp, 8);
-			plain += 8;
-			crypt += 8;
-		}
-		break;
-	default:
-		return -1;
-	}
-
-	return 0;
-}
-
-
-void crypto_cipher_deinit(struct crypto_cipher *ctx)
-{
-	switch (ctx->alg) {
-	case CRYPTO_CIPHER_ALG_AES:
-		aes_encrypt_deinit(ctx->u.aes.ctx_enc);
-		aes_decrypt_deinit(ctx->u.aes.ctx_dec);
-		break;
-	case CRYPTO_CIPHER_ALG_3DES:
-		break;
-	default:
-		break;
-	}
-	os_free(ctx);
-}
-
-
-/* Dummy structures; these are just typecast to struct crypto_rsa_key */
-struct crypto_public_key;
-struct crypto_private_key;
-
-
-struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
-{
-	return (struct crypto_public_key *)
-		crypto_rsa_import_public_key(key, len);
-}
-
-
-#ifdef EAP_TLS_FUNCS
-static struct crypto_private_key *
-crypto_pkcs8_key_import(const u8 *buf, size_t len)
-{
-	struct asn1_hdr hdr;
-	const u8 *pos, *end;
-	struct bignum *zero;
-	struct asn1_oid oid;
-	char obuf[80];
-
-	/* PKCS #8, Chapter 6 */
-
-	/* PrivateKeyInfo ::= SEQUENCE */
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
-			   "header (SEQUENCE); assume PKCS #8 not used");
-		return NULL;
-	}
-	pos = hdr.payload;
-	end = pos + hdr.length;
-
-	/* version Version (Version ::= INTEGER) */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found "
-			   "class %d tag 0x%x; assume PKCS #8 not used",
-			   hdr.class, hdr.tag);
-		return NULL;
-	}
-
-	zero = bignum_init();
-	if (zero == NULL)
-		return NULL;
-
-	if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
-		bignum_deinit(zero);
-		return NULL;
-	}
-	pos = hdr.payload + hdr.length;
-
-	if (bignum_cmp_d(zero, 0) != 0) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
-			   "beginning of private key; not found; assume "
-			   "PKCS #8 not used");
-		bignum_deinit(zero);
-		return NULL;
-	}
-	bignum_deinit(zero);
-
-	/* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
-	 * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
-			   "(AlgorithmIdentifier) - found class %d tag 0x%x; "
-			   "assume PKCS #8 not used",
-			   hdr.class, hdr.tag);
-		return NULL;
-	}
-
-	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
-			   "(algorithm); assume PKCS #8 not used");
-		return NULL;
-	}
-
-	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
-	wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
-
-	if (oid.len != 7 ||
-	    oid.oid[0] != 1 /* iso */ ||
-	    oid.oid[1] != 2 /* member-body */ ||
-	    oid.oid[2] != 840 /* us */ ||
-	    oid.oid[3] != 113549 /* rsadsi */ ||
-	    oid.oid[4] != 1 /* pkcs */ ||
-	    oid.oid[5] != 1 /* pkcs-1 */ ||
-	    oid.oid[6] != 1 /* rsaEncryption */) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
-			   "algorithm %s", obuf);
-		return NULL;
-	}
-
-	pos = hdr.payload + hdr.length;
-
-	/* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
-			   "(privateKey) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
-		return NULL;
-	}
-	wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
-
-	return (struct crypto_private_key *)
-		crypto_rsa_import_private_key(hdr.payload, hdr.length);
-}
-#endif /* EAP_TLS_FUNCS */
-
-
-struct crypto_private_key * crypto_private_key_import(const u8 *key,
-						      size_t len)
-{
-	struct crypto_private_key *res;
-
-	/* First, check for possible PKCS #8 encoding */
-	res = crypto_pkcs8_key_import(key, len);
-	if (res)
-		return res;
-
-	/* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */
-	wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private "
-		   "key");
-	return (struct crypto_private_key *)
-		crypto_rsa_import_private_key(key, len);
-}
-
-
-struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
-						       size_t len)
-{
-	/* No X.509 support in crypto_internal.c */
-	return NULL;
-}
-
-
-static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
-					   const u8 *in, size_t inlen,
-					   u8 *out, size_t *outlen)
-{
-	size_t ps_len;
-	u8 *pos;
-
-	/*
-	 * PKCS #1 v1.5, 8.1:
-	 *
-	 * EB = 00 || BT || PS || 00 || D
-	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
-	 * PS = k-3-||D||; at least eight octets
-	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
-	 * k = length of modulus in octets (modlen)
-	 */
-
-	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
-		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
-			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
-			   __func__, (unsigned long) modlen,
-			   (unsigned long) *outlen,
-			   (unsigned long) inlen);
-		return -1;
-	}
-
-	pos = out;
-	*pos++ = 0x00;
-	*pos++ = block_type; /* BT */
-	ps_len = modlen - inlen - 3;
-	switch (block_type) {
-	case 0:
-		os_memset(pos, 0x00, ps_len);
-		pos += ps_len;
-		break;
-	case 1:
-		os_memset(pos, 0xff, ps_len);
-		pos += ps_len;
-		break;
-	case 2:
-		if (os_get_random(pos, ps_len) < 0) {
-			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
-				   "random data for PS", __func__);
-			return -1;
-		}
-		while (ps_len--) {
-			if (*pos == 0x00)
-				*pos = 0x01;
-			pos++;
-		}
-		break;
-	default:
-		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
-			   "%d", __func__, block_type);
-		return -1;
-	}
-	*pos++ = 0x00;
-	os_memcpy(pos, in, inlen); /* D */
-
-	return 0;
-}
-
-
-static int crypto_rsa_encrypt_pkcs1(int block_type, struct crypto_rsa_key *key,
-				    int use_private,
-				    const u8 *in, size_t inlen,
-				    u8 *out, size_t *outlen)
-{
-	size_t modlen;
-
-	modlen = crypto_rsa_get_modulus_len(key);
-
-	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
-					    out, outlen) < 0)
-		return -1;
-
-	return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private);
-}
-
-
-int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
-					const u8 *in, size_t inlen,
-					u8 *out, size_t *outlen)
-{
-	return crypto_rsa_encrypt_pkcs1(2, (struct crypto_rsa_key *) key,
-					0, in, inlen, out, outlen);
-}
-
-
-int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key,
-					 const u8 *in, size_t inlen,
-					 u8 *out, size_t *outlen)
-{
-	struct crypto_rsa_key *rkey = (struct crypto_rsa_key *) key;
-	int res;
-	u8 *pos, *end;
-
-	res = crypto_rsa_exptmod(in, inlen, out, outlen, rkey, 1);
-	if (res)
-		return res;
-
-	if (*outlen < 2 || out[0] != 0 || out[1] != 2)
-		return -1;
-
-	/* Skip PS (pseudorandom non-zero octets) */
-	pos = out + 2;
-	end = out + *outlen;
-	while (*pos && pos < end)
-		pos++;
-	if (pos == end)
-		return -1;
-	pos++;
-
-	*outlen -= pos - out;
-
-	/* Strip PKCS #1 header */
-	os_memmove(out, pos, *outlen);
-
-	return 0;
-}
-
-
-int crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
-				  const u8 *in, size_t inlen,
-				  u8 *out, size_t *outlen)
-{
-	return crypto_rsa_encrypt_pkcs1(1, (struct crypto_rsa_key *) key,
-					1, in, inlen, out, outlen);
-}
-
-
-void crypto_public_key_free(struct crypto_public_key *key)
-{
-	crypto_rsa_free((struct crypto_rsa_key *) key);
-}
-
-
-void crypto_private_key_free(struct crypto_private_key *key)
-{
-	crypto_rsa_free((struct crypto_rsa_key *) key);
-}
-
-
-int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
-				    const u8 *crypt, size_t crypt_len,
-				    u8 *plain, size_t *plain_len)
-{
-	size_t len;
-	u8 *pos;
-
-	len = *plain_len;
-	if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len,
-			       (struct crypto_rsa_key *) key, 0) < 0)
-		return -1;
-
-	/*
-	 * PKCS #1 v1.5, 8.1:
-	 *
-	 * EB = 00 || BT || PS || 00 || D
-	 * BT = 00 or 01
-	 * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01)
-	 * k = length of modulus in octets
-	 */
-
-	if (len < 3 + 8 + 16 /* min hash len */ ||
-	    plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) {
-		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
-			   "structure");
-		return -1;
-	}
-
-	pos = plain + 3;
-	if (plain[1] == 0x00) {
-		/* BT = 00 */
-		if (plain[2] != 0x00) {
-			wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
-				   "PS (BT=00)");
-			return -1;
-		}
-		while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00)
-			pos++;
-	} else {
-		/* BT = 01 */
-		if (plain[2] != 0xff) {
-			wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
-				   "PS (BT=01)");
-			return -1;
-		}
-		while (pos < plain + len && *pos == 0xff)
-			pos++;
-	}
-
-	if (pos - plain - 2 < 8) {
-		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
-		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
-			   "padding");
-		return -1;
-	}
-
-	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
-		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
-			   "structure (2)");
-		return -1;
-	}
-	pos++;
-	len -= pos - plain;
-
-	/* Strip PKCS #1 header */
-	os_memmove(plain, pos, len);
-	*plain_len = len;
-
-	return 0;
-}
-
-
 int crypto_global_init(void)
 {
 	return 0;
@@ -790,47 +203,3 @@ int crypto_global_init(void)
 void crypto_global_deinit(void)
 {
 }
-#endif /* CONFIG_TLS_INTERNAL */
-
-
-#if defined(EAP_FAST) || defined(CONFIG_WPS)
-
-int crypto_mod_exp(const u8 *base, size_t base_len,
-		   const u8 *power, size_t power_len,
-		   const u8 *modulus, size_t modulus_len,
-		   u8 *result, size_t *result_len)
-{
-	struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result;
-	int ret = -1;
-
-	bn_base = bignum_init();
-	bn_exp = bignum_init();
-	bn_modulus = bignum_init();
-	bn_result = bignum_init();
-
-	if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
-	    bn_result == NULL)
-		goto error;
-
-	if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 ||
-	    bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 ||
-	    bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0)
-		goto error;
-
-	if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0)
-		goto error;
-
-	ret = bignum_get_unsigned_bin(bn_result, result, result_len);
-
-error:
-	bignum_deinit(bn_base);
-	bignum_deinit(bn_exp);
-	bignum_deinit(bn_modulus);
-	bignum_deinit(bn_result);
-	return ret;
-}
-
-#endif /* EAP_FAST || CONFIG_WPS */
-
-
-#endif /* CONFIG_CRYPTO_INTERNAL */
diff --git a/contrib/wpa/src/crypto/crypto_libtomcrypt.c b/contrib/wpa/src/crypto/crypto_libtomcrypt.c
index e82097f10a00..52b67a713d69 100644
--- a/contrib/wpa/src/crypto/crypto_libtomcrypt.c
+++ b/contrib/wpa/src/crypto/crypto_libtomcrypt.c
@@ -16,7 +16,6 @@
 #include 
 
 #include "common.h"
-#include "rc4.h"
 #include "crypto.h"
 
 #ifndef mp_init_multi
@@ -29,7 +28,7 @@
 #endif
 
 
-void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	hash_state md;
 	size_t i;
@@ -38,6 +37,7 @@ void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 	for (i = 0; i < num_elem; i++)
 		md4_process(&md, addr[i], len[i]);
 	md4_done(&md, mac);
+	return 0;
 }
 
 
@@ -62,8 +62,7 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
 }
 
 
-#ifdef EAP_TLS_FUNCS
-void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	hash_state md;
 	size_t i;
@@ -72,10 +71,11 @@ void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 	for (i = 0; i < num_elem; i++)
 		md5_process(&md, addr[i], len[i]);
 	md5_done(&md, mac);
+	return 0;
 }
 
 
-void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	hash_state md;
 	size_t i;
@@ -84,6 +84,7 @@ void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 	for (i = 0; i < num_elem; i++)
 		sha1_process(&md, addr[i], len[i]);
 	sha1_done(&md, mac);
+	return 0;
 }
 
 
@@ -145,8 +146,6 @@ void aes_decrypt_deinit(void *ctx)
 }
 
 
-#ifdef CONFIG_TLS_INTERNAL
-
 struct crypto_hash {
 	enum crypto_hash_alg alg;
 	int error;
@@ -451,7 +450,8 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
 
 
 struct crypto_private_key * crypto_private_key_import(const u8 *key,
-						      size_t len)
+						      size_t len,
+						      const char *passwd)
 {
 	int res;
 	struct crypto_private_key *pk;
@@ -697,7 +697,7 @@ void crypto_global_deinit(void)
 }
 
 
-#ifdef EAP_FAST
+#ifdef CONFIG_MODEXP
 
 int crypto_mod_exp(const u8 *base, size_t base_len,
 		   const u8 *power, size_t power_len,
@@ -729,8 +729,4 @@ int crypto_mod_exp(const u8 *base, size_t base_len,
 	return -1;
 }
 
-#endif /* EAP_FAST */
-
-#endif /* CONFIG_TLS_INTERNAL */
-
-#endif /* EAP_TLS_FUNCS */
+#endif /* CONFIG_MODEXP */
diff --git a/contrib/wpa/src/crypto/crypto_none.c b/contrib/wpa/src/crypto/crypto_none.c
index f18c2a8ded95..9f43775a6462 100644
--- a/contrib/wpa/src/crypto/crypto_none.c
+++ b/contrib/wpa/src/crypto/crypto_none.c
@@ -18,8 +18,9 @@
 #include "crypto.h"
 
 
-void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
+	return 0;
 }
 
 
diff --git a/contrib/wpa/src/crypto/crypto_nss.c b/contrib/wpa/src/crypto/crypto_nss.c
new file mode 100644
index 000000000000..fee4195ca4e3
--- /dev/null
+++ b/contrib/wpa/src/crypto/crypto_nss.c
@@ -0,0 +1,213 @@
+/*
+ * Crypto wrapper functions for NSS
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "common.h"
+#include "crypto.h"
+
+
+static int nss_hash(HASH_HashType type, unsigned int max_res_len,
+		    size_t num_elem, const u8 *addr[], const size_t *len,
+		    u8 *mac)
+{
+	HASHContext *ctx;
+	size_t i;
+	unsigned int reslen;
+
+	ctx = HASH_Create(type);
+	if (ctx == NULL)
+		return -1;
+
+	HASH_Begin(ctx);
+	for (i = 0; i < num_elem; i++)
+		HASH_Update(ctx, addr[i], len[i]);
+	HASH_End(ctx, mac, &reslen, max_res_len);
+	HASH_Destroy(ctx);
+
+	return 0;
+}
+
+
+void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
+{
+	PK11Context *ctx = NULL;
+	PK11SlotInfo *slot;
+	SECItem *param = NULL;
+	PK11SymKey *symkey = NULL;
+	SECItem item;
+	int olen;
+	u8 pkey[8], next, tmp;
+	int i;
+
+	/* Add parity bits to the key */
+	next = 0;
+	for (i = 0; i < 7; i++) {
+		tmp = key[i];
+		pkey[i] = (tmp >> i) | next | 1;
+		next = tmp << (7 - i);
+	}
+	pkey[i] = next | 1;
+
+	slot = PK11_GetBestSlot(CKM_DES_ECB, NULL);
+	if (slot == NULL) {
+		wpa_printf(MSG_ERROR, "NSS: PK11_GetBestSlot failed");
+		goto out;
+	}
+
+	item.type = siBuffer;
+	item.data = pkey;
+	item.len = 8;
+	symkey = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginDerive,
+				   CKA_ENCRYPT, &item, NULL);
+	if (symkey == NULL) {
+		wpa_printf(MSG_ERROR, "NSS: PK11_ImportSymKey failed");
+		goto out;
+	}
+
+	param = PK11_GenerateNewParam(CKM_DES_ECB, symkey);
+	if (param == NULL) {
+		wpa_printf(MSG_ERROR, "NSS: PK11_GenerateNewParam failed");
+		goto out;
+	}
+
+	ctx = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT,
+					 symkey, param);
+	if (ctx == NULL) {
+		wpa_printf(MSG_ERROR, "NSS: PK11_CreateContextBySymKey("
+			   "CKM_DES_ECB) failed");
+		goto out;
+	}
+
+	if (PK11_CipherOp(ctx, cypher, &olen, 8, (void *) clear, 8) !=
+	    SECSuccess) {
+		wpa_printf(MSG_ERROR, "NSS: PK11_CipherOp failed");
+		goto out;
+	}
+
+out:
+	if (ctx)
+		PK11_DestroyContext(ctx, PR_TRUE);
+	if (symkey)
+		PK11_FreeSymKey(symkey);
+	if (param)
+		SECITEM_FreeItem(param, PR_TRUE);
+}
+
+
+int rc4_skip(const u8 *key, size_t keylen, size_t skip,
+	     u8 *data, size_t data_len)
+{
+	return -1;
+}
+
+
+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+	return nss_hash(HASH_AlgMD5, 16, num_elem, addr, len, mac);
+}
+
+
+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+	return nss_hash(HASH_AlgSHA1, 20, num_elem, addr, len, mac);
+}
+
+
+int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+		  u8 *mac)
+{
+	return nss_hash(HASH_AlgSHA256, 32, num_elem, addr, len, mac);
+}
+
+
+void * aes_encrypt_init(const u8 *key, size_t len)
+{
+	return NULL;
+}
+
+
+void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
+{
+}
+
+
+void aes_encrypt_deinit(void *ctx)
+{
+}
+
+
+void * aes_decrypt_init(const u8 *key, size_t len)
+{
+	return NULL;
+}
+
+
+void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
+{
+}
+
+
+void aes_decrypt_deinit(void *ctx)
+{
+}
+
+
+int crypto_mod_exp(const u8 *base, size_t base_len,
+		   const u8 *power, size_t power_len,
+		   const u8 *modulus, size_t modulus_len,
+		   u8 *result, size_t *result_len)
+{
+	return -1;
+}
+
+
+struct crypto_cipher {
+};
+
+
+struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
+					  const u8 *iv, const u8 *key,
+					  size_t key_len)
+{
+	return NULL;
+}
+
+
+int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
+			  u8 *crypt, size_t len)
+{
+	return -1;
+}
+
+
+int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
+			  u8 *plain, size_t len)
+{
+	return -1;
+}
+
+
+void crypto_cipher_deinit(struct crypto_cipher *ctx)
+{
+}
diff --git a/contrib/wpa/src/crypto/crypto_openssl.c b/contrib/wpa/src/crypto/crypto_openssl.c
index a4c3415c4d18..08c98aff4ba1 100644
--- a/contrib/wpa/src/crypto/crypto_openssl.c
+++ b/contrib/wpa/src/crypto/crypto_openssl.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / wrapper functions for libcrypto
- * Copyright (c) 2004-2005, Jouni Malinen 
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -14,15 +14,16 @@
 
 #include "includes.h"
 #include 
-#include 
-#include 
-#include 
+#include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include "common.h"
+#include "wpabuf.h"
+#include "dh_group5.h"
 #include "crypto.h"
 
 #if OPENSSL_VERSION_NUMBER < 0x00907000
@@ -33,16 +34,87 @@
 	des_ecb_encrypt((input), (output), *(ks), (enc))
 #endif /* openssl < 0.9.7 */
 
-
-void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+static BIGNUM * get_group5_prime(void)
 {
-	MD4_CTX ctx;
-	size_t i;
+#if OPENSSL_VERSION_NUMBER < 0x00908000
+	static const unsigned char RFC3526_PRIME_1536[] = {
+		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
+		0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
+		0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6,
+		0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
+		0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,
+		0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,
+		0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9,
+		0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
+		0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,
+		0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,
+		0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36,
+		0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
+		0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,
+		0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,
+		0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08,
+		0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	};
+        return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL);
+#else /* openssl < 0.9.8 */
+	return get_rfc3526_prime_1536(NULL);
+#endif /* openssl < 0.9.8 */
+}
 
-	MD4_Init(&ctx);
-	for (i = 0; i < num_elem; i++)
-		MD4_Update(&ctx, addr[i], len[i]);
-	MD4_Final(mac, &ctx);
+#if OPENSSL_VERSION_NUMBER < 0x00908000
+#ifndef OPENSSL_NO_SHA256
+#ifndef OPENSSL_FIPS
+#define NO_SHA256_WRAPPER
+#endif
+#endif
+
+#endif /* openssl < 0.9.8 */
+
+#ifdef OPENSSL_NO_SHA256
+#define NO_SHA256_WRAPPER
+#endif
+
+static int openssl_digest_vector(const EVP_MD *type, int non_fips,
+				 size_t num_elem, const u8 *addr[],
+				 const size_t *len, u8 *mac)
+{
+	EVP_MD_CTX ctx;
+	size_t i;
+	unsigned int mac_len;
+
+	EVP_MD_CTX_init(&ctx);
+#ifdef CONFIG_FIPS
+#ifdef OPENSSL_FIPS
+	if (non_fips)
+		EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+#endif /* OPENSSL_FIPS */
+#endif /* CONFIG_FIPS */
+	if (!EVP_DigestInit_ex(&ctx, type, NULL)) {
+		wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s",
+			   ERR_error_string(ERR_get_error(), NULL));
+		return -1;
+	}
+	for (i = 0; i < num_elem; i++) {
+		if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) {
+			wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate "
+				   "failed: %s",
+				   ERR_error_string(ERR_get_error(), NULL));
+			return -1;
+		}
+	}
+	if (!EVP_DigestFinal(&ctx, mac, &mac_len)) {
+		wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s",
+			   ERR_error_string(ERR_get_error(), NULL));
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+	return openssl_digest_vector(EVP_md4(), 0, num_elem, addr, len, mac);
 }
 
 
@@ -67,94 +139,72 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
 }
 
 
-void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int rc4_skip(const u8 *key, size_t keylen, size_t skip,
+	     u8 *data, size_t data_len)
 {
-	MD5_CTX ctx;
-	size_t i;
+#ifdef OPENSSL_NO_RC4
+	return -1;
+#else /* OPENSSL_NO_RC4 */
+	EVP_CIPHER_CTX ctx;
+	int outl;
+	int res = -1;
+	unsigned char skip_buf[16];
 
-	MD5_Init(&ctx);
-	for (i = 0; i < num_elem; i++)
-		MD5_Update(&ctx, addr[i], len[i]);
-	MD5_Final(mac, &ctx);
-}
+	EVP_CIPHER_CTX_init(&ctx);
+	if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) ||
+	    !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
+	    !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) ||
+	    !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1))
+		goto out;
 
-
-void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
-{
-	SHA_CTX ctx;
-	size_t i;
-
-	SHA1_Init(&ctx);
-	for (i = 0; i < num_elem; i++)
-		SHA1_Update(&ctx, addr[i], len[i]);
-	SHA1_Final(mac, &ctx);
-}
-
-
-#ifndef CONFIG_NO_FIPS186_2_PRF
-static void sha1_transform(u8 *state, const u8 data[64])
-{
-	SHA_CTX context;
-	os_memset(&context, 0, sizeof(context));
-	os_memcpy(&context.h0, state, 5 * 4);
-	SHA1_Transform(&context, data);
-	os_memcpy(state, &context.h0, 5 * 4);
-}
-
-
-int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
-{
-	u8 xkey[64];
-	u32 t[5], _t[5];
-	int i, j, m, k;
-	u8 *xpos = x;
-	u32 carry;
-
-	if (seed_len > sizeof(xkey))
-		seed_len = sizeof(xkey);
-
-	/* FIPS 186-2 + change notice 1 */
-
-	os_memcpy(xkey, seed, seed_len);
-	os_memset(xkey + seed_len, 0, 64 - seed_len);
-	t[0] = 0x67452301;
-	t[1] = 0xEFCDAB89;
-	t[2] = 0x98BADCFE;
-	t[3] = 0x10325476;
-	t[4] = 0xC3D2E1F0;
-
-	m = xlen / 40;
-	for (j = 0; j < m; j++) {
-		/* XSEED_j = 0 */
-		for (i = 0; i < 2; i++) {
-			/* XVAL = (XKEY + XSEED_j) mod 2^b */
-
-			/* w_i = G(t, XVAL) */
-			os_memcpy(_t, t, 20);
-			sha1_transform((u8 *) _t, xkey);
-			_t[0] = host_to_be32(_t[0]);
-			_t[1] = host_to_be32(_t[1]);
-			_t[2] = host_to_be32(_t[2]);
-			_t[3] = host_to_be32(_t[3]);
-			_t[4] = host_to_be32(_t[4]);
-			os_memcpy(xpos, _t, 20);
-
-			/* XKEY = (1 + XKEY + w_i) mod 2^b */
-			carry = 1;
-			for (k = 19; k >= 0; k--) {
-				carry += xkey[k] + xpos[k];
-				xkey[k] = carry & 0xff;
-				carry >>= 8;
-			}
-
-			xpos += 20;
-		}
-		/* x_j = w_0|w_1 */
+	while (skip >= sizeof(skip_buf)) {
+		size_t len = skip;
+		if (len > sizeof(skip_buf))
+			len = sizeof(skip_buf);
+		if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len))
+			goto out;
+		skip -= len;
 	}
 
-	return 0;
+	if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len))
+		res = 0;
+
+out:
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return res;
+#endif /* OPENSSL_NO_RC4 */
 }
-#endif /* CONFIG_NO_FIPS186_2_PRF */
+
+
+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+	return openssl_digest_vector(EVP_md5(), 0, num_elem, addr, len, mac);
+}
+
+
+#ifdef CONFIG_FIPS
+int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[],
+			      const size_t *len, u8 *mac)
+{
+	return openssl_digest_vector(EVP_md5(), 1, num_elem, addr, len, mac);
+}
+#endif /* CONFIG_FIPS */
+
+
+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+	return openssl_digest_vector(EVP_sha1(), 0, num_elem, addr, len, mac);
+}
+
+
+#ifndef NO_SHA256_WRAPPER
+int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+		  u8 *mac)
+{
+	return openssl_digest_vector(EVP_sha256(), 0, num_elem, addr, len,
+				     mac);
+}
+#endif /* NO_SHA256_WRAPPER */
 
 
 void * aes_encrypt_init(const u8 *key, size_t len)
@@ -310,7 +360,7 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
 	EVP_CIPHER_CTX_set_padding(&ctx->enc, 0);
 	if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) ||
 	    !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) ||
-	    !EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, key, iv)) {
+	    !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) {
 		EVP_CIPHER_CTX_cleanup(&ctx->enc);
 		os_free(ctx);
 		return NULL;
@@ -320,7 +370,7 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
 	EVP_CIPHER_CTX_set_padding(&ctx->dec, 0);
 	if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) ||
 	    !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) ||
-	    !EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, key, iv)) {
+	    !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) {
 		EVP_CIPHER_CTX_cleanup(&ctx->enc);
 		EVP_CIPHER_CTX_cleanup(&ctx->dec);
 		os_free(ctx);
@@ -358,3 +408,98 @@ void crypto_cipher_deinit(struct crypto_cipher *ctx)
 	EVP_CIPHER_CTX_cleanup(&ctx->dec);
 	os_free(ctx);
 }
+
+
+void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
+{
+	DH *dh;
+	struct wpabuf *pubkey = NULL, *privkey = NULL;
+	size_t publen, privlen;
+
+	*priv = NULL;
+	*publ = NULL;
+
+	dh = DH_new();
+	if (dh == NULL)
+		return NULL;
+
+	dh->g = BN_new();
+	if (dh->g == NULL || BN_set_word(dh->g, 2) != 1)
+		goto err;
+
+	dh->p = get_group5_prime();
+	if (dh->p == NULL)
+		goto err;
+
+	if (DH_generate_key(dh) != 1)
+		goto err;
+
+	publen = BN_num_bytes(dh->pub_key);
+	pubkey = wpabuf_alloc(publen);
+	if (pubkey == NULL)
+		goto err;
+	privlen = BN_num_bytes(dh->priv_key);
+	privkey = wpabuf_alloc(privlen);
+	if (privkey == NULL)
+		goto err;
+
+	BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen));
+	BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen));
+
+	*priv = privkey;
+	*publ = pubkey;
+	return dh;
+
+err:
+	wpabuf_free(pubkey);
+	wpabuf_free(privkey);
+	DH_free(dh);
+	return NULL;
+}
+
+
+struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
+				  const struct wpabuf *own_private)
+{
+	BIGNUM *pub_key;
+	struct wpabuf *res = NULL;
+	size_t rlen;
+	DH *dh = ctx;
+	int keylen;
+
+	if (ctx == NULL)
+		return NULL;
+
+	pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public),
+			    NULL);
+	if (pub_key == NULL)
+		return NULL;
+
+	rlen = DH_size(dh);
+	res = wpabuf_alloc(rlen);
+	if (res == NULL)
+		goto err;
+
+	keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh);
+	if (keylen < 0)
+		goto err;
+	wpabuf_put(res, keylen);
+	BN_free(pub_key);
+
+	return res;
+
+err:
+	BN_free(pub_key);
+	wpabuf_free(res);
+	return NULL;
+}
+
+
+void dh5_free(void *ctx)
+{
+	DH *dh;
+	if (ctx == NULL)
+		return;
+	dh = ctx;
+	DH_free(dh);
+}
diff --git a/contrib/wpa/src/crypto/des.c b/contrib/wpa/src/crypto/des-internal.c
similarity index 95%
rename from contrib/wpa/src/crypto/des.c
rename to contrib/wpa/src/crypto/des-internal.c
index 103e592461a7..ccea9503216e 100644
--- a/contrib/wpa/src/crypto/des.c
+++ b/contrib/wpa/src/crypto/des-internal.c
@@ -2,7 +2,7 @@
  * DES and 3DES-EDE ciphers
  *
  * Modifications to LibTomCrypt implementation:
- * Copyright (c) 2006, Jouni Malinen 
+ * Copyright (c) 2006-2009, Jouni Malinen 
  *
  * 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
@@ -18,9 +18,7 @@
 
 #include "common.h"
 #include "crypto.h"
-
-
-#ifdef INTERNAL_DES
+#include "des_i.h"
 
 /*
  * This implementation is based on a DES implementation included in
@@ -432,10 +430,34 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
 }
 
 
-struct des3_key_s {
-	u32 ek[3][32];
-	u32 dk[3][32];
-};
+void des_key_setup(const u8 *key, u32 *ek, u32 *dk)
+{
+	deskey(key, 0, ek);
+	deskey(key, 1, dk);
+}
+
+
+void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt)
+{
+	u32 work[2];
+	work[0] = WPA_GET_BE32(plain);
+	work[1] = WPA_GET_BE32(plain + 4);
+	desfunc(work, ek);
+	WPA_PUT_BE32(crypt, work[0]);
+	WPA_PUT_BE32(crypt + 4, work[1]);
+}
+
+
+void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain)
+{
+	u32 work[2];
+	work[0] = WPA_GET_BE32(crypt);
+	work[1] = WPA_GET_BE32(crypt + 4);
+	desfunc(work, dk);
+	WPA_PUT_BE32(plain, work[0]);
+	WPA_PUT_BE32(plain + 4, work[1]);
+}
+
 
 void des3_key_setup(const u8 *key, struct des3_key_s *dkey)
 {
@@ -475,5 +497,3 @@ void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain)
 	WPA_PUT_BE32(plain, work[0]);
 	WPA_PUT_BE32(plain + 4, work[1]);
 }
-
-#endif /* INTERNAL_DES */
diff --git a/contrib/wpa/src/crypto/des_i.h b/contrib/wpa/src/crypto/des_i.h
new file mode 100644
index 000000000000..6f274144a0e6
--- /dev/null
+++ b/contrib/wpa/src/crypto/des_i.h
@@ -0,0 +1,31 @@
+/*
+ * DES and 3DES-EDE ciphers
+ * Copyright (c) 2006-2009, Jouni Malinen 
+ *
+ * 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 DES_I_H
+#define DES_I_H
+
+struct des3_key_s {
+	u32 ek[3][32];
+	u32 dk[3][32];
+};
+
+void des_key_setup(const u8 *key, u32 *ek, u32 *dk);
+void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt);
+void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain);
+
+void des3_key_setup(const u8 *key, struct des3_key_s *dkey);
+void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt);
+void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain);
+
+#endif /* DES_I_H */
diff --git a/contrib/wpa/src/crypto/dh_group5.c b/contrib/wpa/src/crypto/dh_group5.c
new file mode 100644
index 000000000000..8c475bf94ae9
--- /dev/null
+++ b/contrib/wpa/src/crypto/dh_group5.c
@@ -0,0 +1,40 @@
+/*
+ * Diffie-Hellman group 5 operations
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 "dh_groups.h"
+#include "dh_group5.h"
+
+
+void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
+{
+	*publ = dh_init(dh_groups_get(5), priv);
+	if (*publ == 0)
+		return NULL;
+	return (void *) 1;
+}
+
+
+struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
+				  const struct wpabuf *own_private)
+{
+	return dh_derive_shared(peer_public, own_private, dh_groups_get(5));
+}
+
+
+void dh5_free(void *ctx)
+{
+}
diff --git a/contrib/wpa/src/crypto/dh_group5.h b/contrib/wpa/src/crypto/dh_group5.h
new file mode 100644
index 000000000000..595f1114fe2b
--- /dev/null
+++ b/contrib/wpa/src/crypto/dh_group5.h
@@ -0,0 +1,23 @@
+/*
+ * Diffie-Hellman group 5 operations
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 DH_GROUP5_H
+#define DH_GROUP5_H
+
+void * dh5_init(struct wpabuf **priv, struct wpabuf **publ);
+struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
+				  const struct wpabuf *own_private);
+void dh5_free(void *ctx);
+
+#endif /* DH_GROUP5_H */
diff --git a/contrib/wpa/src/crypto/dh_groups.c b/contrib/wpa/src/crypto/dh_groups.c
index 5f6008a6e2a2..7bd2fb7b4e21 100644
--- a/contrib/wpa/src/crypto/dh_groups.c
+++ b/contrib/wpa/src/crypto/dh_groups.c
@@ -619,11 +619,12 @@ struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public,
 	if (crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public),
 			   wpabuf_head(own_private), wpabuf_len(own_private),
 			   dh->prime, dh->prime_len,
-			   wpabuf_put(shared, shared_len), &shared_len) < 0) {
+			   wpabuf_mhead(shared), &shared_len) < 0) {
 		wpabuf_free(shared);
 		wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
 		return NULL;
 	}
+	wpabuf_put(shared, shared_len);
 	wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared);
 
 	return shared;
diff --git a/contrib/wpa/src/crypto/fips_prf_cryptoapi.c b/contrib/wpa/src/crypto/fips_prf_cryptoapi.c
new file mode 100644
index 000000000000..17d3116e8b57
--- /dev/null
+++ b/contrib/wpa/src/crypto/fips_prf_cryptoapi.c
@@ -0,0 +1,25 @@
+/*
+ * FIPS 186-2 PRF for Microsoft CryptoAPI
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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.h"
+
+
+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
+{
+	/* FIX: how to do this with CryptoAPI? */
+	return -1;
+}
diff --git a/contrib/wpa/src/crypto/fips_prf_gnutls.c b/contrib/wpa/src/crypto/fips_prf_gnutls.c
new file mode 100644
index 000000000000..f742e98589f2
--- /dev/null
+++ b/contrib/wpa/src/crypto/fips_prf_gnutls.c
@@ -0,0 +1,26 @@
+/*
+ * FIPS 186-2 PRF for libgcrypt
+ * Copyright (c) 2004-2009, Jouni Malinen 
+ *
+ * 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 
+
+#include "common.h"
+#include "crypto.h"
+
+
+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
+{
+	/* FIX: how to do this with libgcrypt? */
+	return -1;
+}
diff --git a/contrib/wpa/src/crypto/fips_prf_internal.c b/contrib/wpa/src/crypto/fips_prf_internal.c
new file mode 100644
index 000000000000..a85cb14d7424
--- /dev/null
+++ b/contrib/wpa/src/crypto/fips_prf_internal.c
@@ -0,0 +1,74 @@
+/*
+ * FIPS 186-2 PRF for internal crypto implementation
+ * Copyright (c) 2006-2007, Jouni Malinen 
+ *
+ * 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 "sha1.h"
+#include "sha1_i.h"
+#include "crypto.h"
+
+
+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
+{
+	u8 xkey[64];
+	u32 t[5], _t[5];
+	int i, j, m, k;
+	u8 *xpos = x;
+	u32 carry;
+
+	if (seed_len > sizeof(xkey))
+		seed_len = sizeof(xkey);
+
+	/* FIPS 186-2 + change notice 1 */
+
+	os_memcpy(xkey, seed, seed_len);
+	os_memset(xkey + seed_len, 0, 64 - seed_len);
+	t[0] = 0x67452301;
+	t[1] = 0xEFCDAB89;
+	t[2] = 0x98BADCFE;
+	t[3] = 0x10325476;
+	t[4] = 0xC3D2E1F0;
+
+	m = xlen / 40;
+	for (j = 0; j < m; j++) {
+		/* XSEED_j = 0 */
+		for (i = 0; i < 2; i++) {
+			/* XVAL = (XKEY + XSEED_j) mod 2^b */
+
+			/* w_i = G(t, XVAL) */
+			os_memcpy(_t, t, 20);
+			SHA1Transform(_t, xkey);
+			_t[0] = host_to_be32(_t[0]);
+			_t[1] = host_to_be32(_t[1]);
+			_t[2] = host_to_be32(_t[2]);
+			_t[3] = host_to_be32(_t[3]);
+			_t[4] = host_to_be32(_t[4]);
+			os_memcpy(xpos, _t, 20);
+
+			/* XKEY = (1 + XKEY + w_i) mod 2^b */
+			carry = 1;
+			for (k = 19; k >= 0; k--) {
+				carry += xkey[k] + xpos[k];
+				xkey[k] = carry & 0xff;
+				carry >>= 8;
+			}
+
+			xpos += SHA1_MAC_LEN;
+		}
+		/* x_j = w_0|w_1 */
+	}
+
+	return 0;
+}
diff --git a/contrib/wpa/src/crypto/fips_prf_nss.c b/contrib/wpa/src/crypto/fips_prf_nss.c
new file mode 100644
index 000000000000..f941983c43c3
--- /dev/null
+++ b/contrib/wpa/src/crypto/fips_prf_nss.c
@@ -0,0 +1,25 @@
+/*
+ * FIPS 186-2 PRF for NSS
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 
+
+#include "common.h"
+#include "crypto.h"
+
+
+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
+{
+	return -1;
+}
diff --git a/contrib/wpa/src/crypto/fips_prf_openssl.c b/contrib/wpa/src/crypto/fips_prf_openssl.c
new file mode 100644
index 000000000000..d0af98355f65
--- /dev/null
+++ b/contrib/wpa/src/crypto/fips_prf_openssl.c
@@ -0,0 +1,83 @@
+/*
+ * FIPS 186-2 PRF for libcrypto
+ * Copyright (c) 2004-2005, Jouni Malinen 
+ *
+ * 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 
+
+#include "common.h"
+#include "crypto.h"
+
+
+static void sha1_transform(u8 *state, const u8 data[64])
+{
+	SHA_CTX context;
+	os_memset(&context, 0, sizeof(context));
+	os_memcpy(&context.h0, state, 5 * 4);
+	SHA1_Transform(&context, data);
+	os_memcpy(state, &context.h0, 5 * 4);
+}
+
+
+int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
+{
+	u8 xkey[64];
+	u32 t[5], _t[5];
+	int i, j, m, k;
+	u8 *xpos = x;
+	u32 carry;
+
+	if (seed_len > sizeof(xkey))
+		seed_len = sizeof(xkey);
+
+	/* FIPS 186-2 + change notice 1 */
+
+	os_memcpy(xkey, seed, seed_len);
+	os_memset(xkey + seed_len, 0, 64 - seed_len);
+	t[0] = 0x67452301;
+	t[1] = 0xEFCDAB89;
+	t[2] = 0x98BADCFE;
+	t[3] = 0x10325476;
+	t[4] = 0xC3D2E1F0;
+
+	m = xlen / 40;
+	for (j = 0; j < m; j++) {
+		/* XSEED_j = 0 */
+		for (i = 0; i < 2; i++) {
+			/* XVAL = (XKEY + XSEED_j) mod 2^b */
+
+			/* w_i = G(t, XVAL) */
+			os_memcpy(_t, t, 20);
+			sha1_transform((u8 *) _t, xkey);
+			_t[0] = host_to_be32(_t[0]);
+			_t[1] = host_to_be32(_t[1]);
+			_t[2] = host_to_be32(_t[2]);
+			_t[3] = host_to_be32(_t[3]);
+			_t[4] = host_to_be32(_t[4]);
+			os_memcpy(xpos, _t, 20);
+
+			/* XKEY = (1 + XKEY + w_i) mod 2^b */
+			carry = 1;
+			for (k = 19; k >= 0; k--) {
+				carry += xkey[k] + xpos[k];
+				xkey[k] = carry & 0xff;
+				carry >>= 8;
+			}
+
+			xpos += 20;
+		}
+		/* x_j = w_0|w_1 */
+	}
+
+	return 0;
+}
diff --git a/contrib/wpa/src/crypto/md4.c b/contrib/wpa/src/crypto/md4-internal.c
similarity index 98%
rename from contrib/wpa/src/crypto/md4.c
rename to contrib/wpa/src/crypto/md4-internal.c
index 41c84a3a7b5d..d9f499f1d07b 100644
--- a/contrib/wpa/src/crypto/md4.c
+++ b/contrib/wpa/src/crypto/md4-internal.c
@@ -17,9 +17,6 @@
 #include "common.h"
 #include "crypto.h"
 
-
-#ifdef INTERNAL_MD4
-
 #define	MD4_BLOCK_LENGTH		64
 #define	MD4_DIGEST_LENGTH		16
 
@@ -35,7 +32,7 @@ static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len);
 static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx);
 
 
-void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 {
 	MD4_CTX ctx;
 	size_t i;
@@ -44,6 +41,7 @@ void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
 	for (i = 0; i < num_elem; i++)
 		MD4Update(&ctx, addr[i], len[i]);
 	MD4Final(mac, &ctx);
+	return 0;
 }
 
 
@@ -278,5 +276,3 @@ MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH])
 	state[3] += d;
 }
 /* ===== end - public domain MD4 implementation ===== */
-
-#endif /* INTERNAL_MD4 */
diff --git a/contrib/wpa/src/crypto/md5-internal.c b/contrib/wpa/src/crypto/md5-internal.c
new file mode 100644
index 000000000000..f8692a9557ae
--- /dev/null
+++ b/contrib/wpa/src/crypto/md5-internal.c
@@ -0,0 +1,293 @@
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen 
+ *
+ * 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 "md5.h"
+#include "md5_i.h"
+#include "crypto.h"
+
+
+static void MD5Transform(u32 buf[4], u32 const in[16]);
+
+
+typedef struct MD5Context MD5_CTX;
+
+
+/**
+ * md5_vector - MD5 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 of failure
+ */
+int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+	MD5_CTX ctx;
+	size_t i;
+
+	MD5Init(&ctx);
+	for (i = 0; i < num_elem; i++)
+		MD5Update(&ctx, addr[i], len[i]);
+	MD5Final(mac, &ctx);
+	return 0;
+}
+
+
+/* ===== start - public domain MD5 implementation ===== */
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#ifndef WORDS_BIGENDIAN
+#define byteReverse(buf, len)	/* Nothing */
+#else
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse(unsigned char *buf, unsigned longs)
+{
+    u32 t;
+    do {
+	t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+	    ((unsigned) buf[1] << 8 | buf[0]);
+	*(u32 *) buf = t;
+	buf += 4;
+    } while (--longs);
+}
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->bits[0] = 0;
+    ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+    u32 t;
+
+    /* Update bitcount */
+
+    t = ctx->bits[0];
+    if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
+	ctx->bits[1]++;		/* Carry from low to high */
+    ctx->bits[1] += len >> 29;
+
+    t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+
+    /* Handle any leading odd-sized chunks */
+
+    if (t) {
+	unsigned char *p = (unsigned char *) ctx->in + t;
+
+	t = 64 - t;
+	if (len < t) {
+	    os_memcpy(p, buf, len);
+	    return;
+	}
+	os_memcpy(p, buf, t);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+	buf += t;
+	len -= t;
+    }
+    /* Process data in 64-byte chunks */
+
+    while (len >= 64) {
+	os_memcpy(ctx->in, buf, 64);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+	buf += 64;
+	len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+
+    os_memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+    unsigned count;
+    unsigned char *p;
+
+    /* Compute number of bytes mod 64 */
+    count = (ctx->bits[0] >> 3) & 0x3F;
+
+    /* Set the first char of padding to 0x80.  This is safe since there is
+       always at least one byte free */
+    p = ctx->in + count;
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 64 bytes */
+    count = 64 - 1 - count;
+
+    /* Pad out to 56 mod 64 */
+    if (count < 8) {
+	/* Two lots of padding:  Pad the first block to 64 bytes */
+	os_memset(p, 0, count);
+	byteReverse(ctx->in, 16);
+	MD5Transform(ctx->buf, (u32 *) ctx->in);
+
+	/* Now fill the next block with 56 bytes */
+	os_memset(ctx->in, 0, 56);
+    } else {
+	/* Pad block to 56 bytes */
+	os_memset(p, 0, count - 8);
+    }
+    byteReverse(ctx->in, 14);
+
+    /* Append length in bits and transform */
+    ((u32 *) ctx->in)[14] = ctx->bits[0];
+    ((u32 *) ctx->in)[15] = ctx->bits[1];
+
+    MD5Transform(ctx->buf, (u32 *) ctx->in);
+    byteReverse((unsigned char *) ctx->buf, 4);
+    os_memcpy(digest, ctx->buf, 16);
+    os_memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data,  w = w<>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void MD5Transform(u32 buf[4], u32 const in[16])
+{
+    register u32 a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
+/* ===== end - public domain MD5 implementation ===== */
diff --git a/contrib/wpa/src/crypto/md5-non-fips.c b/contrib/wpa/src/crypto/md5-non-fips.c
new file mode 100644
index 000000000000..6f2920145a1e
--- /dev/null
+++ b/contrib/wpa/src/crypto/md5-non-fips.c
@@ -0,0 +1,113 @@
+/*
+ * MD5 hash implementation and interface functions (non-FIPS allowed cases)
+ * Copyright (c) 2003-2009, Jouni Malinen 
+ *
+ * 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 "md5.h"
+#include "crypto.h"
+
+
+/**
+ * hmac_md5_vector_non_fips_allow - HMAC-MD5 over data vector (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len,
+				   size_t num_elem, const u8 *addr[],
+				   const size_t *len, u8 *mac)
+{
+	u8 k_pad[64]; /* padding - key XORd with ipad/opad */
+	u8 tk[16];
+	const u8 *_addr[6];
+	size_t i, _len[6];
+
+	if (num_elem > 5) {
+		/*
+		 * Fixed limit on the number of fragments to avoid having to
+		 * allocate memory (which could fail).
+		 */
+		return -1;
+	}
+
+        /* if key is longer than 64 bytes reset it to key = MD5(key) */
+        if (key_len > 64) {
+		if (md5_vector_non_fips_allow(1, &key, &key_len, tk))
+			return -1;
+		key = tk;
+		key_len = 16;
+        }
+
+	/* the HMAC_MD5 transform looks like:
+	 *
+	 * MD5(K XOR opad, MD5(K XOR ipad, text))
+	 *
+	 * where K is an n byte key
+	 * ipad is the byte 0x36 repeated 64 times
+	 * opad is the byte 0x5c repeated 64 times
+	 * and text is the data being protected */
+
+	/* start out by storing key in ipad */
+	os_memset(k_pad, 0, sizeof(k_pad));
+	os_memcpy(k_pad, key, key_len);
+
+	/* XOR key with ipad values */
+	for (i = 0; i < 64; i++)
+		k_pad[i] ^= 0x36;
+
+	/* perform inner MD5 */
+	_addr[0] = k_pad;
+	_len[0] = 64;
+	for (i = 0; i < num_elem; i++) {
+		_addr[i + 1] = addr[i];
+		_len[i + 1] = len[i];
+	}
+	if (md5_vector_non_fips_allow(1 + num_elem, _addr, _len, mac))
+		return -1;
+
+	os_memset(k_pad, 0, sizeof(k_pad));
+	os_memcpy(k_pad, key, key_len);
+	/* XOR key with opad values */
+	for (i = 0; i < 64; i++)
+		k_pad[i] ^= 0x5c;
+
+	/* perform outer MD5 */
+	_addr[0] = k_pad;
+	_len[0] = 64;
+	_addr[1] = mac;
+	_len[1] = MD5_MAC_LEN;
+	return md5_vector_non_fips_allow(2, _addr, _len, mac);
+}
+
+
+/**
+ * hmac_md5_non_fips_allow - HMAC-MD5 over data buffer (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @data: Pointers to the data area
+ * @data_len: Length of the data area
+ * @mac: Buffer for the hash (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data,
+			    size_t data_len, u8 *mac)
+{
+	return hmac_md5_vector_non_fips_allow(key, key_len, 1, &data,
+					      &data_len, mac);
+}
diff --git a/contrib/wpa/src/crypto/md5.c b/contrib/wpa/src/crypto/md5.c
index a7db7aa9a771..7f14e9b2ec16 100644
--- a/contrib/wpa/src/crypto/md5.c
+++ b/contrib/wpa/src/crypto/md5.c
@@ -27,9 +27,10 @@
  * @addr: Pointers to the data areas
  * @len: Lengths of the data blocks
  * @mac: Buffer for the hash (16 bytes)
+ * Returns: 0 on success, -1 on failure
  */
-void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
-		     const u8 *addr[], const size_t *len, u8 *mac)
+int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
+		    const u8 *addr[], const size_t *len, u8 *mac)
 {
 	u8 k_pad[64]; /* padding - key XORd with ipad/opad */
 	u8 tk[16];
@@ -41,12 +42,13 @@ void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
 		 * Fixed limit on the number of fragments to avoid having to
 		 * allocate memory (which could fail).
 		 */
-		return;
+		return -1;
 	}
 
         /* if key is longer than 64 bytes reset it to key = MD5(key) */
         if (key_len > 64) {
-		md5_vector(1, &key, &key_len, tk);
+		if (md5_vector(1, &key, &key_len, tk))
+			return -1;
 		key = tk;
 		key_len = 16;
         }
@@ -75,7 +77,8 @@ void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
 		_addr[i + 1] = addr[i];
 		_len[i + 1] = len[i];
 	}
-	md5_vector(1 + num_elem, _addr, _len, mac);
+	if (md5_vector(1 + num_elem, _addr, _len, mac))
+		return -1;
 
 	os_memset(k_pad, 0, sizeof(k_pad));
 	os_memcpy(k_pad, key, key_len);
@@ -88,7 +91,7 @@ void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
 	_len[0] = 64;
 	_addr[1] = mac;
 	_len[1] = MD5_MAC_LEN;
-	md5_vector(2, _addr, _len, mac);
+	return md5_vector(2, _addr, _len, mac);
 }
 
 
@@ -99,296 +102,10 @@ void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
  * @data: Pointers to the data area
  * @data_len: Length of the data area
  * @mac: Buffer for the hash (16 bytes)
+ * Returns: 0 on success, -1 on failure
  */
-void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
 	      u8 *mac)
 {
-	hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
+	return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
 }
-
-
-#ifdef INTERNAL_MD5
-
-struct MD5Context {
-	u32 buf[4];
-	u32 bits[2];
-	u8 in[64];
-};
-
-#ifndef CONFIG_CRYPTO_INTERNAL
-static void MD5Init(struct MD5Context *context);
-static void MD5Update(struct MD5Context *context, unsigned char const *buf,
-			  unsigned len);
-static void MD5Final(unsigned char digest[16], struct MD5Context *context);
-#endif /* CONFIG_CRYPTO_INTERNAL */
-static void MD5Transform(u32 buf[4], u32 const in[16]);
-
-
-typedef struct MD5Context MD5_CTX;
-
-
-/**
- * md5_vector - MD5 hash for data vector
- * @num_elem: Number of elements in the data vector
- * @addr: Pointers to the data areas
- * @len: Lengths of the data blocks
- * @mac: Buffer for the hash
- */
-void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
-{
-	MD5_CTX ctx;
-	size_t i;
-
-	MD5Init(&ctx);
-	for (i = 0; i < num_elem; i++)
-		MD5Update(&ctx, addr[i], len[i]);
-	MD5Final(mac, &ctx);
-}
-
-
-/* ===== start - public domain MD5 implementation ===== */
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest.  This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-#ifndef WORDS_BIGENDIAN
-#define byteReverse(buf, len)	/* Nothing */
-#else
-/*
- * Note: this code is harmless on little-endian machines.
- */
-static void byteReverse(unsigned char *buf, unsigned longs)
-{
-    u32 t;
-    do {
-	t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
-	    ((unsigned) buf[1] << 8 | buf[0]);
-	*(u32 *) buf = t;
-	buf += 4;
-    } while (--longs);
-}
-#endif
-
-/*
- * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-void MD5Init(struct MD5Context *ctx)
-{
-    ctx->buf[0] = 0x67452301;
-    ctx->buf[1] = 0xefcdab89;
-    ctx->buf[2] = 0x98badcfe;
-    ctx->buf[3] = 0x10325476;
-
-    ctx->bits[0] = 0;
-    ctx->bits[1] = 0;
-}
-
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
-{
-    u32 t;
-
-    /* Update bitcount */
-
-    t = ctx->bits[0];
-    if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
-	ctx->bits[1]++;		/* Carry from low to high */
-    ctx->bits[1] += len >> 29;
-
-    t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
-
-    /* Handle any leading odd-sized chunks */
-
-    if (t) {
-	unsigned char *p = (unsigned char *) ctx->in + t;
-
-	t = 64 - t;
-	if (len < t) {
-	    os_memcpy(p, buf, len);
-	    return;
-	}
-	os_memcpy(p, buf, t);
-	byteReverse(ctx->in, 16);
-	MD5Transform(ctx->buf, (u32 *) ctx->in);
-	buf += t;
-	len -= t;
-    }
-    /* Process data in 64-byte chunks */
-
-    while (len >= 64) {
-	os_memcpy(ctx->in, buf, 64);
-	byteReverse(ctx->in, 16);
-	MD5Transform(ctx->buf, (u32 *) ctx->in);
-	buf += 64;
-	len -= 64;
-    }
-
-    /* Handle any remaining bytes of data. */
-
-    os_memcpy(ctx->in, buf, len);
-}
-
-/*
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
-{
-    unsigned count;
-    unsigned char *p;
-
-    /* Compute number of bytes mod 64 */
-    count = (ctx->bits[0] >> 3) & 0x3F;
-
-    /* Set the first char of padding to 0x80.  This is safe since there is
-       always at least one byte free */
-    p = ctx->in + count;
-    *p++ = 0x80;
-
-    /* Bytes of padding needed to make 64 bytes */
-    count = 64 - 1 - count;
-
-    /* Pad out to 56 mod 64 */
-    if (count < 8) {
-	/* Two lots of padding:  Pad the first block to 64 bytes */
-	os_memset(p, 0, count);
-	byteReverse(ctx->in, 16);
-	MD5Transform(ctx->buf, (u32 *) ctx->in);
-
-	/* Now fill the next block with 56 bytes */
-	os_memset(ctx->in, 0, 56);
-    } else {
-	/* Pad block to 56 bytes */
-	os_memset(p, 0, count - 8);
-    }
-    byteReverse(ctx->in, 14);
-
-    /* Append length in bits and transform */
-    ((u32 *) ctx->in)[14] = ctx->bits[0];
-    ((u32 *) ctx->in)[15] = ctx->bits[1];
-
-    MD5Transform(ctx->buf, (u32 *) ctx->in);
-    byteReverse((unsigned char *) ctx->buf, 4);
-    os_memcpy(digest, ctx->buf, 16);
-    os_memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
-}
-
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
-	( w += f(x, y, z) + data,  w = w<>(32-s),  w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data.  MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void MD5Transform(u32 buf[4], u32 const in[16])
-{
-    register u32 a, b, c, d;
-
-    a = buf[0];
-    b = buf[1];
-    c = buf[2];
-    d = buf[3];
-
-    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
-    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
-    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
-    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
-    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
-    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
-    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
-    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
-    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
-    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
-    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
-    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
-    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
-    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
-    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
-    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
-    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
-    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
-    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
-    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
-    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
-    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
-    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
-    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
-    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
-    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
-    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
-    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
-    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
-    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
-    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
-    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
-    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
-    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
-    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
-    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
-    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
-    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
-    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
-    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
-    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
-    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
-    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
-    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
-    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
-    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
-    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
-    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
-    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
-    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
-    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
-    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
-    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
-    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
-    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
-    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
-    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
-    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
-    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
-    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
-    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
-    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
-    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
-    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
-    buf[0] += a;
-    buf[1] += b;
-    buf[2] += c;
-    buf[3] += d;
-}
-/* ===== end - public domain MD5 implementation ===== */
-
-#endif /* INTERNAL_MD5 */
diff --git a/contrib/wpa/src/crypto/md5.h b/contrib/wpa/src/crypto/md5.h
index e82f3969ed08..8952590782a3 100644
--- a/contrib/wpa/src/crypto/md5.h
+++ b/contrib/wpa/src/crypto/md5.h
@@ -1,6 +1,6 @@
 /*
  * MD5 hash implementation and interface functions
- * Copyright (c) 2003-2005, Jouni Malinen 
+ * Copyright (c) 2003-2009, Jouni Malinen 
  *
  * 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
@@ -17,18 +17,19 @@
 
 #define MD5_MAC_LEN 16
 
-void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
-		     const u8 *addr[], const size_t *len, u8 *mac);
-void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
-	      u8 *mac);
-
-#ifdef CONFIG_CRYPTO_INTERNAL
-struct MD5Context;
-
-void MD5Init(struct MD5Context *context);
-void MD5Update(struct MD5Context *context, unsigned char const *buf,
-	       unsigned len);
-void MD5Final(unsigned char digest[16], struct MD5Context *context);
-#endif /* CONFIG_CRYPTO_INTERNAL */
+int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
+		    const u8 *addr[], const size_t *len, u8 *mac);
+int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+	     u8 *mac);
+#ifdef CONFIG_FIPS
+int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len,
+				   size_t num_elem, const u8 *addr[],
+				   const size_t *len, u8 *mac);
+int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data,
+			    size_t data_len, u8 *mac);
+#else /* CONFIG_FIPS */
+#define hmac_md5_vector_non_fips_allow hmac_md5_vector
+#define hmac_md5_non_fips_allow hmac_md5
+#endif /* CONFIG_FIPS */
 
 #endif /* MD5_H */
diff --git a/contrib/wpa/src/crypto/md5_i.h b/contrib/wpa/src/crypto/md5_i.h
new file mode 100644
index 000000000000..b7f6596052a6
--- /dev/null
+++ b/contrib/wpa/src/crypto/md5_i.h
@@ -0,0 +1,29 @@
+/*
+ * MD5 internal definitions
+ * Copyright (c) 2003-2005, Jouni Malinen 
+ *
+ * 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 MD5_I_H
+#define MD5_I_H
+
+struct MD5Context {
+	u32 buf[4];
+	u32 bits[2];
+	u8 in[64];
+};
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, unsigned char const *buf,
+	       unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+
+#endif /* MD5_I_H */
diff --git a/contrib/wpa/src/crypto/milenage.c b/contrib/wpa/src/crypto/milenage.c
new file mode 100644
index 000000000000..cf0c60e5510f
--- /dev/null
+++ b/contrib/wpa/src/crypto/milenage.c
@@ -0,0 +1,329 @@
+/*
+ * 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
+ * Copyright (c) 2006-2007 
+ *
+ * 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 file implements an example authentication algorithm defined for 3GPP
+ * AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow
+ * EAP-AKA to be tested properly with real USIM cards.
+ *
+ * This implementations assumes that the r1..r5 and c1..c5 constants defined in
+ * TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00,
+ * c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to
+ * be AES (Rijndael).
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto/aes_wrap.h"
+#include "milenage.h"
+
+
+/**
+ * milenage_f1 - Milenage f1 and f1* algorithms
+ * @opc: OPc = 128-bit value derived from OP and K
+ * @k: K = 128-bit subscriber key
+ * @_rand: RAND = 128-bit random challenge
+ * @sqn: SQN = 48-bit sequence number
+ * @amf: AMF = 16-bit authentication management field
+ * @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL
+ * @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL
+ * Returns: 0 on success, -1 on failure
+ */
+int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
+		const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s)
+{
+	u8 tmp1[16], tmp2[16], tmp3[16];
+	int i;
+
+	/* tmp1 = TEMP = E_K(RAND XOR OP_C) */
+	for (i = 0; i < 16; i++)
+		tmp1[i] = _rand[i] ^ opc[i];
+	if (aes_128_encrypt_block(k, tmp1, tmp1))
+		return -1;
+
+	/* tmp2 = IN1 = SQN || AMF || SQN || AMF */
+	os_memcpy(tmp2, sqn, 6);
+	os_memcpy(tmp2 + 6, amf, 2);
+	os_memcpy(tmp2 + 8, tmp2, 8);
+
+	/* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */
+
+	/* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */
+	for (i = 0; i < 16; i++)
+		tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i];
+	/* XOR with TEMP = E_K(RAND XOR OP_C) */
+	for (i = 0; i < 16; i++)
+		tmp3[i] ^= tmp1[i];
+	/* XOR with c1 (= ..00, i.e., NOP) */
+
+	/* f1 || f1* = E_K(tmp3) XOR OP_c */
+	if (aes_128_encrypt_block(k, tmp3, tmp1))
+		return -1;
+	for (i = 0; i < 16; i++)
+		tmp1[i] ^= opc[i];
+	if (mac_a)
+		os_memcpy(mac_a, tmp1, 8); /* f1 */
+	if (mac_s)
+		os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */
+	return 0;
+}
+
+
+/**
+ * milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
+ * @opc: OPc = 128-bit value derived from OP and K
+ * @k: K = 128-bit subscriber key
+ * @_rand: RAND = 128-bit random challenge
+ * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
+ * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
+ * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
+ * @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL
+ * @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL
+ * Returns: 0 on success, -1 on failure
+ */
+int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
+		   u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar)
+{
+	u8 tmp1[16], tmp2[16], tmp3[16];
+	int i;
+
+	/* tmp2 = TEMP = E_K(RAND XOR OP_C) */
+	for (i = 0; i < 16; i++)
+		tmp1[i] = _rand[i] ^ opc[i];
+	if (aes_128_encrypt_block(k, tmp1, tmp2))
+		return -1;
+
+	/* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */
+	/* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */
+	/* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */
+	/* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */
+
+	/* f2 and f5 */
+	/* rotate by r2 (= 0, i.e., NOP) */
+	for (i = 0; i < 16; i++)
+		tmp1[i] = tmp2[i] ^ opc[i];
+	tmp1[15] ^= 1; /* XOR c2 (= ..01) */
+	/* f5 || f2 = E_K(tmp1) XOR OP_c */
+	if (aes_128_encrypt_block(k, tmp1, tmp3))
+		return -1;
+	for (i = 0; i < 16; i++)
+		tmp3[i] ^= opc[i];
+	if (res)
+		os_memcpy(res, tmp3 + 8, 8); /* f2 */
+	if (ak)
+		os_memcpy(ak, tmp3, 6); /* f5 */
+
+	/* f3 */
+	if (ck) {
+		/* rotate by r3 = 0x20 = 4 bytes */
+		for (i = 0; i < 16; i++)
+			tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i];
+		tmp1[15] ^= 2; /* XOR c3 (= ..02) */
+		if (aes_128_encrypt_block(k, tmp1, ck))
+			return -1;
+		for (i = 0; i < 16; i++)
+			ck[i] ^= opc[i];
+	}
+
+	/* f4 */
+	if (ik) {
+		/* rotate by r4 = 0x40 = 8 bytes */
+		for (i = 0; i < 16; i++)
+			tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i];
+		tmp1[15] ^= 4; /* XOR c4 (= ..04) */
+		if (aes_128_encrypt_block(k, tmp1, ik))
+			return -1;
+		for (i = 0; i < 16; i++)
+			ik[i] ^= opc[i];
+	}
+
+	/* f5* */
+	if (akstar) {
+		/* rotate by r5 = 0x60 = 12 bytes */
+		for (i = 0; i < 16; i++)
+			tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i];
+		tmp1[15] ^= 8; /* XOR c5 (= ..08) */
+		if (aes_128_encrypt_block(k, tmp1, tmp1))
+			return -1;
+		for (i = 0; i < 6; i++)
+			akstar[i] = tmp1[i] ^ opc[i];
+	}
+
+	return 0;
+}
+
+
+/**
+ * milenage_generate - Generate AKA AUTN,IK,CK,RES
+ * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
+ * @amf: AMF = 16-bit authentication management field
+ * @k: K = 128-bit subscriber key
+ * @sqn: SQN = 48-bit sequence number
+ * @_rand: RAND = 128-bit random challenge
+ * @autn: Buffer for AUTN = 128-bit authentication token
+ * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
+ * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
+ * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
+ * @res_len: Max length for res; set to used length or 0 on failure
+ */
+void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
+		       const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik,
+		       u8 *ck, u8 *res, size_t *res_len)
+{
+	int i;
+	u8 mac_a[8], ak[6];
+
+	if (*res_len < 8) {
+		*res_len = 0;
+		return;
+	}
+	if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) ||
+	    milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) {
+		*res_len = 0;
+		return;
+	}
+	*res_len = 8;
+
+	/* AUTN = (SQN ^ AK) || AMF || MAC */
+	for (i = 0; i < 6; i++)
+		autn[i] = sqn[i] ^ ak[i];
+	os_memcpy(autn + 6, amf, 2);
+	os_memcpy(autn + 8, mac_a, 8);
+}
+
+
+/**
+ * milenage_auts - Milenage AUTS validation
+ * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
+ * @k: K = 128-bit subscriber key
+ * @_rand: RAND = 128-bit random challenge
+ * @auts: AUTS = 112-bit authentication token from client
+ * @sqn: Buffer for SQN = 48-bit sequence number
+ * Returns: 0 = success (sqn filled), -1 on failure
+ */
+int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
+		  u8 *sqn)
+{
+	u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
+	u8 ak[6], mac_s[8];
+	int i;
+
+	if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
+		return -1;
+	for (i = 0; i < 6; i++)
+		sqn[i] = auts[i] ^ ak[i];
+	if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) ||
+	    memcmp(mac_s, auts + 6, 8) != 0)
+		return -1;
+	return 0;
+}
+
+
+/**
+ * gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet
+ * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
+ * @k: K = 128-bit subscriber key
+ * @_rand: RAND = 128-bit random challenge
+ * @sres: Buffer for SRES = 32-bit SRES
+ * @kc: Buffer for Kc = 64-bit Kc
+ * Returns: 0 on success, -1 on failure
+ */
+int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc)
+{
+	u8 res[8], ck[16], ik[16];
+	int i;
+
+	if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL))
+		return -1;
+
+	for (i = 0; i < 8; i++)
+		kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8];
+
+#ifdef GSM_MILENAGE_ALT_SRES
+	os_memcpy(sres, res, 4);
+#else /* GSM_MILENAGE_ALT_SRES */
+	for (i = 0; i < 4; i++)
+		sres[i] = res[i] ^ res[i + 4];
+#endif /* GSM_MILENAGE_ALT_SRES */
+	return 0;
+}
+
+
+/**
+ * milenage_generate - Generate AKA AUTN,IK,CK,RES
+ * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
+ * @k: K = 128-bit subscriber key
+ * @sqn: SQN = 48-bit sequence number
+ * @_rand: RAND = 128-bit random challenge
+ * @autn: AUTN = 128-bit authentication token
+ * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
+ * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
+ * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
+ * @res_len: Variable that will be set to RES length
+ * @auts: 112-bit buffer for AUTS
+ * Returns: 0 on success, -1 on failure, or -2 on synchronization failure
+ */
+int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
+		   const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
+		   u8 *auts)
+{
+	int i;
+	u8 mac_a[8], ak[6], rx_sqn[6];
+	const u8 *amf;
+
+	wpa_hexdump(MSG_DEBUG, "Milenage: AUTN", autn, 16);
+	wpa_hexdump(MSG_DEBUG, "Milenage: RAND", _rand, 16);
+
+	if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
+		return -1;
+
+	*res_len = 8;
+	wpa_hexdump_key(MSG_DEBUG, "Milenage: RES", res, *res_len);
+	wpa_hexdump_key(MSG_DEBUG, "Milenage: CK", ck, 16);
+	wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 16);
+	wpa_hexdump_key(MSG_DEBUG, "Milenage: AK", ak, 6);
+
+	/* AUTN = (SQN ^ AK) || AMF || MAC */
+	for (i = 0; i < 6; i++)
+		rx_sqn[i] = autn[i] ^ ak[i];
+	wpa_hexdump(MSG_DEBUG, "Milenage: SQN", rx_sqn, 6);
+
+	if (os_memcmp(rx_sqn, sqn, 6) <= 0) {
+		u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
+		if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
+			return -1;
+		wpa_hexdump_key(MSG_DEBUG, "Milenage: AK*", ak, 6);
+		for (i = 0; i < 6; i++)
+			auts[i] = sqn[i] ^ ak[i];
+		if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6))
+			return -1;
+		wpa_hexdump(MSG_DEBUG, "Milenage: AUTS", auts, 14);
+		return -2;
+	}
+
+	amf = autn + 6;
+	wpa_hexdump(MSG_DEBUG, "Milenage: AMF", amf, 2);
+	if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL))
+		return -1;
+
+	wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8);
+
+	if (os_memcmp(mac_a, autn + 8, 8) != 0) {
+		wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch");
+		wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A",
+			    autn + 8, 8);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/contrib/wpa/src/hlr_auc_gw/milenage.h b/contrib/wpa/src/crypto/milenage.h
similarity index 81%
rename from contrib/wpa/src/hlr_auc_gw/milenage.h
rename to contrib/wpa/src/crypto/milenage.h
index b35603ca8698..d5054d6dcca6 100644
--- a/contrib/wpa/src/hlr_auc_gw/milenage.h
+++ b/contrib/wpa/src/crypto/milenage.h
@@ -25,5 +25,9 @@ int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres,
 int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
 		   const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
 		   u8 *auts);
+int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
+		const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s);
+int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
+		   u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar);
 
 #endif /* MILENAGE_H */
diff --git a/contrib/wpa/src/crypto/ms_funcs.c b/contrib/wpa/src/crypto/ms_funcs.c
index 7e2f0fa37710..dae15ab915fe 100644
--- a/contrib/wpa/src/crypto/ms_funcs.c
+++ b/contrib/wpa/src/crypto/ms_funcs.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
- * Copyright (c) 2004-2007, Jouni Malinen 
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -18,7 +18,6 @@
 #include "sha1.h"
 #include "ms_funcs.h"
 #include "crypto.h"
-#include "rc4.h"
 
 
 /**
@@ -28,10 +27,11 @@
  * @username: 0-to-256-char UserName (IN)
  * @username_len: Length of username
  * @challenge: 8-octet Challenge (OUT)
+ * Returns: 0 on success, -1 on failure
  */
-static void challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
-			   const u8 *username, size_t username_len,
-			   u8 *challenge)
+static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
+			  const u8 *username, size_t username_len,
+			  u8 *challenge)
 {
 	u8 hash[SHA1_MAC_LEN];
 	const unsigned char *addr[3];
@@ -44,8 +44,10 @@ static void challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
 	addr[2] = username;
 	len[2] = username_len;
 
-	sha1_vector(3, addr, len, hash);
+	if (sha1_vector(3, addr, len, hash))
+		return -1;
 	os_memcpy(challenge, hash, 8);
+	return 0;
 }
 
 
@@ -54,8 +56,9 @@ static void challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
  * @password: 0-to-256-unicode-char Password (IN; ASCII)
  * @password_len: Length of password
  * @password_hash: 16-octet PasswordHash (OUT)
+ * Returns: 0 on success, -1 on failure
  */
-void nt_password_hash(const u8 *password, size_t password_len,
+int nt_password_hash(const u8 *password, size_t password_len,
 		      u8 *password_hash)
 {
 	u8 buf[512], *pos;
@@ -72,7 +75,7 @@ void nt_password_hash(const u8 *password, size_t password_len,
 
 	len = password_len * 2;
 	pos = buf;
-	md4_vector(1, (const u8 **) &pos, &len, password_hash);
+	return md4_vector(1, (const u8 **) &pos, &len, password_hash);
 }
 
 
@@ -80,11 +83,12 @@ void nt_password_hash(const u8 *password, size_t password_len,
  * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4
  * @password_hash: 16-octet PasswordHash (IN)
  * @password_hash_hash: 16-octet PasswordHashHash (OUT)
+ * Returns: 0 on success, -1 on failure
  */
-void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
+int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
 {
 	size_t len = 16;
-	md4_vector(1, &password_hash, &len, password_hash_hash);
+	return md4_vector(1, &password_hash, &len, password_hash_hash);
 }
 
 
@@ -116,19 +120,22 @@ void challenge_response(const u8 *challenge, const u8 *password_hash,
  * @password: 0-to-256-unicode-char Password (IN; ASCII)
  * @password_len: Length of password
  * @response: 24-octet Response (OUT)
+ * Returns: 0 on success, -1 on failure
  */
-void generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
-			  const u8 *username, size_t username_len,
-			  const u8 *password, size_t password_len,
-			  u8 *response)
+int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
+			 const u8 *username, size_t username_len,
+			 const u8 *password, size_t password_len,
+			 u8 *response)
 {
 	u8 challenge[8];
 	u8 password_hash[16];
 
 	challenge_hash(peer_challenge, auth_challenge, username, username_len,
 		       challenge);
-	nt_password_hash(password, password_len, password_hash);
+	if (nt_password_hash(password, password_len, password_hash))
+		return -1;
 	challenge_response(challenge, password_hash, response);
+	return 0;
 }
 
 
@@ -140,18 +147,22 @@ void generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
  * @username_len: Length of username
  * @password_hash: 16-octet PasswordHash (IN)
  * @response: 24-octet Response (OUT)
+ * Returns: 0 on success, -1 on failure
  */
-void generate_nt_response_pwhash(const u8 *auth_challenge,
-				 const u8 *peer_challenge,
-				 const u8 *username, size_t username_len,
-				 const u8 *password_hash,
-				 u8 *response)
+int generate_nt_response_pwhash(const u8 *auth_challenge,
+				const u8 *peer_challenge,
+				const u8 *username, size_t username_len,
+				const u8 *password_hash,
+				u8 *response)
 {
 	u8 challenge[8];
 
-	challenge_hash(peer_challenge, auth_challenge, username, username_len,
-		       challenge);
+	if (challenge_hash(peer_challenge, auth_challenge,
+			   username, username_len,
+			   challenge))
+		return -1;
 	challenge_response(challenge, password_hash, response);
+	return 0;
 }
 
 
@@ -165,8 +176,9 @@ void generate_nt_response_pwhash(const u8 *auth_challenge,
  * @username_len: Length of username
  * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
  * encoded as a 42-octet ASCII string (S=hexdump_of_response)
+ * Returns: 0 on success, -1 on failure
  */
-void generate_authenticator_response_pwhash(
+int generate_authenticator_response_pwhash(
 	const u8 *password_hash,
 	const u8 *peer_challenge, const u8 *auth_challenge,
 	const u8 *username, size_t username_len,
@@ -200,12 +212,14 @@ void generate_authenticator_response_pwhash(
 	addr2[1] = challenge;
 	addr2[2] = magic2;
 
-	hash_nt_password_hash(password_hash, password_hash_hash);
-	sha1_vector(3, addr1, len1, response);
+	if (hash_nt_password_hash(password_hash, password_hash_hash))
+		return -1;
+	if (sha1_vector(3, addr1, len1, response))
+		return -1;
 
 	challenge_hash(peer_challenge, auth_challenge, username, username_len,
 		       challenge);
-	sha1_vector(3, addr2, len2, response);
+	return sha1_vector(3, addr2, len2, response);
 }
 
 
@@ -220,19 +234,20 @@ void generate_authenticator_response_pwhash(
  * @username_len: Length of username
  * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
  * encoded as a 42-octet ASCII string (S=hexdump_of_response)
+ * Returns: 0 on success, -1 on failure
  */
-void generate_authenticator_response(const u8 *password, size_t password_len,
-				     const u8 *peer_challenge,
-				     const u8 *auth_challenge,
-				     const u8 *username, size_t username_len,
-				     const u8 *nt_response, u8 *response)
+int generate_authenticator_response(const u8 *password, size_t password_len,
+				    const u8 *peer_challenge,
+				    const u8 *auth_challenge,
+				    const u8 *username, size_t username_len,
+				    const u8 *nt_response, u8 *response)
 {
 	u8 password_hash[16];
-	nt_password_hash(password, password_len, password_hash);
-	generate_authenticator_response_pwhash(password_hash,
-					       peer_challenge, auth_challenge,
-					       username, username_len,
-					       nt_response, response);
+	if (nt_password_hash(password, password_len, password_hash))
+		return -1;
+	return generate_authenticator_response_pwhash(
+		password_hash, peer_challenge, auth_challenge,
+		username, username_len, nt_response, response);
 }
 
 
@@ -242,13 +257,16 @@ void generate_authenticator_response(const u8 *password, size_t password_len,
  * @password: 0-to-256-unicode-char Password (IN; ASCII)
  * @password_len: Length of password
  * @response: 24-octet Response (OUT)
+ * Returns: 0 on success, -1 on failure
  */
-void nt_challenge_response(const u8 *challenge, const u8 *password,
-			   size_t password_len, u8 *response)
+int nt_challenge_response(const u8 *challenge, const u8 *password,
+			  size_t password_len, u8 *response)
 {
 	u8 password_hash[16];
-	nt_password_hash(password, password_len, password_hash);
+	if (nt_password_hash(password, password_len, password_hash))
+		return -1;
 	challenge_response(challenge, password_hash, response);
+	return 0;
 }
 
 
@@ -257,9 +275,10 @@ void nt_challenge_response(const u8 *challenge, const u8 *password,
  * @password_hash_hash: 16-octet PasswordHashHash (IN)
  * @nt_response: 24-octet NTResponse (IN)
  * @master_key: 16-octet MasterKey (OUT)
+ * Returns: 0 on success, -1 on failure
  */
-void get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
-		    u8 *master_key)
+int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
+		   u8 *master_key)
 {
 	static const u8 magic1[27] = {
 		0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
@@ -274,8 +293,10 @@ void get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
 	addr[1] = nt_response;
 	addr[2] = magic1;
 
-	sha1_vector(3, addr, len, hash);
+	if (sha1_vector(3, addr, len, hash))
+		return -1;
 	os_memcpy(master_key, hash, 16);
+	return 0;
 }
 
 
@@ -286,10 +307,11 @@ void get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
  * @session_key_len: SessionKeyLength (Length of session_key) (IN)
  * @is_send: IsSend (IN, BOOLEAN)
  * @is_server: IsServer (IN, BOOLEAN)
+ * Returns: 0 on success, -1 on failure
  */
-void get_asymetric_start_key(const u8 *master_key, u8 *session_key,
-			     size_t session_key_len, int is_send,
-			     int is_server)
+int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
+			    size_t session_key_len, int is_send,
+			    int is_server)
 {
 	static const u8 magic2[84] = {
 		0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
@@ -339,11 +361,13 @@ void get_asymetric_start_key(const u8 *master_key, u8 *session_key,
 	}
 	addr[3] = shs_pad2;
 
-	sha1_vector(4, addr, len, digest);
+	if (sha1_vector(4, addr, len, digest))
+		return -1;
 
 	if (session_key_len > SHA1_MAC_LEN)
 		session_key_len = SHA1_MAC_LEN;
 	os_memcpy(session_key, digest, session_key_len);
+	return 0;
 }
 
 
@@ -400,7 +424,8 @@ int new_password_encrypted_with_old_nt_password_hash(
 {
 	u8 password_hash[16];
 
-	nt_password_hash(old_password, old_password_len, password_hash);
+	if (nt_password_hash(old_password, old_password_len, password_hash))
+		return -1;
 	if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
 						password_hash,
 						encrypted_pw_block))
@@ -430,17 +455,22 @@ void nt_password_hash_encrypted_with_block(const u8 *password_hash,
  * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII)
  * @old_password_len: Length of old_password
  * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
+ * Returns: 0 on success, -1 on failure
  */
-void old_nt_password_hash_encrypted_with_new_nt_password_hash(
+int old_nt_password_hash_encrypted_with_new_nt_password_hash(
 	const u8 *new_password, size_t new_password_len,
 	const u8 *old_password, size_t old_password_len,
 	u8 *encrypted_password_hash)
 {
 	u8 old_password_hash[16], new_password_hash[16];
 
-	nt_password_hash(old_password, old_password_len, old_password_hash);
-	nt_password_hash(new_password, new_password_len, new_password_hash);
+	if (nt_password_hash(old_password, old_password_len,
+			     old_password_hash) ||
+	    nt_password_hash(new_password, new_password_len,
+			     new_password_hash))
+		return -1;
 	nt_password_hash_encrypted_with_block(old_password_hash,
 					      new_password_hash,
 					      encrypted_password_hash);
+	return 0;
 }
diff --git a/contrib/wpa/src/crypto/ms_funcs.h b/contrib/wpa/src/crypto/ms_funcs.h
index 6205bf68d3ec..298dbcf4fee3 100644
--- a/contrib/wpa/src/crypto/ms_funcs.h
+++ b/contrib/wpa/src/crypto/ms_funcs.h
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
- * Copyright (c) 2004-2007, Jouni Malinen 
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -15,38 +15,38 @@
 #ifndef MS_FUNCS_H
 #define MS_FUNCS_H
 
-void generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
-			  const u8 *username, size_t username_len,
-			  const u8 *password, size_t password_len,
-			  u8 *response);
-void generate_nt_response_pwhash(const u8 *auth_challenge,
-				 const u8 *peer_challenge,
-				 const u8 *username, size_t username_len,
-				 const u8 *password_hash,
-				 u8 *response);
-void generate_authenticator_response(const u8 *password, size_t password_len,
-				     const u8 *peer_challenge,
-				     const u8 *auth_challenge,
-				     const u8 *username, size_t username_len,
-				     const u8 *nt_response, u8 *response);
-void generate_authenticator_response_pwhash(
+int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
+			 const u8 *username, size_t username_len,
+			 const u8 *password, size_t password_len,
+			 u8 *response);
+int generate_nt_response_pwhash(const u8 *auth_challenge,
+				const u8 *peer_challenge,
+				const u8 *username, size_t username_len,
+				const u8 *password_hash,
+				u8 *response);
+int generate_authenticator_response(const u8 *password, size_t password_len,
+				    const u8 *peer_challenge,
+				    const u8 *auth_challenge,
+				    const u8 *username, size_t username_len,
+				    const u8 *nt_response, u8 *response);
+int generate_authenticator_response_pwhash(
 	const u8 *password_hash,
 	const u8 *peer_challenge, const u8 *auth_challenge,
 	const u8 *username, size_t username_len,
 	const u8 *nt_response, u8 *response);
-void nt_challenge_response(const u8 *challenge, const u8 *password,
-			   size_t password_len, u8 *response);
+int nt_challenge_response(const u8 *challenge, const u8 *password,
+			  size_t password_len, u8 *response);
 
 void challenge_response(const u8 *challenge, const u8 *password_hash,
 			u8 *response);
-void nt_password_hash(const u8 *password, size_t password_len,
-		      u8 *password_hash);
-void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash);
-void get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
-		    u8 *master_key);
-void get_asymetric_start_key(const u8 *master_key, u8 *session_key,
-			     size_t session_key_len, int is_send,
-			     int is_server);
+int nt_password_hash(const u8 *password, size_t password_len,
+		     u8 *password_hash);
+int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash);
+int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
+		   u8 *master_key);
+int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
+			    size_t session_key_len, int is_send,
+			    int is_server);
 int __must_check encrypt_pw_block_with_password_hash(
 	const u8 *password, size_t password_len,
 	const u8 *password_hash, u8 *pw_block);
@@ -56,7 +56,7 @@ int __must_check new_password_encrypted_with_old_nt_password_hash(
 	u8 *encrypted_pw_block);
 void nt_password_hash_encrypted_with_block(const u8 *password_hash,
 					   const u8 *block, u8 *cypher);
-void old_nt_password_hash_encrypted_with_new_nt_password_hash(
+int old_nt_password_hash_encrypted_with_new_nt_password_hash(
 	const u8 *new_password, size_t new_password_len,
 	const u8 *old_password, size_t old_password_len,
 	u8 *encrypted_password_hash);
diff --git a/contrib/wpa/src/crypto/rc4.c b/contrib/wpa/src/crypto/rc4.c
index 70c790e364f7..5ab1be191e9a 100644
--- a/contrib/wpa/src/crypto/rc4.c
+++ b/contrib/wpa/src/crypto/rc4.c
@@ -15,24 +15,12 @@
 #include "includes.h"
 
 #include "common.h"
-#include "rc4.h"
+#include "crypto.h"
 
 #define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
 
-/**
- * rc4 - XOR RC4 stream to given data with skip-stream-start
- * @key: RC4 key
- * @keylen: RC4 key length
- * @skip: number of bytes to skip from the beginning of the RC4 stream
- * @data: data to be XOR'ed with RC4 stream
- * @data_len: buf length
- *
- * Generate RC4 pseudo random stream for the given key, skip beginning of the
- * stream, and XOR the end result with the data buffer to perform RC4
- * encryption/decryption.
- */
-void rc4_skip(const u8 *key, size_t keylen, size_t skip,
-	      u8 *data, size_t data_len)
+int rc4_skip(const u8 *key, size_t keylen, size_t skip,
+	     u8 *data, size_t data_len)
 {
 	u32 i, j, k;
 	u8 S[256], *pos;
@@ -67,4 +55,6 @@ void rc4_skip(const u8 *key, size_t keylen, size_t skip,
 		S_SWAP(i, j);
 		*pos++ ^= S[(S[i] + S[j]) & 0xff];
 	}
+
+	return 0;
 }
diff --git a/contrib/wpa/src/crypto/sha1-internal.c b/contrib/wpa/src/crypto/sha1-internal.c
new file mode 100644
index 000000000000..3f05ca113125
--- /dev/null
+++ b/contrib/wpa/src/crypto/sha1-internal.c
@@ -0,0 +1,308 @@
+/*
+ * SHA1 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen 
+ *
+ * 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 "sha1.h"
+#include "sha1_i.h"
+#include "md5.h"
+#include "crypto.h"
+
+typedef struct SHA1Context SHA1_CTX;
+
+void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
+
+
+/**
+ * sha1_vector - SHA-1 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 of failure
+ */
+int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+	SHA1_CTX ctx;
+	size_t i;
+
+	SHA1Init(&ctx);
+	for (i = 0; i < num_elem; i++)
+		SHA1Update(&ctx, addr[i], len[i]);
+	SHA1Final(mac, &ctx);
+	return 0;
+}
+
+
+/* ===== start - public domain SHA1 implementation ===== */
+
+/*
+SHA-1 in C
+By Steve Reid 
+100% Public Domain
+
+-----------------
+Modified 7/98 
+By James H. Brown 
+Still 100% Public Domain
+
+Corrected a problem which generated improper hash values on 16 bit machines
+Routine SHA1Update changed from
+	void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
+len)
+to
+	void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
+long len)
+
+The 'len' parameter was declared an int which works fine on 32 bit machines.
+However, on 16 bit machines an int is too small for the shifts being done
+against
+it.  This caused the hash function to generate incorrect values if len was
+greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
+
+Since the file IO in main() reads 16K at a time, any file 8K or larger would
+be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
+"a"s).
+
+I also changed the declaration of variables i & j in SHA1Update to 
+unsigned long from unsigned int for the same reason.
+
+These changes should make no difference to any 32 bit implementations since
+an
+int and a long are the same size in those environments.
+
+--
+I also corrected a few compiler warnings generated by Borland C.
+1. Added #include  for exit() prototype
+2. Removed unused variable 'j' in SHA1Final
+3. Changed exit(0) to return(0) at end of main.
+
+ALL changes I made can be located by searching for comments containing 'JHB'
+-----------------
+Modified 8/98
+By Steve Reid 
+Still 100% public domain
+
+1- Removed #include  and used return() instead of exit()
+2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
+3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
+
+-----------------
+Modified 4/01
+By Saul Kravitz 
+Still 100% PD
+Modified to run on Compaq Alpha hardware.  
+
+-----------------
+Modified 4/01
+By Jouni Malinen 
+Minor changes to match the coding style used in Dynamics.
+
+Modified September 24, 2004
+By Jouni Malinen 
+Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
+
+*/
+
+/*
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+#define SHA1HANDSOFF
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifndef WORDS_BIGENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
+	(rol(block->l[i], 8) & 0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
+	block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) \
+	z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
+	w = rol(w, 30);
+#define R1(v,w,x,y,z,i) \
+	z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
+	w = rol(w, 30);
+#define R2(v,w,x,y,z,i) \
+	z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
+#define R3(v,w,x,y,z,i) \
+	z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
+	w = rol(w, 30);
+#define R4(v,w,x,y,z,i) \
+	z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
+	w=rol(w, 30);
+
+
+#ifdef VERBOSE  /* SAK */
+void SHAPrintContext(SHA1_CTX *context, char *msg)
+{
+	printf("%s (%d,%d) %x %x %x %x %x\n",
+	       msg,
+	       context->count[0], context->count[1], 
+	       context->state[0],
+	       context->state[1],
+	       context->state[2],
+	       context->state[3],
+	       context->state[4]);
+}
+#endif
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(u32 state[5], const unsigned char buffer[64])
+{
+	u32 a, b, c, d, e;
+	typedef union {
+		unsigned char c[64];
+		u32 l[16];
+	} CHAR64LONG16;
+	CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+	CHAR64LONG16 workspace;
+	block = &workspace;
+	os_memcpy(block, buffer, 64);
+#else
+	block = (CHAR64LONG16 *) buffer;
+#endif
+	/* Copy context->state[] to working vars */
+	a = state[0];
+	b = state[1];
+	c = state[2];
+	d = state[3];
+	e = state[4];
+	/* 4 rounds of 20 operations each. Loop unrolled. */
+	R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+	R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+	R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+	R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+	R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+	R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+	R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+	R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+	R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+	R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+	R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+	R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+	R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+	R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+	R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+	R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+	R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+	R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+	R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+	R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+	/* Add the working vars back into context.state[] */
+	state[0] += a;
+	state[1] += b;
+	state[2] += c;
+	state[3] += d;
+	state[4] += e;
+	/* Wipe variables */
+	a = b = c = d = e = 0;
+#ifdef SHA1HANDSOFF
+	os_memset(block, 0, 64);
+#endif
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+	/* SHA1 initialization constants */
+	context->state[0] = 0x67452301;
+	context->state[1] = 0xEFCDAB89;
+	context->state[2] = 0x98BADCFE;
+	context->state[3] = 0x10325476;
+	context->state[4] = 0xC3D2E1F0;
+	context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
+{
+	u32 i, j;
+	const unsigned char *data = _data;
+
+#ifdef VERBOSE
+	SHAPrintContext(context, "before");
+#endif
+	j = (context->count[0] >> 3) & 63;
+	if ((context->count[0] += len << 3) < (len << 3))
+		context->count[1]++;
+	context->count[1] += (len >> 29);
+	if ((j + len) > 63) {
+		os_memcpy(&context->buffer[j], data, (i = 64-j));
+		SHA1Transform(context->state, context->buffer);
+		for ( ; i + 63 < len; i += 64) {
+			SHA1Transform(context->state, &data[i]);
+		}
+		j = 0;
+	}
+	else i = 0;
+	os_memcpy(&context->buffer[j], &data[i], len - i);
+#ifdef VERBOSE
+	SHAPrintContext(context, "after ");
+#endif
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+	u32 i;
+	unsigned char finalcount[8];
+
+	for (i = 0; i < 8; i++) {
+		finalcount[i] = (unsigned char)
+			((context->count[(i >= 4 ? 0 : 1)] >>
+			  ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
+	}
+	SHA1Update(context, (unsigned char *) "\200", 1);
+	while ((context->count[0] & 504) != 448) {
+		SHA1Update(context, (unsigned char *) "\0", 1);
+	}
+	SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform()
+					      */
+	for (i = 0; i < 20; i++) {
+		digest[i] = (unsigned char)
+			((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
+			 255);
+	}
+	/* Wipe variables */
+	i = 0;
+	os_memset(context->buffer, 0, 64);
+	os_memset(context->state, 0, 20);
+	os_memset(context->count, 0, 8);
+	os_memset(finalcount, 0, 8);
+}
+
+/* ===== end - public domain SHA1 implementation ===== */
diff --git a/contrib/wpa/src/crypto/sha1-pbkdf2.c b/contrib/wpa/src/crypto/sha1-pbkdf2.c
new file mode 100644
index 000000000000..11323de7a01e
--- /dev/null
+++ b/contrib/wpa/src/crypto/sha1-pbkdf2.c
@@ -0,0 +1,100 @@
+/*
+ * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i
+ * Copyright (c) 2003-2005, Jouni Malinen 
+ *
+ * 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 "sha1.h"
+#include "md5.h"
+#include "crypto.h"
+
+static int pbkdf2_sha1_f(const char *passphrase, const char *ssid,
+			 size_t ssid_len, int iterations, unsigned int count,
+			 u8 *digest)
+{
+	unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN];
+	int i, j;
+	unsigned char count_buf[4];
+	const u8 *addr[2];
+	size_t len[2];
+	size_t passphrase_len = os_strlen(passphrase);
+
+	addr[0] = (u8 *) ssid;
+	len[0] = ssid_len;
+	addr[1] = count_buf;
+	len[1] = 4;
+
+	/* F(P, S, c, i) = U1 xor U2 xor ... Uc
+	 * U1 = PRF(P, S || i)
+	 * U2 = PRF(P, U1)
+	 * Uc = PRF(P, Uc-1)
+	 */
+
+	count_buf[0] = (count >> 24) & 0xff;
+	count_buf[1] = (count >> 16) & 0xff;
+	count_buf[2] = (count >> 8) & 0xff;
+	count_buf[3] = count & 0xff;
+	if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len,
+			     tmp))
+		return -1;
+	os_memcpy(digest, tmp, SHA1_MAC_LEN);
+
+	for (i = 1; i < iterations; i++) {
+		if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp,
+			      SHA1_MAC_LEN, tmp2))
+			return -1;
+		os_memcpy(tmp, tmp2, SHA1_MAC_LEN);
+		for (j = 0; j < SHA1_MAC_LEN; j++)
+			digest[j] ^= tmp2[j];
+	}
+
+	return 0;
+}
+
+
+/**
+ * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i
+ * @passphrase: ASCII passphrase
+ * @ssid: SSID
+ * @ssid_len: SSID length in bytes
+ * @iterations: Number of iterations to run
+ * @buf: Buffer for the generated key
+ * @buflen: Length of the buffer in bytes
+ * Returns: 0 on success, -1 of failure
+ *
+ * This function is used to derive PSK for WPA-PSK. For this protocol,
+ * iterations is set to 4096 and buflen to 32. This function is described in
+ * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0.
+ */
+int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
+		int iterations, u8 *buf, size_t buflen)
+{
+	unsigned int count = 0;
+	unsigned char *pos = buf;
+	size_t left = buflen, plen;
+	unsigned char digest[SHA1_MAC_LEN];
+
+	while (left > 0) {
+		count++;
+		if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations,
+				  count, digest))
+			return -1;
+		plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left;
+		os_memcpy(pos, digest, plen);
+		pos += plen;
+		left -= plen;
+	}
+
+	return 0;
+}
diff --git a/contrib/wpa/src/crypto/sha1-tlsprf.c b/contrib/wpa/src/crypto/sha1-tlsprf.c
new file mode 100644
index 000000000000..2c8c029ecf49
--- /dev/null
+++ b/contrib/wpa/src/crypto/sha1-tlsprf.c
@@ -0,0 +1,109 @@
+/*
+ * TLS PRF (SHA1 + MD5)
+ * Copyright (c) 2003-2005, Jouni Malinen 
+ *
+ * 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 "sha1.h"
+#include "md5.h"
+#include "crypto.h"
+
+
+/**
+ * tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246)
+ * @secret: Key for PRF
+ * @secret_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the PRF
+ * @seed: Seed value to bind into the key
+ * @seed_len: Length of the seed
+ * @out: Buffer for the generated pseudo-random key
+ * @outlen: Number of bytes of key to generate
+ * Returns: 0 on success, -1 on failure.
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key in TLS. This PRF is defined in RFC 2246, Chapter 5.
+ */
+int tls_prf(const u8 *secret, size_t secret_len, const char *label,
+	    const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
+{
+	size_t L_S1, L_S2, i;
+	const u8 *S1, *S2;
+	u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN];
+	u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN];
+	int MD5_pos, SHA1_pos;
+	const u8 *MD5_addr[3];
+	size_t MD5_len[3];
+	const unsigned char *SHA1_addr[3];
+	size_t SHA1_len[3];
+
+	if (secret_len & 1)
+		return -1;
+
+	MD5_addr[0] = A_MD5;
+	MD5_len[0] = MD5_MAC_LEN;
+	MD5_addr[1] = (unsigned char *) label;
+	MD5_len[1] = os_strlen(label);
+	MD5_addr[2] = seed;
+	MD5_len[2] = seed_len;
+
+	SHA1_addr[0] = A_SHA1;
+	SHA1_len[0] = SHA1_MAC_LEN;
+	SHA1_addr[1] = (unsigned char *) label;
+	SHA1_len[1] = os_strlen(label);
+	SHA1_addr[2] = seed;
+	SHA1_len[2] = seed_len;
+
+	/* RFC 2246, Chapter 5
+	 * A(0) = seed, A(i) = HMAC(secret, A(i-1))
+	 * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + ..
+	 * PRF = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed)
+	 */
+
+	L_S1 = L_S2 = (secret_len + 1) / 2;
+	S1 = secret;
+	S2 = secret + L_S1;
+	if (secret_len & 1) {
+		/* The last byte of S1 will be shared with S2 */
+		S2--;
+	}
+
+	hmac_md5_vector_non_fips_allow(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1],
+				       A_MD5);
+	hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1);
+
+	MD5_pos = MD5_MAC_LEN;
+	SHA1_pos = SHA1_MAC_LEN;
+	for (i = 0; i < outlen; i++) {
+		if (MD5_pos == MD5_MAC_LEN) {
+			hmac_md5_vector_non_fips_allow(S1, L_S1, 3, MD5_addr,
+						       MD5_len, P_MD5);
+			MD5_pos = 0;
+			hmac_md5_non_fips_allow(S1, L_S1, A_MD5, MD5_MAC_LEN,
+						A_MD5);
+		}
+		if (SHA1_pos == SHA1_MAC_LEN) {
+			hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len,
+					 P_SHA1);
+			SHA1_pos = 0;
+			hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1);
+		}
+
+		out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos];
+
+		MD5_pos++;
+		SHA1_pos++;
+	}
+
+	return 0;
+}
diff --git a/contrib/wpa/src/crypto/sha1-tprf.c b/contrib/wpa/src/crypto/sha1-tprf.c
new file mode 100644
index 000000000000..4a80e96f0193
--- /dev/null
+++ b/contrib/wpa/src/crypto/sha1-tprf.c
@@ -0,0 +1,76 @@
+/*
+ * SHA1 T-PRF for EAP-FAST
+ * Copyright (c) 2003-2005, Jouni Malinen 
+ *
+ * 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 "sha1.h"
+#include "crypto.h"
+
+/**
+ * sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF)
+ * @key: Key for PRF
+ * @key_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the PRF
+ * @seed: Seed value to bind into the key
+ * @seed_len: Length of the seed
+ * @buf: Buffer for the generated pseudo-random key
+ * @buf_len: Number of bytes of key to generate
+ * Returns: 0 on success, -1 of failure
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5.
+ */
+int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
+	       const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len)
+{
+	unsigned char counter = 0;
+	size_t pos, plen;
+	u8 hash[SHA1_MAC_LEN];
+	size_t label_len = os_strlen(label);
+	u8 output_len[2];
+	const unsigned char *addr[5];
+	size_t len[5];
+
+	addr[0] = hash;
+	len[0] = 0;
+	addr[1] = (unsigned char *) label;
+	len[1] = label_len + 1;
+	addr[2] = seed;
+	len[2] = seed_len;
+	addr[3] = output_len;
+	len[3] = 2;
+	addr[4] = &counter;
+	len[4] = 1;
+
+	output_len[0] = (buf_len >> 8) & 0xff;
+	output_len[1] = buf_len & 0xff;
+	pos = 0;
+	while (pos < buf_len) {
+		counter++;
+		plen = buf_len - pos;
+		if (hmac_sha1_vector(key, key_len, 5, addr, len, hash))
+			return -1;
+		if (plen >= SHA1_MAC_LEN) {
+			os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
+			pos += SHA1_MAC_LEN;
+		} else {
+			os_memcpy(&buf[pos], hash, plen);
+			break;
+		}
+		len[0] = SHA1_MAC_LEN;
+	}
+
+	return 0;
+}
diff --git a/contrib/wpa/src/crypto/sha1.c b/contrib/wpa/src/crypto/sha1.c
index 141e4f4ee60a..fe00bdbc5869 100644
--- a/contrib/wpa/src/crypto/sha1.c
+++ b/contrib/wpa/src/crypto/sha1.c
@@ -16,7 +16,6 @@
 
 #include "common.h"
 #include "sha1.h"
-#include "md5.h"
 #include "crypto.h"
 
 
@@ -28,9 +27,10 @@
  * @addr: Pointers to the data areas
  * @len: Lengths of the data blocks
  * @mac: Buffer for the hash (20 bytes)
+ * Returns: 0 on success, -1 on failure
  */
-void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
-		      const u8 *addr[], const size_t *len, u8 *mac)
+int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
+		     const u8 *addr[], const size_t *len, u8 *mac)
 {
 	unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
 	unsigned char tk[20];
@@ -42,12 +42,13 @@ void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
 		 * Fixed limit on the number of fragments to avoid having to
 		 * allocate memory (which could fail).
 		 */
-		return;
+		return -1;
 	}
 
         /* if key is longer than 64 bytes reset it to key = SHA1(key) */
         if (key_len > 64) {
-		sha1_vector(1, &key, &key_len, tk);
+		if (sha1_vector(1, &key, &key_len, tk))
+			return -1;
 		key = tk;
 		key_len = 20;
         }
@@ -75,7 +76,8 @@ void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
 		_addr[i + 1] = addr[i];
 		_len[i + 1] = len[i];
 	}
-	sha1_vector(1 + num_elem, _addr, _len, mac);
+	if (sha1_vector(1 + num_elem, _addr, _len, mac))
+		return -1;
 
 	os_memset(k_pad, 0, sizeof(k_pad));
 	os_memcpy(k_pad, key, key_len);
@@ -88,7 +90,7 @@ void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
 	_len[0] = 64;
 	_addr[1] = mac;
 	_len[1] = SHA1_MAC_LEN;
-	sha1_vector(2, _addr, _len, mac);
+	return sha1_vector(2, _addr, _len, mac);
 }
 
 
@@ -99,11 +101,12 @@ void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
  * @data: Pointers to the data area
  * @data_len: Length of the data area
  * @mac: Buffer for the hash (20 bytes)
+ * Returns: 0 on success, -1 of failure
  */
-void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
 	       u8 *mac)
 {
-	hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
+	return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
 }
 
 
@@ -116,12 +119,13 @@ void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
  * @data_len: Length of the data
  * @buf: Buffer for the generated pseudo-random key
  * @buf_len: Number of bytes of key to generate
+ * Returns: 0 on success, -1 of failure
  *
  * This function is used to derive new, cryptographically separate keys from a
  * given key (e.g., PMK in IEEE 802.11i).
  */
-void sha1_prf(const u8 *key, size_t key_len, const char *label,
-	      const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
+int sha1_prf(const u8 *key, size_t key_len, const char *label,
+	     const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
 {
 	u8 counter = 0;
 	size_t pos, plen;
@@ -141,593 +145,19 @@ void sha1_prf(const u8 *key, size_t key_len, const char *label,
 	while (pos < buf_len) {
 		plen = buf_len - pos;
 		if (plen >= SHA1_MAC_LEN) {
-			hmac_sha1_vector(key, key_len, 3, addr, len,
-					 &buf[pos]);
+			if (hmac_sha1_vector(key, key_len, 3, addr, len,
+					     &buf[pos]))
+				return -1;
 			pos += SHA1_MAC_LEN;
 		} else {
-			hmac_sha1_vector(key, key_len, 3, addr, len,
-					 hash);
+			if (hmac_sha1_vector(key, key_len, 3, addr, len,
+					     hash))
+				return -1;
 			os_memcpy(&buf[pos], hash, plen);
 			break;
 		}
 		counter++;
 	}
-}
-
-
-#ifndef CONFIG_NO_T_PRF
-/**
- * sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF)
- * @key: Key for PRF
- * @key_len: Length of the key in bytes
- * @label: A unique label for each purpose of the PRF
- * @seed: Seed value to bind into the key
- * @seed_len: Length of the seed
- * @buf: Buffer for the generated pseudo-random key
- * @buf_len: Number of bytes of key to generate
- *
- * This function is used to derive new, cryptographically separate keys from a
- * given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5.
- */
-void sha1_t_prf(const u8 *key, size_t key_len, const char *label,
-		const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len)
-{
-	unsigned char counter = 0;
-	size_t pos, plen;
-	u8 hash[SHA1_MAC_LEN];
-	size_t label_len = os_strlen(label);
-	u8 output_len[2];
-	const unsigned char *addr[5];
-	size_t len[5];
-
-	addr[0] = hash;
-	len[0] = 0;
-	addr[1] = (unsigned char *) label;
-	len[1] = label_len + 1;
-	addr[2] = seed;
-	len[2] = seed_len;
-	addr[3] = output_len;
-	len[3] = 2;
-	addr[4] = &counter;
-	len[4] = 1;
-
-	output_len[0] = (buf_len >> 8) & 0xff;
-	output_len[1] = buf_len & 0xff;
-	pos = 0;
-	while (pos < buf_len) {
-		counter++;
-		plen = buf_len - pos;
-		hmac_sha1_vector(key, key_len, 5, addr, len, hash);
-		if (plen >= SHA1_MAC_LEN) {
-			os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
-			pos += SHA1_MAC_LEN;
-		} else {
-			os_memcpy(&buf[pos], hash, plen);
-			break;
-		}
-		len[0] = SHA1_MAC_LEN;
-	}
-}
-#endif /* CONFIG_NO_T_PRF */
-
-
-#ifndef CONFIG_NO_TLS_PRF
-/**
- * tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246)
- * @secret: Key for PRF
- * @secret_len: Length of the key in bytes
- * @label: A unique label for each purpose of the PRF
- * @seed: Seed value to bind into the key
- * @seed_len: Length of the seed
- * @out: Buffer for the generated pseudo-random key
- * @outlen: Number of bytes of key to generate
- * Returns: 0 on success, -1 on failure.
- *
- * This function is used to derive new, cryptographically separate keys from a
- * given key in TLS. This PRF is defined in RFC 2246, Chapter 5.
- */
-int tls_prf(const u8 *secret, size_t secret_len, const char *label,
-	    const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
-{
-	size_t L_S1, L_S2, i;
-	const u8 *S1, *S2;
-	u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN];
-	u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN];
-	int MD5_pos, SHA1_pos;
-	const u8 *MD5_addr[3];
-	size_t MD5_len[3];
-	const unsigned char *SHA1_addr[3];
-	size_t SHA1_len[3];
-
-	if (secret_len & 1)
-		return -1;
-
-	MD5_addr[0] = A_MD5;
-	MD5_len[0] = MD5_MAC_LEN;
-	MD5_addr[1] = (unsigned char *) label;
-	MD5_len[1] = os_strlen(label);
-	MD5_addr[2] = seed;
-	MD5_len[2] = seed_len;
-
-	SHA1_addr[0] = A_SHA1;
-	SHA1_len[0] = SHA1_MAC_LEN;
-	SHA1_addr[1] = (unsigned char *) label;
-	SHA1_len[1] = os_strlen(label);
-	SHA1_addr[2] = seed;
-	SHA1_len[2] = seed_len;
-
-	/* RFC 2246, Chapter 5
-	 * A(0) = seed, A(i) = HMAC(secret, A(i-1))
-	 * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + ..
-	 * PRF = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed)
-	 */
-
-	L_S1 = L_S2 = (secret_len + 1) / 2;
-	S1 = secret;
-	S2 = secret + L_S1;
-	if (secret_len & 1) {
-		/* The last byte of S1 will be shared with S2 */
-		S2--;
-	}
-
-	hmac_md5_vector(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], A_MD5);
-	hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1);
-
-	MD5_pos = MD5_MAC_LEN;
-	SHA1_pos = SHA1_MAC_LEN;
-	for (i = 0; i < outlen; i++) {
-		if (MD5_pos == MD5_MAC_LEN) {
-			hmac_md5_vector(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5);
-			MD5_pos = 0;
-			hmac_md5(S1, L_S1, A_MD5, MD5_MAC_LEN, A_MD5);
-		}
-		if (SHA1_pos == SHA1_MAC_LEN) {
-			hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len,
-					 P_SHA1);
-			SHA1_pos = 0;
-			hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1);
-		}
-
-		out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos];
-
-		MD5_pos++;
-		SHA1_pos++;
-	}
 
 	return 0;
 }
-#endif /* CONFIG_NO_TLS_PRF */
-
-
-#ifndef CONFIG_NO_PBKDF2
-
-static void pbkdf2_sha1_f(const char *passphrase, const char *ssid,
-			  size_t ssid_len, int iterations, unsigned int count,
-			  u8 *digest)
-{
-	unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN];
-	int i, j;
-	unsigned char count_buf[4];
-	const u8 *addr[2];
-	size_t len[2];
-	size_t passphrase_len = os_strlen(passphrase);
-
-	addr[0] = (u8 *) ssid;
-	len[0] = ssid_len;
-	addr[1] = count_buf;
-	len[1] = 4;
-
-	/* F(P, S, c, i) = U1 xor U2 xor ... Uc
-	 * U1 = PRF(P, S || i)
-	 * U2 = PRF(P, U1)
-	 * Uc = PRF(P, Uc-1)
-	 */
-
-	count_buf[0] = (count >> 24) & 0xff;
-	count_buf[1] = (count >> 16) & 0xff;
-	count_buf[2] = (count >> 8) & 0xff;
-	count_buf[3] = count & 0xff;
-	hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, tmp);
-	os_memcpy(digest, tmp, SHA1_MAC_LEN);
-
-	for (i = 1; i < iterations; i++) {
-		hmac_sha1((u8 *) passphrase, passphrase_len, tmp, SHA1_MAC_LEN,
-			  tmp2);
-		os_memcpy(tmp, tmp2, SHA1_MAC_LEN);
-		for (j = 0; j < SHA1_MAC_LEN; j++)
-			digest[j] ^= tmp2[j];
-	}
-}
-
-
-/**
- * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i
- * @passphrase: ASCII passphrase
- * @ssid: SSID
- * @ssid_len: SSID length in bytes
- * @iterations: Number of iterations to run
- * @buf: Buffer for the generated key
- * @buflen: Length of the buffer in bytes
- *
- * This function is used to derive PSK for WPA-PSK. For this protocol,
- * iterations is set to 4096 and buflen to 32. This function is described in
- * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0.
- */
-void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
-		 int iterations, u8 *buf, size_t buflen)
-{
-	unsigned int count = 0;
-	unsigned char *pos = buf;
-	size_t left = buflen, plen;
-	unsigned char digest[SHA1_MAC_LEN];
-
-	while (left > 0) {
-		count++;
-		pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count,
-			      digest);
-		plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left;
-		os_memcpy(pos, digest, plen);
-		pos += plen;
-		left -= plen;
-	}
-}
-
-#endif /* CONFIG_NO_PBKDF2 */
-
-
-#ifdef INTERNAL_SHA1
-
-struct SHA1Context {
-	u32 state[5];
-	u32 count[2];
-	unsigned char buffer[64];
-};
-
-typedef struct SHA1Context SHA1_CTX;
-
-#ifndef CONFIG_CRYPTO_INTERNAL
-static void SHA1Init(struct SHA1Context *context);
-static void SHA1Update(struct SHA1Context *context, const void *data, u32 len);
-static void SHA1Final(unsigned char digest[20], struct SHA1Context *context);
-#endif /* CONFIG_CRYPTO_INTERNAL */
-static void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
-
-
-/**
- * sha1_vector - SHA-1 hash for data vector
- * @num_elem: Number of elements in the data vector
- * @addr: Pointers to the data areas
- * @len: Lengths of the data blocks
- * @mac: Buffer for the hash
- */
-void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
-		 u8 *mac)
-{
-	SHA1_CTX ctx;
-	size_t i;
-
-	SHA1Init(&ctx);
-	for (i = 0; i < num_elem; i++)
-		SHA1Update(&ctx, addr[i], len[i]);
-	SHA1Final(mac, &ctx);
-}
-
-
-#ifndef CONFIG_NO_FIPS186_2_PRF
-int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
-{
-	u8 xkey[64];
-	u32 t[5], _t[5];
-	int i, j, m, k;
-	u8 *xpos = x;
-	u32 carry;
-
-	if (seed_len > sizeof(xkey))
-		seed_len = sizeof(xkey);
-
-	/* FIPS 186-2 + change notice 1 */
-
-	os_memcpy(xkey, seed, seed_len);
-	os_memset(xkey + seed_len, 0, 64 - seed_len);
-	t[0] = 0x67452301;
-	t[1] = 0xEFCDAB89;
-	t[2] = 0x98BADCFE;
-	t[3] = 0x10325476;
-	t[4] = 0xC3D2E1F0;
-
-	m = xlen / 40;
-	for (j = 0; j < m; j++) {
-		/* XSEED_j = 0 */
-		for (i = 0; i < 2; i++) {
-			/* XVAL = (XKEY + XSEED_j) mod 2^b */
-
-			/* w_i = G(t, XVAL) */
-			os_memcpy(_t, t, 20);
-			SHA1Transform(_t, xkey);
-			_t[0] = host_to_be32(_t[0]);
-			_t[1] = host_to_be32(_t[1]);
-			_t[2] = host_to_be32(_t[2]);
-			_t[3] = host_to_be32(_t[3]);
-			_t[4] = host_to_be32(_t[4]);
-			os_memcpy(xpos, _t, 20);
-
-			/* XKEY = (1 + XKEY + w_i) mod 2^b */
-			carry = 1;
-			for (k = 19; k >= 0; k--) {
-				carry += xkey[k] + xpos[k];
-				xkey[k] = carry & 0xff;
-				carry >>= 8;
-			}
-
-			xpos += SHA1_MAC_LEN;
-		}
-		/* x_j = w_0|w_1 */
-	}
-
-	return 0;
-}
-#endif /* CONFIG_NO_FIPS186_2_PRF */
-
-
-/* ===== start - public domain SHA1 implementation ===== */
-
-/*
-SHA-1 in C
-By Steve Reid 
-100% Public Domain
-
------------------
-Modified 7/98 
-By James H. Brown 
-Still 100% Public Domain
-
-Corrected a problem which generated improper hash values on 16 bit machines
-Routine SHA1Update changed from
-	void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
-len)
-to
-	void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
-long len)
-
-The 'len' parameter was declared an int which works fine on 32 bit machines.
-However, on 16 bit machines an int is too small for the shifts being done
-against
-it.  This caused the hash function to generate incorrect values if len was
-greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
-
-Since the file IO in main() reads 16K at a time, any file 8K or larger would
-be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
-"a"s).
-
-I also changed the declaration of variables i & j in SHA1Update to 
-unsigned long from unsigned int for the same reason.
-
-These changes should make no difference to any 32 bit implementations since
-an
-int and a long are the same size in those environments.
-
---
-I also corrected a few compiler warnings generated by Borland C.
-1. Added #include  for exit() prototype
-2. Removed unused variable 'j' in SHA1Final
-3. Changed exit(0) to return(0) at end of main.
-
-ALL changes I made can be located by searching for comments containing 'JHB'
------------------
-Modified 8/98
-By Steve Reid 
-Still 100% public domain
-
-1- Removed #include  and used return() instead of exit()
-2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
-3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
-
------------------
-Modified 4/01
-By Saul Kravitz 
-Still 100% PD
-Modified to run on Compaq Alpha hardware.  
-
------------------
-Modified 4/01
-By Jouni Malinen 
-Minor changes to match the coding style used in Dynamics.
-
-Modified September 24, 2004
-By Jouni Malinen 
-Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
-
-*/
-
-/*
-Test Vectors (from FIPS PUB 180-1)
-"abc"
-  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
-  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-#define SHA1HANDSOFF
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-#ifndef WORDS_BIGENDIAN
-#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
-	(rol(block->l[i], 8) & 0x00FF00FF))
-#else
-#define blk0(i) block->l[i]
-#endif
-#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
-	block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) \
-	z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
-	w = rol(w, 30);
-#define R1(v,w,x,y,z,i) \
-	z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
-	w = rol(w, 30);
-#define R2(v,w,x,y,z,i) \
-	z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
-#define R3(v,w,x,y,z,i) \
-	z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
-	w = rol(w, 30);
-#define R4(v,w,x,y,z,i) \
-	z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
-	w=rol(w, 30);
-
-
-#ifdef VERBOSE  /* SAK */
-void SHAPrintContext(SHA1_CTX *context, char *msg)
-{
-	printf("%s (%d,%d) %x %x %x %x %x\n",
-	       msg,
-	       context->count[0], context->count[1], 
-	       context->state[0],
-	       context->state[1],
-	       context->state[2],
-	       context->state[3],
-	       context->state[4]);
-}
-#endif
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-static void SHA1Transform(u32 state[5], const unsigned char buffer[64])
-{
-	u32 a, b, c, d, e;
-	typedef union {
-		unsigned char c[64];
-		u32 l[16];
-	} CHAR64LONG16;
-	CHAR64LONG16* block;
-#ifdef SHA1HANDSOFF
-	CHAR64LONG16 workspace;
-	block = &workspace;
-	os_memcpy(block, buffer, 64);
-#else
-	block = (CHAR64LONG16 *) buffer;
-#endif
-	/* Copy context->state[] to working vars */
-	a = state[0];
-	b = state[1];
-	c = state[2];
-	d = state[3];
-	e = state[4];
-	/* 4 rounds of 20 operations each. Loop unrolled. */
-	R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-	R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-	R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-	R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-	R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-	R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-	R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-	R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-	R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-	R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-	R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-	R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-	R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-	R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-	R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-	R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-	R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-	R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-	R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-	R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-	/* Add the working vars back into context.state[] */
-	state[0] += a;
-	state[1] += b;
-	state[2] += c;
-	state[3] += d;
-	state[4] += e;
-	/* Wipe variables */
-	a = b = c = d = e = 0;
-#ifdef SHA1HANDSOFF
-	os_memset(block, 0, 64);
-#endif
-}
-
-
-/* SHA1Init - Initialize new context */
-
-void SHA1Init(SHA1_CTX* context)
-{
-	/* SHA1 initialization constants */
-	context->state[0] = 0x67452301;
-	context->state[1] = 0xEFCDAB89;
-	context->state[2] = 0x98BADCFE;
-	context->state[3] = 0x10325476;
-	context->state[4] = 0xC3D2E1F0;
-	context->count[0] = context->count[1] = 0;
-}
-
-
-/* Run your data through this. */
-
-void SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
-{
-	u32 i, j;
-	const unsigned char *data = _data;
-
-#ifdef VERBOSE
-	SHAPrintContext(context, "before");
-#endif
-	j = (context->count[0] >> 3) & 63;
-	if ((context->count[0] += len << 3) < (len << 3))
-		context->count[1]++;
-	context->count[1] += (len >> 29);
-	if ((j + len) > 63) {
-		os_memcpy(&context->buffer[j], data, (i = 64-j));
-		SHA1Transform(context->state, context->buffer);
-		for ( ; i + 63 < len; i += 64) {
-			SHA1Transform(context->state, &data[i]);
-		}
-		j = 0;
-	}
-	else i = 0;
-	os_memcpy(&context->buffer[j], &data[i], len - i);
-#ifdef VERBOSE
-	SHAPrintContext(context, "after ");
-#endif
-}
-
-
-/* Add padding and return the message digest. */
-
-void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
-{
-	u32 i;
-	unsigned char finalcount[8];
-
-	for (i = 0; i < 8; i++) {
-		finalcount[i] = (unsigned char)
-			((context->count[(i >= 4 ? 0 : 1)] >>
-			  ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
-	}
-	SHA1Update(context, (unsigned char *) "\200", 1);
-	while ((context->count[0] & 504) != 448) {
-		SHA1Update(context, (unsigned char *) "\0", 1);
-	}
-	SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform()
-					      */
-	for (i = 0; i < 20; i++) {
-		digest[i] = (unsigned char)
-			((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
-			 255);
-	}
-	/* Wipe variables */
-	i = 0;
-	os_memset(context->buffer, 0, 64);
-	os_memset(context->state, 0, 20);
-	os_memset(context->count, 0, 8);
-	os_memset(finalcount, 0, 8);
-}
-
-/* ===== end - public domain SHA1 implementation ===== */
-
-#endif /* INTERNAL_SHA1 */
diff --git a/contrib/wpa/src/crypto/sha1.h b/contrib/wpa/src/crypto/sha1.h
index 9c365e2677bb..c1a6233bb0fb 100644
--- a/contrib/wpa/src/crypto/sha1.h
+++ b/contrib/wpa/src/crypto/sha1.h
@@ -1,6 +1,6 @@
 /*
  * SHA1 hash implementation and interface functions
- * Copyright (c) 2003-2005, Jouni Malinen 
+ * Copyright (c) 2003-2009, Jouni Malinen 
  *
  * 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
@@ -17,26 +17,17 @@
 
 #define SHA1_MAC_LEN 20
 
-void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
-		      const u8 *addr[], const size_t *len, u8 *mac);
-void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
+		     const u8 *addr[], const size_t *len, u8 *mac);
+int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
 	       u8 *mac);
-void sha1_prf(const u8 *key, size_t key_len, const char *label,
-	      const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
-void sha1_t_prf(const u8 *key, size_t key_len, const char *label,
-		const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len);
+int sha1_prf(const u8 *key, size_t key_len, const char *label,
+	     const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
+int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
+	       const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len);
 int __must_check tls_prf(const u8 *secret, size_t secret_len,
 			 const char *label, const u8 *seed, size_t seed_len,
 			 u8 *out, size_t outlen);
-void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
-		 int iterations, u8 *buf, size_t buflen);
-
-#ifdef CONFIG_CRYPTO_INTERNAL
-struct SHA1Context;
-
-void SHA1Init(struct SHA1Context *context);
-void SHA1Update(struct SHA1Context *context, const void *data, u32 len);
-void SHA1Final(unsigned char digest[20], struct SHA1Context *context);
-#endif /* CONFIG_CRYPTO_INTERNAL */
-
+int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
+		int iterations, u8 *buf, size_t buflen);
 #endif /* SHA1_H */
diff --git a/contrib/wpa/src/crypto/sha1_i.h b/contrib/wpa/src/crypto/sha1_i.h
new file mode 100644
index 000000000000..ec2f82f75b96
--- /dev/null
+++ b/contrib/wpa/src/crypto/sha1_i.h
@@ -0,0 +1,29 @@
+/*
+ * SHA1 internal definitions
+ * Copyright (c) 2003-2005, Jouni Malinen 
+ *
+ * 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 SHA1_I_H
+#define SHA1_I_H
+
+struct SHA1Context {
+	u32 state[5];
+	u32 count[2];
+	unsigned char buffer[64];
+};
+
+void SHA1Init(struct SHA1Context *context);
+void SHA1Update(struct SHA1Context *context, const void *data, u32 len);
+void SHA1Final(unsigned char digest[20], struct SHA1Context *context);
+void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
+
+#endif /* SHA1_I_H */
diff --git a/contrib/wpa/src/crypto/sha256-internal.c b/contrib/wpa/src/crypto/sha256-internal.c
new file mode 100644
index 000000000000..b0613739fbc6
--- /dev/null
+++ b/contrib/wpa/src/crypto/sha256-internal.c
@@ -0,0 +1,243 @@
+/*
+ * SHA-256 hash implementation and interface functions
+ * Copyright (c) 2003-2007, Jouni Malinen 
+ *
+ * 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 "sha256.h"
+#include "crypto.h"
+
+struct sha256_state {
+	u64 length;
+	u32 state[8], curlen;
+	u8 buf[64];
+};
+
+static void sha256_init(struct sha256_state *md);
+static int sha256_process(struct sha256_state *md, const unsigned char *in,
+			  unsigned long inlen);
+static int sha256_done(struct sha256_state *md, unsigned char *out);
+
+
+/**
+ * sha256_vector - SHA256 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 of failure
+ */
+int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+		  u8 *mac)
+{
+	struct sha256_state ctx;
+	size_t i;
+
+	sha256_init(&ctx);
+	for (i = 0; i < num_elem; i++)
+		if (sha256_process(&ctx, addr[i], len[i]))
+			return -1;
+	if (sha256_done(&ctx, mac))
+		return -1;
+	return 0;
+}
+
+
+/* ===== start - public domain SHA256 implementation ===== */
+
+/* This is based on SHA256 implementation in LibTomCrypt that was released into
+ * public domain by Tom St Denis. */
+
+/* the K array */
+static const unsigned long K[64] = {
+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+	0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+	0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+	0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+	0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+	0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+	0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+	0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+	0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+	0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+
+/* Various logical functions */
+#define RORc(x, y) \
+( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
+   ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
+#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
+#define Maj(x,y,z)      (((x | y) & z) | (x & y)) 
+#define S(x, n)         RORc((x), (n))
+#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+#ifndef MIN
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#endif
+
+/* compress 512-bits */
+static int sha256_compress(struct sha256_state *md, unsigned char *buf)
+{
+	u32 S[8], W[64], t0, t1;
+	u32 t;
+	int i;
+
+	/* copy state into S */
+	for (i = 0; i < 8; i++) {
+		S[i] = md->state[i];
+	}
+
+	/* copy the state into 512-bits into W[0..15] */
+	for (i = 0; i < 16; i++)
+		W[i] = WPA_GET_BE32(buf + (4 * i));
+
+	/* fill W[16..63] */
+	for (i = 16; i < 64; i++) {
+		W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
+			W[i - 16];
+	}        
+
+	/* Compress */
+#define RND(a,b,c,d,e,f,g,h,i)                          \
+	t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];	\
+	t1 = Sigma0(a) + Maj(a, b, c);			\
+	d += t0;					\
+	h  = t0 + t1;
+
+	for (i = 0; i < 64; ++i) {
+		RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
+		t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; 
+		S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
+	}
+
+	/* feedback */
+	for (i = 0; i < 8; i++) {
+		md->state[i] = md->state[i] + S[i];
+	}
+	return 0;
+}
+
+
+/* Initialize the hash state */
+static void sha256_init(struct sha256_state *md)
+{
+	md->curlen = 0;
+	md->length = 0;
+	md->state[0] = 0x6A09E667UL;
+	md->state[1] = 0xBB67AE85UL;
+	md->state[2] = 0x3C6EF372UL;
+	md->state[3] = 0xA54FF53AUL;
+	md->state[4] = 0x510E527FUL;
+	md->state[5] = 0x9B05688CUL;
+	md->state[6] = 0x1F83D9ABUL;
+	md->state[7] = 0x5BE0CD19UL;
+}
+
+/**
+   Process a block of memory though the hash
+   @param md     The hash state
+   @param in     The data to hash
+   @param inlen  The length of the data (octets)
+   @return CRYPT_OK if successful
+*/
+static int sha256_process(struct sha256_state *md, const unsigned char *in,
+			  unsigned long inlen)
+{
+	unsigned long n;
+#define block_size 64
+
+	if (md->curlen > sizeof(md->buf))
+		return -1;
+
+	while (inlen > 0) {
+		if (md->curlen == 0 && inlen >= block_size) {
+			if (sha256_compress(md, (unsigned char *) in) < 0)
+				return -1;
+			md->length += block_size * 8;
+			in += block_size;
+			inlen -= block_size;
+		} else {
+			n = MIN(inlen, (block_size - md->curlen));
+			os_memcpy(md->buf + md->curlen, in, n);
+			md->curlen += n;
+			in += n;
+			inlen -= n;
+			if (md->curlen == block_size) {
+				if (sha256_compress(md, md->buf) < 0)
+					return -1;
+				md->length += 8 * block_size;
+				md->curlen = 0;
+			}
+		}
+	}
+
+	return 0;
+}
+
+
+/**
+   Terminate the hash to get the digest
+   @param md  The hash state
+   @param out [out] The destination of the hash (32 bytes)
+   @return CRYPT_OK if successful
+*/
+static int sha256_done(struct sha256_state *md, unsigned char *out)
+{
+	int i;
+
+	if (md->curlen >= sizeof(md->buf))
+		return -1;
+
+	/* increase the length of the message */
+	md->length += md->curlen * 8;
+
+	/* append the '1' bit */
+	md->buf[md->curlen++] = (unsigned char) 0x80;
+
+	/* if the length is currently above 56 bytes we append zeros
+	 * then compress.  Then we can fall back to padding zeros and length
+	 * encoding like normal.
+	 */
+	if (md->curlen > 56) {
+		while (md->curlen < 64) {
+			md->buf[md->curlen++] = (unsigned char) 0;
+		}
+		sha256_compress(md, md->buf);
+		md->curlen = 0;
+	}
+
+	/* pad upto 56 bytes of zeroes */
+	while (md->curlen < 56) {
+		md->buf[md->curlen++] = (unsigned char) 0;
+	}
+
+	/* store length */
+	WPA_PUT_BE64(md->buf + 56, md->length);
+	sha256_compress(md, md->buf);
+
+	/* copy output */
+	for (i = 0; i < 8; i++)
+		WPA_PUT_BE32(out + (4 * i), md->state[i]);
+
+	return 0;
+}
+
+/* ===== end - public domain SHA256 implementation ===== */
diff --git a/contrib/wpa/src/crypto/sha256.c b/contrib/wpa/src/crypto/sha256.c
index 96dac0ea7159..7f320f9bfea5 100644
--- a/contrib/wpa/src/crypto/sha256.c
+++ b/contrib/wpa/src/crypto/sha256.c
@@ -155,228 +155,3 @@ void sha256_prf(const u8 *key, size_t key_len, const char *label,
 		counter++;
 	}
 }
-
-
-#ifdef INTERNAL_SHA256
-
-struct sha256_state {
-	u64 length;
-	u32 state[8], curlen;
-	u8 buf[64];
-};
-
-static void sha256_init(struct sha256_state *md);
-static int sha256_process(struct sha256_state *md, const unsigned char *in,
-			  unsigned long inlen);
-static int sha256_done(struct sha256_state *md, unsigned char *out);
-
-
-/**
- * sha256_vector - SHA256 hash for data vector
- * @num_elem: Number of elements in the data vector
- * @addr: Pointers to the data areas
- * @len: Lengths of the data blocks
- * @mac: Buffer for the hash
- */
-void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
-		 u8 *mac)
-{
-	struct sha256_state ctx;
-	size_t i;
-
-	sha256_init(&ctx);
-	for (i = 0; i < num_elem; i++)
-		sha256_process(&ctx, addr[i], len[i]);
-	sha256_done(&ctx, mac);
-}
-
-
-/* ===== start - public domain SHA256 implementation ===== */
-
-/* This is based on SHA256 implementation in LibTomCrypt that was released into
- * public domain by Tom St Denis. */
-
-/* the K array */
-static const unsigned long K[64] = {
-	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
-	0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
-	0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
-	0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
-	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
-	0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
-	0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
-	0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
-	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
-	0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
-	0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
-	0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
-	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
-};
-
-
-/* Various logical functions */
-#define RORc(x, y) \
-( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
-   ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
-#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
-#define Maj(x,y,z)      (((x | y) & z) | (x & y)) 
-#define S(x, n)         RORc((x), (n))
-#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
-#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
-#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
-#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
-#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
-#ifndef MIN
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-#endif
-
-/* compress 512-bits */
-static int sha256_compress(struct sha256_state *md, unsigned char *buf)
-{
-	u32 S[8], W[64], t0, t1;
-	u32 t;
-	int i;
-
-	/* copy state into S */
-	for (i = 0; i < 8; i++) {
-		S[i] = md->state[i];
-	}
-
-	/* copy the state into 512-bits into W[0..15] */
-	for (i = 0; i < 16; i++)
-		W[i] = WPA_GET_BE32(buf + (4 * i));
-
-	/* fill W[16..63] */
-	for (i = 16; i < 64; i++) {
-		W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
-			W[i - 16];
-	}        
-
-	/* Compress */
-#define RND(a,b,c,d,e,f,g,h,i)                          \
-	t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];	\
-	t1 = Sigma0(a) + Maj(a, b, c);			\
-	d += t0;					\
-	h  = t0 + t1;
-
-	for (i = 0; i < 64; ++i) {
-		RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
-		t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; 
-		S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
-	}
-
-	/* feedback */
-	for (i = 0; i < 8; i++) {
-		md->state[i] = md->state[i] + S[i];
-	}
-	return 0;
-}
-
-
-/* Initialize the hash state */
-static void sha256_init(struct sha256_state *md)
-{
-	md->curlen = 0;
-	md->length = 0;
-	md->state[0] = 0x6A09E667UL;
-	md->state[1] = 0xBB67AE85UL;
-	md->state[2] = 0x3C6EF372UL;
-	md->state[3] = 0xA54FF53AUL;
-	md->state[4] = 0x510E527FUL;
-	md->state[5] = 0x9B05688CUL;
-	md->state[6] = 0x1F83D9ABUL;
-	md->state[7] = 0x5BE0CD19UL;
-}
-
-/**
-   Process a block of memory though the hash
-   @param md     The hash state
-   @param in     The data to hash
-   @param inlen  The length of the data (octets)
-   @return CRYPT_OK if successful
-*/
-static int sha256_process(struct sha256_state *md, const unsigned char *in,
-			  unsigned long inlen)
-{
-	unsigned long n;
-#define block_size 64
-
-	if (md->curlen > sizeof(md->buf))
-		return -1;
-
-	while (inlen > 0) {
-		if (md->curlen == 0 && inlen >= block_size) {
-			if (sha256_compress(md, (unsigned char *) in) < 0)
-				return -1;
-			md->length += block_size * 8;
-			in += block_size;
-			inlen -= block_size;
-		} else {
-			n = MIN(inlen, (block_size - md->curlen));
-			os_memcpy(md->buf + md->curlen, in, n);
-			md->curlen += n;
-			in += n;
-			inlen -= n;
-			if (md->curlen == block_size) {
-				if (sha256_compress(md, md->buf) < 0)
-					return -1;
-				md->length += 8 * block_size;
-				md->curlen = 0;
-			}
-		}
-	}
-
-	return 0;
-}
-
-
-/**
-   Terminate the hash to get the digest
-   @param md  The hash state
-   @param out [out] The destination of the hash (32 bytes)
-   @return CRYPT_OK if successful
-*/
-static int sha256_done(struct sha256_state *md, unsigned char *out)
-{
-	int i;
-
-	if (md->curlen >= sizeof(md->buf))
-		return -1;
-
-	/* increase the length of the message */
-	md->length += md->curlen * 8;
-
-	/* append the '1' bit */
-	md->buf[md->curlen++] = (unsigned char) 0x80;
-
-	/* if the length is currently above 56 bytes we append zeros
-	 * then compress.  Then we can fall back to padding zeros and length
-	 * encoding like normal.
-	 */
-	if (md->curlen > 56) {
-		while (md->curlen < 64) {
-			md->buf[md->curlen++] = (unsigned char) 0;
-		}
-		sha256_compress(md, md->buf);
-		md->curlen = 0;
-	}
-
-	/* pad upto 56 bytes of zeroes */
-	while (md->curlen < 56) {
-		md->buf[md->curlen++] = (unsigned char) 0;
-	}
-
-	/* store length */
-	WPA_PUT_BE64(md->buf + 56, md->length);
-	sha256_compress(md, md->buf);
-
-	/* copy output */
-	for (i = 0; i < 8; i++)
-		WPA_PUT_BE32(out + (4 * i), md->state[i]);
-
-	return 0;
-}
-
-/* ===== end - public domain SHA256 implementation ===== */
-
-#endif /* INTERNAL_SHA256 */
diff --git a/contrib/wpa/src/crypto/tls.h b/contrib/wpa/src/crypto/tls.h
index aafb79999320..0928b5ba43b7 100644
--- a/contrib/wpa/src/crypto/tls.h
+++ b/contrib/wpa/src/crypto/tls.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / SSL/TLS interface definition
- * Copyright (c) 2004-2007, Jouni Malinen 
+ * SSL/TLS interface definition
+ * Copyright (c) 2004-2010, Jouni Malinen 
  *
  * 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
@@ -28,10 +28,54 @@ struct tls_keys {
 	size_t inner_secret_len;
 };
 
+enum tls_event {
+	TLS_CERT_CHAIN_FAILURE,
+	TLS_PEER_CERTIFICATE
+};
+
+/*
+ * Note: These are used as identifier with external programs and as such, the
+ * values must not be changed.
+ */
+enum tls_fail_reason {
+	TLS_FAIL_UNSPECIFIED = 0,
+	TLS_FAIL_UNTRUSTED = 1,
+	TLS_FAIL_REVOKED = 2,
+	TLS_FAIL_NOT_YET_VALID = 3,
+	TLS_FAIL_EXPIRED = 4,
+	TLS_FAIL_SUBJECT_MISMATCH = 5,
+	TLS_FAIL_ALTSUBJECT_MISMATCH = 6,
+	TLS_FAIL_BAD_CERTIFICATE = 7,
+	TLS_FAIL_SERVER_CHAIN_PROBE = 8
+};
+
+union tls_event_data {
+	struct {
+		int depth;
+		const char *subject;
+		enum tls_fail_reason reason;
+		const char *reason_txt;
+		const struct wpabuf *cert;
+	} cert_fail;
+
+	struct {
+		int depth;
+		const char *subject;
+		const struct wpabuf *cert;
+		const u8 *hash;
+		size_t hash_len;
+	} peer_cert;
+};
+
 struct tls_config {
 	const char *opensc_engine_path;
 	const char *pkcs11_engine_path;
 	const char *pkcs11_module_path;
+	int fips_mode;
+
+	void (*event_cb)(void *ctx, enum tls_event ev,
+			 union tls_event_data *data);
+	void *cb_ctx;
 };
 
 #define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0)
@@ -292,17 +336,14 @@ int __must_check  tls_connection_prf(void *tls_ctx,
  * tls_connection_handshake - Process TLS handshake (client side)
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- * @in_data: Input data from TLS peer
- * @in_len: Input data length
- * @out_len: Length of the output buffer.
+ * @in_data: Input data from TLS server
  * @appl_data: Pointer to application data pointer, or %NULL if dropped
- * @appl_data_len: Pointer to variable that is set to appl_data length
- * Returns: Pointer to output data, %NULL on failure
+ * Returns: Output data, %NULL on failure
  *
- * Caller is responsible for freeing returned output data. If the final
+ * The caller is responsible for freeing the returned output data. If the final
  * handshake message includes application data, this is decrypted and
- * appl_data (if not %NULL) is set to point this data. Caller is responsible
- * for freeing appl_data.
+ * appl_data (if not %NULL) is set to point this data. The caller is
+ * responsible for freeing appl_data.
  *
  * This function is used during TLS handshake. The first call is done with
  * in_data == %NULL and the library is expected to return ClientHello packet.
@@ -318,62 +359,55 @@ int __must_check  tls_connection_prf(void *tls_ctx,
  * tls_connection_established() should return 1 once the TLS handshake has been
  * completed successfully.
  */
-u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
-			      const u8 *in_data, size_t in_len,
-			      size_t *out_len, u8 **appl_data,
-			      size_t *appl_data_len);
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+					 struct tls_connection *conn,
+					 const struct wpabuf *in_data,
+					 struct wpabuf **appl_data);
 
 /**
  * tls_connection_server_handshake - Process TLS handshake (server side)
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
  * @in_data: Input data from TLS peer
- * @in_len: Input data length
- * @out_len: Length of the output buffer.
- * Returns: pointer to output data, %NULL on failure
+ * @appl_data: Pointer to application data pointer, or %NULL if dropped
+ * Returns: Output data, %NULL on failure
  *
- * Caller is responsible for freeing returned output data.
+ * The caller is responsible for freeing the returned output data.
  */
-u8 * tls_connection_server_handshake(void *tls_ctx,
-				     struct tls_connection *conn,
-				     const u8 *in_data, size_t in_len,
-				     size_t *out_len);
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+						struct tls_connection *conn,
+						const struct wpabuf *in_data,
+						struct wpabuf **appl_data);
 
 /**
  * tls_connection_encrypt - Encrypt data into TLS tunnel
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- * @in_data: Pointer to plaintext data to be encrypted
- * @in_len: Input buffer length
- * @out_data: Pointer to output buffer (encrypted TLS data)
- * @out_len: Maximum out_data length 
- * Returns: Number of bytes written to out_data, -1 on failure
+ * @in_data: Plaintext data to be encrypted
+ * Returns: Encrypted TLS data or %NULL on failure
  *
  * This function is used after TLS handshake has been completed successfully to
- * send data in the encrypted tunnel.
+ * send data in the encrypted tunnel. The caller is responsible for freeing the
+ * returned output data.
  */
-int __must_check tls_connection_encrypt(void *tls_ctx,
-					struct tls_connection *conn,
-					const u8 *in_data, size_t in_len,
-					u8 *out_data, size_t out_len);
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data);
 
 /**
  * tls_connection_decrypt - Decrypt data from TLS tunnel
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
- * @in_data: Pointer to input buffer (encrypted TLS data)
- * @in_len: Input buffer length
- * @out_data: Pointer to output buffer (decrypted data from TLS tunnel)
- * @out_len: Maximum out_data length
- * Returns: Number of bytes written to out_data, -1 on failure
+ * @in_data: Encrypted TLS data
+ * Returns: Decrypted TLS data or %NULL on failure
  *
  * This function is used after TLS handshake has been completed successfully to
- * receive data from the encrypted tunnel.
+ * receive data from the encrypted tunnel. The caller is responsible for
+ * freeing the returned output data.
  */
-int __must_check tls_connection_decrypt(void *tls_ctx,
-					struct tls_connection *conn,
-					const u8 *in_data, size_t in_len,
-					u8 *out_data, size_t out_len);
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data);
 
 /**
  * tls_connection_resumed - Was session resumption used
@@ -493,16 +527,13 @@ unsigned int tls_capabilities(void *tls_ctx);
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
  * @final: 1 = FinalPhaseFinished, 0 = IntermediatePhaseFinished
- * @out_data: Pointer to output buffer (encrypted TLS/IA data)
- * @out_len: Maximum out_data length 
- * Returns: Number of bytes written to out_data on success, -1 on failure
+ * Returns: Encrypted TLS/IA data, %NULL on failure
  *
  * This function is used to send the TLS/IA end phase message, e.g., when the
  * EAP server completes EAP-TTLSv1.
  */
-int __must_check tls_connection_ia_send_phase_finished(
-	void *tls_ctx, struct tls_connection *conn, int final,
-	u8 *out_data, size_t out_len);
+struct wpabuf * tls_connection_ia_send_phase_finished(
+	void *tls_ctx, struct tls_connection *conn, int final);
 
 /**
  * tls_connection_ia_final_phase_finished - Has final phase been completed
diff --git a/contrib/wpa/src/crypto/tls_gnutls.c b/contrib/wpa/src/crypto/tls_gnutls.c
index 2c5c5a2b6406..c3a7358c0e77 100644
--- a/contrib/wpa/src/crypto/tls_gnutls.c
+++ b/contrib/wpa/src/crypto/tls_gnutls.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / SSL/TLS interface functions for openssl
- * Copyright (c) 2004-2007, Jouni Malinen 
+ * SSL/TLS interface functions for GnuTLS
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -112,8 +112,9 @@ struct tls_connection {
 	int established;
 	int verify_peer;
 
-	u8 *push_buf, *pull_buf, *pull_buf_offset;
-	size_t push_buf_len, pull_buf_len;
+	struct wpabuf *push_buf;
+	struct wpabuf *pull_buf;
+	const u8 *pull_buf_offset;
 
 	int params_set;
 	gnutls_certificate_credentials_t xcred;
@@ -241,22 +242,22 @@ static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf,
 			     size_t len)
 {
 	struct tls_connection *conn = (struct tls_connection *) ptr;
-	u8 *end;
+	const u8 *end;
 	if (conn->pull_buf == NULL) {
 		errno = EWOULDBLOCK;
 		return -1;
 	}
 
-	end = conn->pull_buf + conn->pull_buf_len;
+	end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf);
 	if ((size_t) (end - conn->pull_buf_offset) < len)
 		len = end - conn->pull_buf_offset;
 	os_memcpy(buf, conn->pull_buf_offset, len);
 	conn->pull_buf_offset += len;
 	if (conn->pull_buf_offset == end) {
 		wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
-		os_free(conn->pull_buf);
-		conn->pull_buf = conn->pull_buf_offset = NULL;
-		conn->pull_buf_len = 0;
+		wpabuf_free(conn->pull_buf);
+		conn->pull_buf = NULL;
+		conn->pull_buf_offset = NULL;
 	} else {
 		wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
 			   __func__,
@@ -270,16 +271,12 @@ static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf,
 			     size_t len)
 {
 	struct tls_connection *conn = (struct tls_connection *) ptr;
-	u8 *nbuf;
 
-	nbuf = os_realloc(conn->push_buf, conn->push_buf_len + len);
-	if (nbuf == NULL) {
+	if (wpabuf_resize(&conn->push_buf, len) < 0) {
 		errno = ENOMEM;
 		return -1;
 	}
-	os_memcpy(nbuf + conn->push_buf_len, buf, len);
-	conn->push_buf = nbuf;
-	conn->push_buf_len += len;
+	wpabuf_put_data(conn->push_buf, buf, len);
 
 	return len;
 }
@@ -383,8 +380,8 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
 	os_free(conn->pre_shared_secret);
 	os_free(conn->subject_match);
 	os_free(conn->altsubject_match);
-	os_free(conn->push_buf);
-	os_free(conn->pull_buf);
+	wpabuf_free(conn->push_buf);
+	wpabuf_free(conn->pull_buf);
 	os_free(conn);
 }
 
@@ -407,9 +404,8 @@ int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
 	 * because the connection was already terminated in practice
 	 * and "close notify" shutdown alert would confuse AS. */
 	gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
-	os_free(conn->push_buf);
+	wpabuf_free(conn->push_buf);
 	conn->push_buf = NULL;
-	conn->push_buf_len = 0;
 	conn->established = 0;
 	conn->final_phase_finished = 0;
 #ifdef GNUTLS_IA
@@ -979,31 +975,56 @@ static int tls_connection_verify_peer(struct tls_connection *conn,
 }
 
 
-u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
-			      const u8 *in_data, size_t in_len,
-			      size_t *out_len, u8 **appl_data,
-			      size_t *appl_data_len)
+static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
 {
-	struct tls_global *global = ssl_ctx;
-	u8 *out_data;
+	int res;
+	struct wpabuf *ad;
+	wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
+	ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
+	if (ad == NULL)
+		return NULL;
+
+	res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
+				 wpabuf_size(ad));
+	wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
+	if (res < 0) {
+		wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
+			   "(%s)", __func__, (int) res,
+			   gnutls_strerror(res));
+		wpabuf_free(ad);
+		return NULL;
+	}
+
+	wpabuf_put(ad, res);
+	wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
+		   res);
+	return ad;
+}
+
+
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+					 struct tls_connection *conn,
+					 const struct wpabuf *in_data,
+					 struct wpabuf **appl_data)
+{
+	struct tls_global *global = tls_ctx;
+	struct wpabuf *out_data;
 	int ret;
 
 	if (appl_data)
 		*appl_data = NULL;
 
-	if (in_data && in_len) {
+	if (in_data && wpabuf_len(in_data) > 0) {
 		if (conn->pull_buf) {
 			wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
 				   "pull_buf", __func__,
-				   (unsigned long) conn->pull_buf_len);
-			os_free(conn->pull_buf);
+				   (unsigned long) wpabuf_len(conn->pull_buf));
+			wpabuf_free(conn->pull_buf);
 		}
-		conn->pull_buf = os_malloc(in_len);
+		conn->pull_buf = wpabuf_dup(in_data);
 		if (conn->pull_buf == NULL)
 			return NULL;
-		os_memcpy(conn->pull_buf, in_data, in_len);
-		conn->pull_buf_offset = conn->pull_buf;
-		conn->pull_buf_len = in_len;
+		conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
 	}
 
 	ret = gnutls_handshake(conn->session);
@@ -1014,7 +1035,7 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 			    conn->push_buf == NULL) {
 				/* Need to return something to trigger
 				 * completion of EAP-TLS. */
-				conn->push_buf = os_malloc(1);
+				conn->push_buf = wpabuf_alloc(0);
 			}
 			break;
 		case GNUTLS_E_FATAL_ALERT_RECEIVED:
@@ -1058,7 +1079,7 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 		conn->established = 1;
 		if (conn->push_buf == NULL) {
 			/* Need to return something to get final TLS ACK. */
-			conn->push_buf = os_malloc(1);
+			conn->push_buf = wpabuf_alloc(0);
 		}
 
 		gnutls_session_get_data(conn->session, NULL, &size);
@@ -1073,90 +1094,88 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 						global->session_data,
 						&global->session_data_size);
 		}
+
+		if (conn->pull_buf && appl_data)
+			*appl_data = gnutls_get_appl_data(conn);
 	}
 
 out:
 	out_data = conn->push_buf;
-	*out_len = conn->push_buf_len;
 	conn->push_buf = NULL;
-	conn->push_buf_len = 0;
 	return out_data;
 }
 
 
-u8 * tls_connection_server_handshake(void *ssl_ctx,
-				     struct tls_connection *conn,
-				     const u8 *in_data, size_t in_len,
-				     size_t *out_len)
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+						struct tls_connection *conn,
+						const struct wpabuf *in_data,
+						struct wpabuf **appl_data)
 {
-	return tls_connection_handshake(ssl_ctx, conn, in_data, in_len,
-					out_len, NULL, NULL);
+	return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
 }
 
 
-int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
-			   const u8 *in_data, size_t in_len,
-			   u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
 {
 	ssize_t res;
+	struct wpabuf *buf;
 
 #ifdef GNUTLS_IA
 	if (conn->tls_ia)
-		res = gnutls_ia_send(conn->session, (char *) in_data, in_len);
+		res = gnutls_ia_send(conn->session, wpabuf_head(in_data),
+				     wpabuf_len(in_data));
 	else
 #endif /* GNUTLS_IA */
-	res = gnutls_record_send(conn->session, in_data, in_len);
+	res = gnutls_record_send(conn->session, wpabuf_head(in_data),
+				 wpabuf_len(in_data));
 	if (res < 0) {
 		wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
 			   __func__, gnutls_strerror(res));
-		return -1;
+		return NULL;
 	}
-	if (conn->push_buf == NULL)
-		return -1;
-	if (conn->push_buf_len < out_len)
-		out_len = conn->push_buf_len;
-	else if (conn->push_buf_len > out_len) {
-		wpa_printf(MSG_INFO, "GnuTLS: Not enough buffer space for "
-			   "encrypted message (in_len=%lu push_buf_len=%lu "
-			   "out_len=%lu",
-			   (unsigned long) in_len,
-			   (unsigned long) conn->push_buf_len,
-			   (unsigned long) out_len);
-	}
-	os_memcpy(out_data, conn->push_buf, out_len);
-	os_free(conn->push_buf);
+
+	buf = conn->push_buf;
 	conn->push_buf = NULL;
-	conn->push_buf_len = 0;
-	return out_len;
+	return buf;
 }
 
 
-int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
-			   const u8 *in_data, size_t in_len,
-			   u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
 {
 	ssize_t res;
+	struct wpabuf *out;
 
 	if (conn->pull_buf) {
 		wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
 			   "pull_buf", __func__,
-			   (unsigned long) conn->pull_buf_len);
-		os_free(conn->pull_buf);
+			   (unsigned long) wpabuf_len(conn->pull_buf));
+		wpabuf_free(conn->pull_buf);
 	}
-	conn->pull_buf = os_malloc(in_len);
+	conn->pull_buf = wpabuf_dup(in_data);
 	if (conn->pull_buf == NULL)
-		return -1;
-	os_memcpy(conn->pull_buf, in_data, in_len);
-	conn->pull_buf_offset = conn->pull_buf;
-	conn->pull_buf_len = in_len;
+		return NULL;
+	conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
+
+	/*
+	 * Even though we try to disable TLS compression, it is possible that
+	 * this cannot be done with all TLS libraries. Add extra buffer space
+	 * to handle the possibility of the decrypted data being longer than
+	 * input data.
+	 */
+	out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
+	if (out == NULL)
+		return NULL;
 
 #ifdef GNUTLS_IA
 	if (conn->tls_ia) {
-		res = gnutls_ia_recv(conn->session, (char *) out_data,
-				     out_len);
-		if (out_len >= 12 &&
-		    (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
-		     res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) {
+		res = gnutls_ia_recv(conn->session, wpabuf_mhead(out),
+				     wpabuf_size(out));
+		if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
+		    res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) {
 			int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
 			wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
 				   __func__, final ? "Final" : "Intermediate");
@@ -1175,11 +1194,12 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
 				wpa_printf(MSG_DEBUG, "%s: Failed to permute "
 					   "inner secret: %s",
 					   __func__, gnutls_strerror(res));
-				return -1;
+				wpabuf_free(out);
+				return NULL;
 			}
 
 			res = gnutls_ia_verify_endphase(conn->session,
-							(char *) out_data);
+							wpabuf_head(out));
 			if (res == 0) {
 				wpa_printf(MSG_DEBUG, "%s: Correct endphase "
 					   "checksum", __func__);
@@ -1187,31 +1207,39 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
 				wpa_printf(MSG_INFO, "%s: Endphase "
 					   "verification failed: %s",
 					   __func__, gnutls_strerror(res));
-				return -1;
+				wpabuf_free(out);
+				return NULL;
 			}
 
 			if (final)
 				conn->final_phase_finished = 1;
 
-			return 0;
+			return out;
 		}
 
 		if (res < 0) {
 			wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d "
 				   "(%s)", __func__, (int) res,
 				   gnutls_strerror(res));
+			wpabuf_free(out);
+			return NULL;
 		}
-		return res;
+		wpabuf_put(out, res);
+		return out;
 	}
 #endif /* GNUTLS_IA */
 
-	res = gnutls_record_recv(conn->session, out_data, out_len);
+	res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
+				 wpabuf_size(out));
 	if (res < 0) {
 		wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
 			   "(%s)", __func__, (int) res, gnutls_strerror(res));
+		wpabuf_free(out);
+		return NULL;
 	}
+	wpabuf_put(out, res);
 
-	return res;
+	return out;
 }
 
 
@@ -1243,7 +1271,7 @@ int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
 int tls_connection_enable_workaround(void *ssl_ctx,
 				     struct tls_connection *conn)
 {
-	/* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */
+	gnutls_record_disable_padding(conn->session);
 	return 0;
 }
 
@@ -1338,16 +1366,15 @@ int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-int tls_connection_ia_send_phase_finished(void *tls_ctx,
-					  struct tls_connection *conn,
-					  int final,
-					  u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_ia_send_phase_finished(
+	void *tls_ctx, struct tls_connection *conn, int final)
 {
 #ifdef GNUTLS_IA
 	int ret;
+	struct wpabuf *buf;
 
 	if (conn == NULL || conn->session == NULL || !conn->tls_ia)
-		return -1;
+		return NULL;
 
 	ret = gnutls_ia_permute_inner_secret(conn->session,
 					     conn->session_keys_len,
@@ -1361,27 +1388,21 @@ int tls_connection_ia_send_phase_finished(void *tls_ctx,
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s",
 			   __func__, gnutls_strerror(ret));
-		return -1;
+		return NULL;
 	}
 
 	ret = gnutls_ia_endphase_send(conn->session, final);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s",
 			   __func__, gnutls_strerror(ret));
-		return -1;
+		return NULL;
 	}
 
-	if (conn->push_buf == NULL)
-		return -1;
-	if (conn->push_buf_len < out_len)
-		out_len = conn->push_buf_len;
-	os_memcpy(out_data, conn->push_buf, out_len);
-	os_free(conn->push_buf);
+	buf = conn->push_buf;
 	conn->push_buf = NULL;
-	conn->push_buf_len = 0;
-	return out_len;
+	return buf;
 #else /* GNUTLS_IA */
-	return -1;
+	return NULL;
 #endif /* GNUTLS_IA */
 }
 
@@ -1426,3 +1447,11 @@ int tls_connection_ia_permute_inner_secret(void *tls_ctx,
 	return -1;
 #endif /* GNUTLS_IA */
 }
+
+
+int tls_connection_set_session_ticket_cb(void *tls_ctx,
+					 struct tls_connection *conn,
+					 tls_session_ticket_cb cb, void *ctx)
+{
+	return -1;
+}
diff --git a/contrib/wpa/src/crypto/tls_internal.c b/contrib/wpa/src/crypto/tls_internal.c
index 42120c8a882e..64124d8a8e3e 100644
--- a/contrib/wpa/src/crypto/tls_internal.c
+++ b/contrib/wpa/src/crypto/tls_internal.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / TLS interface functions and an internal TLS implementation
- * Copyright (c) 2004-2007, Jouni Malinen 
+ * TLS interface functions and an internal TLS implementation
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -331,45 +331,77 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
-			      const u8 *in_data, size_t in_len,
-			      size_t *out_len, u8 **appl_data,
-			      size_t *appl_data_len)
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+					 struct tls_connection *conn,
+					 const struct wpabuf *in_data,
+					 struct wpabuf **appl_data)
 {
 #ifdef CONFIG_TLS_INTERNAL_CLIENT
+	u8 *res, *ad;
+	size_t res_len, ad_len;
+	struct wpabuf *out;
+
 	if (conn->client == NULL)
 		return NULL;
 
-	if (appl_data)
-		*appl_data = NULL;
+	ad = NULL;
+	res = tlsv1_client_handshake(conn->client,
+				     in_data ? wpabuf_head(in_data) : NULL,
+				     in_data ? wpabuf_len(in_data) : 0,
+				     &res_len, &ad, &ad_len);
+	if (res == NULL)
+		return NULL;
+	out = wpabuf_alloc_ext_data(res, res_len);
+	if (out == NULL) {
+		os_free(res);
+		os_free(ad);
+		return NULL;
+	}
+	if (appl_data) {
+		if (ad) {
+			*appl_data = wpabuf_alloc_ext_data(ad, ad_len);
+			if (*appl_data == NULL)
+				os_free(ad);
+		} else
+			*appl_data = NULL;
+	} else
+		os_free(ad);
 
-	wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)",
-		   __func__, in_data, (unsigned long) in_len);
-	return tlsv1_client_handshake(conn->client, in_data, in_len, out_len,
-				      appl_data, appl_data_len);
+	return out;
 #else /* CONFIG_TLS_INTERNAL_CLIENT */
 	return NULL;
 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
 }
 
 
-u8 * tls_connection_server_handshake(void *tls_ctx,
-				     struct tls_connection *conn,
-				     const u8 *in_data, size_t in_len,
-				     size_t *out_len)
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+						struct tls_connection *conn,
+						const struct wpabuf *in_data,
+						struct wpabuf **appl_data)
 {
 #ifdef CONFIG_TLS_INTERNAL_SERVER
-	u8 *out;
+	u8 *res;
+	size_t res_len;
+	struct wpabuf *out;
+
 	if (conn->server == NULL)
 		return NULL;
 
-	wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)",
-		   __func__, in_data, (unsigned long) in_len);
-	out = tlsv1_server_handshake(conn->server, in_data, in_len, out_len);
-	if (out == NULL && tlsv1_server_established(conn->server)) {
-		out = os_malloc(1);
-		*out_len = 0;
+	if (appl_data)
+		*appl_data = NULL;
+
+	res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
+				     wpabuf_len(in_data), &res_len);
+	if (res == NULL && tlsv1_server_established(conn->server))
+		return wpabuf_alloc(0);
+	if (res == NULL)
+		return NULL;
+	out = wpabuf_alloc_ext_data(res, res_len);
+	if (out == NULL) {
+		os_free(res);
+		return NULL;
 	}
+
 	return out;
 #else /* CONFIG_TLS_INTERNAL_SERVER */
 	return NULL;
@@ -377,43 +409,95 @@ u8 * tls_connection_server_handshake(void *tls_ctx,
 }
 
 
-int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
-			   const u8 *in_data, size_t in_len,
-			   u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
 {
 #ifdef CONFIG_TLS_INTERNAL_CLIENT
 	if (conn->client) {
-		return tlsv1_client_encrypt(conn->client, in_data, in_len,
-					    out_data, out_len);
+		struct wpabuf *buf;
+		int res;
+		buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
+		if (buf == NULL)
+			return NULL;
+		res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data),
+					   wpabuf_len(in_data),
+					   wpabuf_mhead(buf),
+					   wpabuf_size(buf));
+		if (res < 0) {
+			wpabuf_free(buf);
+			return NULL;
+		}
+		wpabuf_put(buf, res);
+		return buf;
 	}
 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
 #ifdef CONFIG_TLS_INTERNAL_SERVER
 	if (conn->server) {
-		return tlsv1_server_encrypt(conn->server, in_data, in_len,
-					    out_data, out_len);
+		struct wpabuf *buf;
+		int res;
+		buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
+		if (buf == NULL)
+			return NULL;
+		res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data),
+					   wpabuf_len(in_data),
+					   wpabuf_mhead(buf),
+					   wpabuf_size(buf));
+		if (res < 0) {
+			wpabuf_free(buf);
+			return NULL;
+		}
+		wpabuf_put(buf, res);
+		return buf;
 	}
 #endif /* CONFIG_TLS_INTERNAL_SERVER */
-	return -1;
+	return NULL;
 }
 
 
-int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
-			   const u8 *in_data, size_t in_len,
-			   u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
 {
 #ifdef CONFIG_TLS_INTERNAL_CLIENT
 	if (conn->client) {
-		return tlsv1_client_decrypt(conn->client, in_data, in_len,
-					    out_data, out_len);
+		struct wpabuf *buf;
+		int res;
+		buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
+		if (buf == NULL)
+			return NULL;
+		res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
+					   wpabuf_len(in_data),
+					   wpabuf_mhead(buf),
+					   wpabuf_size(buf));
+		if (res < 0) {
+			wpabuf_free(buf);
+			return NULL;
+		}
+		wpabuf_put(buf, res);
+		return buf;
 	}
 #endif /* CONFIG_TLS_INTERNAL_CLIENT */
 #ifdef CONFIG_TLS_INTERNAL_SERVER
 	if (conn->server) {
-		return tlsv1_server_decrypt(conn->server, in_data, in_len,
-					    out_data, out_len);
+		struct wpabuf *buf;
+		int res;
+		buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
+		if (buf == NULL)
+			return NULL;
+		res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data),
+					   wpabuf_len(in_data),
+					   wpabuf_mhead(buf),
+					   wpabuf_size(buf));
+		if (res < 0) {
+			wpabuf_free(buf);
+			return NULL;
+		}
+		wpabuf_put(buf, res);
+		return buf;
 	}
 #endif /* CONFIG_TLS_INTERNAL_SERVER */
-	return -1;
+	return NULL;
 }
 
 
@@ -524,12 +608,10 @@ unsigned int tls_capabilities(void *tls_ctx)
 }
 
 
-int tls_connection_ia_send_phase_finished(void *tls_ctx,
-					  struct tls_connection *conn,
-					  int final,
-					  u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_ia_send_phase_finished(
+	void *tls_ctx, struct tls_connection *conn, int final)
 {
-	return -1;
+	return NULL;
 }
 
 
diff --git a/contrib/wpa/src/crypto/tls_none.c b/contrib/wpa/src/crypto/tls_none.c
index f731628b0e38..0c836bb63187 100644
--- a/contrib/wpa/src/crypto/tls_none.c
+++ b/contrib/wpa/src/crypto/tls_none.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / SSL/TLS interface functions for no TLS case
- * Copyright (c) 2004, Jouni Malinen 
+ * SSL/TLS interface functions for no TLS case
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -22,13 +22,12 @@ void * tls_init(const struct tls_config *conf)
 	return (void *) 1;
 }
 
+
 void tls_deinit(void *ssl_ctx)
 {
 }
 
 
-#ifdef EAP_TLS_NONE
-
 int tls_get_errors(void *tls_ctx)
 {
 	return 0;
@@ -107,37 +106,37 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn,
-			      const u8 *in_data, size_t in_len,
-			      size_t *out_len, u8 **appl_data,
-			      size_t *appl_data_len)
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+					 struct tls_connection *conn,
+					 const struct wpabuf *in_data,
+					 struct wpabuf **appl_data)
 {
 	return NULL;
 }
 
 
-u8 * tls_connection_server_handshake(void *tls_ctx,
-				     struct tls_connection *conn,
-				     const u8 *in_data, size_t in_len,
-				     size_t *out_len)
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+						struct tls_connection *conn,
+						const struct wpabuf *in_data,
+						struct wpabuf **appl_data)
 {
 	return NULL;
 }
 
 
-int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn,
-			   const u8 *in_data, size_t in_len,
-			   u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
 {
-	return -1;
+	return NULL;
 }
 
 
-int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn,
-			   const u8 *in_data, size_t in_len,
-			   u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
 {
-	return -1;
+	return NULL;
 }
 
 
@@ -208,12 +207,10 @@ unsigned int tls_capabilities(void *tls_ctx)
 }
 
 
-int tls_connection_ia_send_phase_finished(void *tls_ctx,
-					  struct tls_connection *conn,
-					  int final,
-					  u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_ia_send_phase_finished(
+	void *tls_ctx, struct tls_connection *conn, int final)
 {
-	return -1;
+	return NULL;
 }
 
 
@@ -230,5 +227,3 @@ int tls_connection_ia_permute_inner_secret(void *tls_ctx,
 {
 	return -1;
 }
-
-#endif /* EAP_TLS_NONE */
diff --git a/contrib/wpa/src/crypto/tls_nss.c b/contrib/wpa/src/crypto/tls_nss.c
new file mode 100644
index 000000000000..ad834b649337
--- /dev/null
+++ b/contrib/wpa/src/crypto/tls_nss.c
@@ -0,0 +1,680 @@
+/*
+ * SSL/TLS interface functions for NSS
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "common.h"
+#include "tls.h"
+
+static int tls_nss_ref_count = 0;
+
+static PRDescIdentity nss_layer_id;
+
+
+struct tls_connection {
+	PRFileDesc *fd;
+
+	int established;
+	int verify_peer;
+	u8 *push_buf, *pull_buf, *pull_buf_offset;
+	size_t push_buf_len, pull_buf_len;
+};
+
+
+static PRStatus nss_io_close(PRFileDesc *fd)
+{
+	wpa_printf(MSG_DEBUG, "NSS: I/O close");
+	return PR_SUCCESS;
+}
+
+
+static PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+	wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount);
+	return PR_FAILURE;
+}
+
+
+static PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+	wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount);
+	return PR_FAILURE;
+}
+
+
+static PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov,
+			     PRInt32 iov_size, PRIntervalTime timeout)
+{
+	wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size);
+	return PR_FAILURE;
+}
+
+
+static PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
+			   PRIntn flags, PRIntervalTime timeout)
+{
+	struct tls_connection *conn = (struct tls_connection *) fd->secret;
+	u8 *end;
+
+	wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount);
+
+	if (conn->pull_buf == NULL) {
+		wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet");
+		return PR_FAILURE;
+	}
+
+	end = conn->pull_buf + conn->pull_buf_len;
+	if (end - conn->pull_buf_offset < amount)
+		amount = end - conn->pull_buf_offset;
+	os_memcpy(buf, conn->pull_buf_offset, amount);
+	conn->pull_buf_offset += amount;
+	if (conn->pull_buf_offset == end) {
+		wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
+		os_free(conn->pull_buf);
+		conn->pull_buf = conn->pull_buf_offset = NULL;
+		conn->pull_buf_len = 0;
+	} else {
+		wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
+			   __func__,
+			   (unsigned long) (end - conn->pull_buf_offset));
+	}
+	return amount;
+}
+
+
+static PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
+			   PRIntn flags, PRIntervalTime timeout)
+{
+	struct tls_connection *conn = (struct tls_connection *) fd->secret;
+	u8 *nbuf;
+
+	wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
+	wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount);
+
+	nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount);
+	if (nbuf == NULL) {
+		wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the "
+			   "data to be sent");
+		return PR_FAILURE;
+	}
+	os_memcpy(nbuf + conn->push_buf_len, buf, amount);
+	conn->push_buf = nbuf;
+	conn->push_buf_len += amount;
+
+	return amount;
+}
+
+
+static PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount,
+			       PRIntn flags, PRNetAddr *addr,
+			       PRIntervalTime timeout)
+{
+	wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
+	return PR_FAILURE;
+}
+
+
+static PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount,
+			     PRIntn flags, const PRNetAddr *addr,
+			     PRIntervalTime timeout)
+{
+	wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__);
+	return PR_FAILURE;
+}
+
+
+static PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr)
+{
+	wpa_printf(MSG_DEBUG, "NSS: I/O getpeername");
+
+	/*
+	 * It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a
+	 * fake IPv4 address to work around this even though we are not really
+	 * using TCP.
+	 */
+	os_memset(addr, 0, sizeof(*addr));
+	addr->inet.family = PR_AF_INET;
+
+	return PR_SUCCESS;
+}
+
+
+static PRStatus nss_io_getsocketoption(PRFileDesc *fd,
+				       PRSocketOptionData *data)
+{
+	switch (data->option) {
+	case PR_SockOpt_Nonblocking:
+		wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)");
+		data->value.non_blocking = PR_TRUE;
+		return PR_SUCCESS;
+	default:
+		wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)",
+			   data->option);
+		return PR_FAILURE;
+	}
+}
+
+
+static const PRIOMethods nss_io = {
+	PR_DESC_LAYERED,
+	nss_io_close,
+	nss_io_read,
+	nss_io_write,
+	NULL /* available */,
+	NULL /* available64 */,
+	NULL /* fsync */,
+	NULL /* fseek */,
+	NULL /* fseek64 */,
+	NULL /* fileinfo */,
+	NULL /* fileinfo64 */,
+	nss_io_writev,
+	NULL /* connect */,
+	NULL /* accept */,
+	NULL /* bind */,
+	NULL /* listen */,
+	NULL /* shutdown */,
+	nss_io_recv,
+	nss_io_send,
+	nss_io_recvfrom,
+	nss_io_sendto,
+	NULL /* poll */,
+	NULL /* acceptread */,
+	NULL /* transmitfile */,
+	NULL /* getsockname */,
+	nss_io_getpeername,
+	NULL /* reserved_fn_6 */,
+	NULL /* reserved_fn_5 */,
+	nss_io_getsocketoption,
+	NULL /* setsocketoption */,
+	NULL /* sendfile */,
+	NULL /* connectcontinue */,
+	NULL /* reserved_fn_3 */,
+	NULL /* reserved_fn_2 */,
+	NULL /* reserved_fn_1 */,
+	NULL /* reserved_fn_0 */
+};
+
+
+static char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+	wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__);
+	return NULL;
+}
+
+
+void * tls_init(const struct tls_config *conf)
+{
+	char *dir;
+
+	tls_nss_ref_count++;
+	if (tls_nss_ref_count > 1)
+		return (void *) 1;
+
+	PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+	nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant");
+
+	PK11_SetPasswordFunc(nss_password_cb);
+
+	dir = getenv("SSL_DIR");
+	if (dir) {
+		if (NSS_Init(dir) != SECSuccess) {
+			wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) "
+				   "failed", dir);
+			return NULL;
+		}
+	} else {
+		if (NSS_NoDB_Init(NULL) != SECSuccess) {
+			wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) "
+				   "failed");
+			return NULL;
+		}
+	}
+
+	if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) !=
+	    SECSuccess ||
+	    SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess ||
+	    SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess ||
+	    SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) {
+		wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed");
+		return NULL;
+	}
+
+	if (NSS_SetDomesticPolicy() != SECSuccess) {
+		wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed");
+		return NULL;
+	}
+
+	return (void *) 1;
+}
+
+void tls_deinit(void *ssl_ctx)
+{
+	tls_nss_ref_count--;
+	if (tls_nss_ref_count == 0) {
+		if (NSS_Shutdown() != SECSuccess)
+			wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed");
+	}
+}
+
+
+int tls_get_errors(void *tls_ctx)
+{
+	return 0;
+}
+
+
+static SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd)
+{
+	struct tls_connection *conn = arg;
+	SECStatus res = SECSuccess;
+	PRErrorCode err;
+	CERTCertificate *cert;
+	char *subject, *issuer;
+
+	err = PR_GetError();
+	if (IS_SEC_ERROR(err))
+		wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err "
+			   "%d)", err - SEC_ERROR_BASE);
+	else
+		wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)",
+			   err);
+	cert = SSL_PeerCertificate(fd);
+	subject = CERT_NameToAscii(&cert->subject);
+	issuer = CERT_NameToAscii(&cert->issuer);
+	wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'",
+		   subject, issuer);
+	CERT_DestroyCertificate(cert);
+	PR_Free(subject);
+	PR_Free(issuer);
+	if (conn->verify_peer)
+		res = SECFailure;
+
+	return res;
+}
+
+
+static void nss_handshake_cb(PRFileDesc *fd, void *client_data)
+{
+	struct tls_connection *conn = client_data;
+	wpa_printf(MSG_DEBUG, "NSS: Handshake completed");
+	conn->established = 1;
+}
+
+
+struct tls_connection * tls_connection_init(void *tls_ctx)
+{
+	struct tls_connection *conn;
+
+	conn = os_zalloc(sizeof(*conn));
+	if (conn == NULL)
+		return NULL;
+
+	conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io);
+	if (conn->fd == NULL) {
+		os_free(conn);
+		return NULL;
+	}
+	conn->fd->secret = (void *) conn;
+
+	conn->fd = SSL_ImportFD(NULL, conn->fd);
+	if (conn->fd == NULL) {
+		os_free(conn);
+		return NULL;
+	}
+
+	if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess ||
+	    SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) !=
+	    SECSuccess ||
+	    SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) !=
+	    SECSuccess ||
+	    SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess ||
+	    SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess ||
+	    SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) !=
+	    SECSuccess) {
+		wpa_printf(MSG_ERROR, "NSS: Failed to set options");
+		PR_Close(conn->fd);
+		os_free(conn);
+		return NULL;
+	}
+
+	SSL_ResetHandshake(conn->fd, PR_FALSE);
+
+	return conn;
+}
+
+
+void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
+{
+	PR_Close(conn->fd);
+	os_free(conn->push_buf);
+	os_free(conn->pull_buf);
+	os_free(conn);
+}
+
+
+int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
+{
+	return conn->established;
+}
+
+
+int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
+			      const struct tls_connection_params *params)
+{
+	wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__);
+	return 0;
+}
+
+
+int tls_global_set_params(void *tls_ctx,
+			  const struct tls_connection_params *params)
+{
+	return -1;
+}
+
+
+int tls_global_set_verify(void *tls_ctx, int check_crl)
+{
+	return -1;
+}
+
+
+int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
+			      int verify_peer)
+{
+	conn->verify_peer = verify_peer;
+	return 0;
+}
+
+
+int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
+			  int tls_ia)
+{
+	return -1;
+}
+
+
+int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
+			    struct tls_keys *keys)
+{
+	/* NSS does not export master secret or client/server random. */
+	return -1;
+}
+
+
+int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
+		       const char *label, int server_random_first,
+		       u8 *out, size_t out_len)
+{
+	if (conn == NULL || server_random_first) {
+		wpa_printf(MSG_INFO, "NSS: Unsupported PRF request "
+			   "(server_random_first=%d)",
+			   server_random_first);
+		return -1;
+	}
+
+	if (SSL_ExportKeyingMaterial(conn->fd, label, NULL, 0, out, out_len) !=
+	    SECSuccess) {
+		wpa_printf(MSG_INFO, "NSS: Failed to use TLS extractor "
+			   "(label='%s' out_len=%d", label, (int) out_len);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+					 struct tls_connection *conn,
+					 const struct wpabuf *in_data,
+					 struct wpabuf **appl_data)
+{
+	struct wpabuf *out_data;
+
+	wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u",
+		   in_data ? (unsigned int) wpabuf_len(in_data) : 0);
+
+	if (appl_data)
+		*appl_data = NULL;
+
+	if (in_data && wpabuf_len(in_data) > 0) {
+		if (conn->pull_buf) {
+			wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
+				   "pull_buf", __func__,
+				   (unsigned long) conn->pull_buf_len);
+			os_free(conn->pull_buf);
+		}
+		conn->pull_buf = os_malloc(wpabuf_len(in_data));
+		if (conn->pull_buf == NULL)
+			return NULL;
+		os_memcpy(conn->pull_buf, wpabuf_head(in_data),
+			  wpabuf_len(in_data));
+		conn->pull_buf_offset = conn->pull_buf;
+		conn->pull_buf_len = wpabuf_len(in_data);
+	}
+
+	SSL_ForceHandshake(conn->fd);
+
+	if (conn->established && conn->push_buf == NULL) {
+		/* Need to return something to get final TLS ACK. */
+		conn->push_buf = os_malloc(1);
+	}
+
+	if (conn->push_buf == NULL)
+		return NULL;
+	out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
+	if (out_data == NULL)
+		os_free(conn->push_buf);
+	conn->push_buf = NULL;
+	conn->push_buf_len = 0;
+	return out_data;
+}
+
+
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+						struct tls_connection *conn,
+						const struct wpabuf *in_data,
+						struct wpabuf **appl_data)
+{
+	return NULL;
+}
+
+
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
+{
+	PRInt32 res;
+	struct wpabuf *buf;
+
+	wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes",
+		   (int) wpabuf_len(in_data));
+	res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0,
+		      0);
+	if (res < 0) {
+		wpa_printf(MSG_ERROR, "NSS: Encryption failed");
+		return NULL;
+	}
+	if (conn->push_buf == NULL)
+		return NULL;
+	buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len);
+	if (buf == NULL)
+		os_free(conn->push_buf);
+	conn->push_buf = NULL;
+	conn->push_buf_len = 0;
+	return buf;
+}
+
+
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
+{
+	PRInt32 res;
+	struct wpabuf *out;
+
+	wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes",
+		   (int) wpabuf_len(in_data));
+	if (conn->pull_buf) {
+		wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
+			   "pull_buf", __func__,
+			   (unsigned long) conn->pull_buf_len);
+		os_free(conn->pull_buf);
+	}
+	conn->pull_buf = os_malloc(wpabuf_len(in_data));
+	if (conn->pull_buf == NULL)
+		return NULL;
+	os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data));
+	conn->pull_buf_offset = conn->pull_buf;
+	conn->pull_buf_len = wpabuf_len(in_data);
+
+	/*
+	 * Even though we try to disable TLS compression, it is possible that
+	 * this cannot be done with all TLS libraries. Add extra buffer space
+	 * to handle the possibility of the decrypted data being longer than
+	 * input data.
+	 */
+	out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
+	if (out == NULL)
+		return NULL;
+
+	res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0);
+	wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res);
+	if (res < 0) {
+		wpabuf_free(out);
+		return NULL;
+	}
+	wpabuf_put(out, res);
+
+	return out;
+}
+
+
+int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
+{
+	return 0;
+}
+
+
+int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
+				   u8 *ciphers)
+{
+	return -1;
+}
+
+
+int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
+		   char *buf, size_t buflen)
+{
+	return -1;
+}
+
+
+int tls_connection_enable_workaround(void *tls_ctx,
+				     struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
+				    int ext_type, const u8 *data,
+				    size_t data_len)
+{
+	return -1;
+}
+
+
+int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
+{
+	return 0;
+}
+
+
+int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
+{
+	return 0;
+}
+
+
+int tls_connection_get_write_alerts(void *tls_ctx,
+				    struct tls_connection *conn)
+{
+	return 0;
+}
+
+
+int tls_connection_get_keyblock_size(void *tls_ctx,
+				     struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+unsigned int tls_capabilities(void *tls_ctx)
+{
+	return 0;
+}
+
+
+struct wpabuf * tls_connection_ia_send_phase_finished(
+	void *tls_ctx, struct tls_connection *conn, int final)
+{
+	return NULL;
+}
+
+
+int tls_connection_ia_final_phase_finished(void *tls_ctx,
+					   struct tls_connection *conn)
+{
+	return -1;
+}
+
+
+int tls_connection_ia_permute_inner_secret(void *tls_ctx,
+					   struct tls_connection *conn,
+					   const u8 *key, size_t key_len)
+{
+	return -1;
+}
+
+
+int tls_connection_set_session_ticket_cb(void *tls_ctx,
+					 struct tls_connection *conn,
+					 tls_session_ticket_cb cb,
+					 void *ctx)
+{
+	return -1;
+}
diff --git a/contrib/wpa/src/crypto/tls_openssl.c b/contrib/wpa/src/crypto/tls_openssl.c
index b5a1d64f53bd..c0a40f95617c 100644
--- a/contrib/wpa/src/crypto/tls_openssl.c
+++ b/contrib/wpa/src/crypto/tls_openssl.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / SSL/TLS interface functions for openssl
- * Copyright (c) 2004-2008, Jouni Malinen 
+ * SSL/TLS interface functions for OpenSSL
+ * Copyright (c) 2004-2010, Jouni Malinen 
  *
  * 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
@@ -29,6 +29,7 @@
 #endif /* OPENSSL_NO_ENGINE */
 
 #include "common.h"
+#include "crypto.h"
 #include "tls.h"
 
 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
@@ -49,6 +50,15 @@
 
 static int tls_openssl_ref_count = 0;
 
+struct tls_global {
+	void (*event_cb)(void *ctx, enum tls_event ev,
+			 union tls_event_data *data);
+	void *cb_ctx;
+};
+
+static struct tls_global *tls_global = NULL;
+
+
 struct tls_connection {
 	SSL *ssl;
 	BIO *ssl_in, *ssl_out;
@@ -65,6 +75,12 @@ struct tls_connection {
 	/* SessionTicket received from OpenSSL hello_extension_cb (server) */
 	u8 *session_ticket;
 	size_t session_ticket_len;
+
+	unsigned int ca_cert_verify:1;
+	unsigned int cert_probe:1;
+	unsigned int server_cert_only:1;
+
+	u8 srv_cert_hash[32];
 };
 
 
@@ -665,6 +681,34 @@ void * tls_init(const struct tls_config *conf)
 	SSL_CTX *ssl;
 
 	if (tls_openssl_ref_count == 0) {
+		tls_global = os_zalloc(sizeof(*tls_global));
+		if (tls_global == NULL)
+			return NULL;
+		if (conf) {
+			tls_global->event_cb = conf->event_cb;
+			tls_global->cb_ctx = conf->cb_ctx;
+		}
+
+#ifdef CONFIG_FIPS
+#ifdef OPENSSL_FIPS
+		if (conf && conf->fips_mode) {
+			if (!FIPS_mode_set(1)) {
+				wpa_printf(MSG_ERROR, "Failed to enable FIPS "
+					   "mode");
+				ERR_load_crypto_strings();
+				ERR_print_errors_fp(stderr);
+				return NULL;
+			} else
+				wpa_printf(MSG_INFO, "Running in FIPS mode");
+		}
+#else /* OPENSSL_FIPS */
+		if (conf && conf->fips_mode) {
+			wpa_printf(MSG_ERROR, "FIPS mode requested, but not "
+				   "supported");
+			return NULL;
+		}
+#endif /* OPENSSL_FIPS */
+#endif /* CONFIG_FIPS */
 		SSL_load_error_strings();
 		SSL_library_init();
 #ifndef OPENSSL_NO_SHA256
@@ -730,6 +774,8 @@ void tls_deinit(void *ssl_ctx)
 		ERR_remove_state(0);
 		ERR_free_strings();
 		EVP_cleanup();
+		os_free(tls_global);
+		tls_global = NULL;
 	}
 }
 
@@ -996,6 +1042,124 @@ static int tls_match_altsubject(X509 *cert, const char *match)
 }
 
 
+static enum tls_fail_reason openssl_tls_fail_reason(int err)
+{
+	switch (err) {
+	case X509_V_ERR_CERT_REVOKED:
+		return TLS_FAIL_REVOKED;
+	case X509_V_ERR_CERT_NOT_YET_VALID:
+	case X509_V_ERR_CRL_NOT_YET_VALID:
+		return TLS_FAIL_NOT_YET_VALID;
+	case X509_V_ERR_CERT_HAS_EXPIRED:
+	case X509_V_ERR_CRL_HAS_EXPIRED:
+		return TLS_FAIL_EXPIRED;
+	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+	case X509_V_ERR_UNABLE_TO_GET_CRL:
+	case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
+	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+	case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+	case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+	case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+	case X509_V_ERR_INVALID_CA:
+		return TLS_FAIL_UNTRUSTED;
+	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+	case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+	case X509_V_ERR_CERT_UNTRUSTED:
+	case X509_V_ERR_CERT_REJECTED:
+		return TLS_FAIL_BAD_CERTIFICATE;
+	default:
+		return TLS_FAIL_UNSPECIFIED;
+	}
+}
+
+
+static struct wpabuf * get_x509_cert(X509 *cert)
+{
+	struct wpabuf *buf;
+	u8 *tmp;
+
+	int cert_len = i2d_X509(cert, NULL);
+	if (cert_len <= 0)
+		return NULL;
+
+	buf = wpabuf_alloc(cert_len);
+	if (buf == NULL)
+		return NULL;
+
+	tmp = wpabuf_put(buf, cert_len);
+	i2d_X509(cert, &tmp);
+	return buf;
+}
+
+
+static void openssl_tls_fail_event(struct tls_connection *conn,
+				   X509 *err_cert, int err, int depth,
+				   const char *subject, const char *err_str,
+				   enum tls_fail_reason reason)
+{
+	union tls_event_data ev;
+	struct wpabuf *cert = NULL;
+
+	if (tls_global->event_cb == NULL)
+		return;
+
+	cert = get_x509_cert(err_cert);
+	os_memset(&ev, 0, sizeof(ev));
+	ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ?
+		reason : openssl_tls_fail_reason(err);
+	ev.cert_fail.depth = depth;
+	ev.cert_fail.subject = subject;
+	ev.cert_fail.reason_txt = err_str;
+	ev.cert_fail.cert = cert;
+	tls_global->event_cb(tls_global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
+	wpabuf_free(cert);
+}
+
+
+static void openssl_tls_cert_event(struct tls_connection *conn,
+				   X509 *err_cert, int depth,
+				   const char *subject)
+{
+	struct wpabuf *cert = NULL;
+	union tls_event_data ev;
+#ifdef CONFIG_SHA256
+	u8 hash[32];
+#endif /* CONFIG_SHA256 */
+
+	if (tls_global->event_cb == NULL)
+		return;
+
+	os_memset(&ev, 0, sizeof(ev));
+	if (conn->cert_probe) {
+		cert = get_x509_cert(err_cert);
+		ev.peer_cert.cert = cert;
+	}
+#ifdef CONFIG_SHA256
+	if (cert) {
+		const u8 *addr[1];
+		size_t len[1];
+		addr[0] = wpabuf_head(cert);
+		len[0] = wpabuf_len(cert);
+		if (sha256_vector(1, addr, len, hash) == 0) {
+			ev.peer_cert.hash = hash;
+			ev.peer_cert.hash_len = sizeof(hash);
+		}
+	}
+#endif /* CONFIG_SHA256 */
+	ev.peer_cert.depth = depth;
+	ev.peer_cert.subject = subject;
+	tls_global->event_cb(tls_global->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
+	wpabuf_free(cert);
+}
+
+
 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
 {
 	char buf[256];
@@ -1004,6 +1168,7 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
 	SSL *ssl;
 	struct tls_connection *conn;
 	char *match, *altmatch;
+	const char *err_str;
 
 	err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
 	err = X509_STORE_CTX_get_error(x509_ctx);
@@ -1016,25 +1181,76 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
 	match = conn ? conn->subject_match : NULL;
 	altmatch = conn ? conn->altsubject_match : NULL;
 
+	if (!preverify_ok && !conn->ca_cert_verify)
+		preverify_ok = 1;
+	if (!preverify_ok && depth > 0 && conn->server_cert_only)
+		preverify_ok = 1;
+
+	err_str = X509_verify_cert_error_string(err);
+
+#ifdef CONFIG_SHA256
+	if (preverify_ok && depth == 0 && conn->server_cert_only) {
+		struct wpabuf *cert;
+		cert = get_x509_cert(err_cert);
+		if (!cert) {
+			wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch "
+				   "server certificate data");
+			preverify_ok = 0;
+		} else {
+			u8 hash[32];
+			const u8 *addr[1];
+			size_t len[1];
+			addr[0] = wpabuf_head(cert);
+			len[0] = wpabuf_len(cert);
+			if (sha256_vector(1, addr, len, hash) < 0 ||
+			    os_memcmp(conn->srv_cert_hash, hash, 32) != 0) {
+				err_str = "Server certificate mismatch";
+				err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
+				preverify_ok = 0;
+			}
+			wpabuf_free(cert);
+		}
+	}
+#endif /* CONFIG_SHA256 */
+
 	if (!preverify_ok) {
 		wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
-			   " error %d (%s) depth %d for '%s'", err,
-			   X509_verify_cert_error_string(err), depth, buf);
-	} else {
-		wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - "
-			   "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
-			   preverify_ok, err,
-			   X509_verify_cert_error_string(err), depth, buf);
-		if (depth == 0 && match && os_strstr(buf, match) == NULL) {
-			wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
-				   "match with '%s'", buf, match);
-			preverify_ok = 0;
-		} else if (depth == 0 && altmatch &&
-			   !tls_match_altsubject(err_cert, altmatch)) {
-			wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
-				   "'%s' not found", altmatch);
-			preverify_ok = 0;
-		}
+			   " error %d (%s) depth %d for '%s'", err, err_str,
+			   depth, buf);
+		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+				       err_str, TLS_FAIL_UNSPECIFIED);
+		return preverify_ok;
+	}
+
+	wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d "
+		   "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
+		   preverify_ok, err, err_str,
+		   conn->ca_cert_verify, depth, buf);
+	if (depth == 0 && match && os_strstr(buf, match) == NULL) {
+		wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
+			   "match with '%s'", buf, match);
+		preverify_ok = 0;
+		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+				       "Subject mismatch",
+				       TLS_FAIL_SUBJECT_MISMATCH);
+	} else if (depth == 0 && altmatch &&
+		   !tls_match_altsubject(err_cert, altmatch)) {
+		wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
+			   "'%s' not found", altmatch);
+		preverify_ok = 0;
+		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+				       "AltSubject mismatch",
+				       TLS_FAIL_ALTSUBJECT_MISMATCH);
+	} else
+		openssl_tls_cert_event(conn, err_cert, depth, buf);
+
+	if (conn->cert_probe && preverify_ok && depth == 0) {
+		wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate "
+			   "on probe-only run");
+		preverify_ok = 0;
+		openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+				       "Server certificate chain probe",
+				       TLS_FAIL_SERVER_CHAIN_PROBE);
 	}
 
 	return preverify_ok;
@@ -1092,6 +1308,47 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
 		return -1;
 	}
 
+	SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
+	conn->ca_cert_verify = 1;
+
+	if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) {
+		wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate "
+			   "chain");
+		conn->cert_probe = 1;
+		conn->ca_cert_verify = 0;
+		return 0;
+	}
+
+	if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) {
+#ifdef CONFIG_SHA256
+		const char *pos = ca_cert + 7;
+		if (os_strncmp(pos, "server/sha256/", 14) != 0) {
+			wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert "
+				   "hash value '%s'", ca_cert);
+			return -1;
+		}
+		pos += 14;
+		if (os_strlen(pos) != 32 * 2) {
+			wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 "
+				   "hash length in ca_cert '%s'", ca_cert);
+			return -1;
+		}
+		if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) {
+			wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash "
+				   "value in ca_cert '%s'", ca_cert);
+			return -1;
+		}
+		conn->server_cert_only = 1;
+		wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server "
+			   "certificate match");
+		return 0;
+#else /* CONFIG_SHA256 */
+		wpa_printf(MSG_INFO, "No SHA256 included in the build - "
+			   "cannot validate server certificate hash");
+		return -1;
+#endif /* CONFIG_SHA256 */
+	}
+
 	if (ca_cert_blob) {
 		X509 *cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ca_cert_blob,
 				      ca_cert_blob_len);
@@ -1120,7 +1377,6 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
 		X509_free(cert);
 		wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "
 			   "to certificate store", __func__);
-		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
 		return 0;
 	}
 
@@ -1129,7 +1385,6 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
 	    0) {
 		wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from "
 			   "system certificate store");
-		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
 		return 0;
 	}
 #endif /* CONFIG_NATIVE_WINDOWS */
@@ -1152,7 +1407,6 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
 				   "certificate(s) loaded");
 			tls_get_errors(ssl_ctx);
 		}
-		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
 #else /* OPENSSL_NO_STDIO */
 		wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
 			   __func__);
@@ -1161,7 +1415,7 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
 	} else {
 		/* No ca_cert configured - do not try to verify server
 		 * certificate */
-		SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
+		conn->ca_cert_verify = 0;
 	}
 
 	return 0;
@@ -1246,10 +1500,12 @@ int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
 		return -1;
 
 	if (verify_peer) {
+		conn->ca_cert_verify = 1;
 		SSL_set_verify(conn->ssl, SSL_VERIFY_PEER |
 			       SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
 			       SSL_VERIFY_CLIENT_ONCE, tls_verify_cb);
 	} else {
+		conn->ca_cert_verify = 0;
 		SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
 	}
 
@@ -1979,30 +2235,30 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
-			      const u8 *in_data, size_t in_len,
-			      size_t *out_len, u8 **appl_data,
-			      size_t *appl_data_len)
+static struct wpabuf *
+openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data,
+		  int server)
 {
 	int res;
-	u8 *out_data;
-
-	if (appl_data)
-		*appl_data = NULL;
+	struct wpabuf *out_data;
 
 	/*
 	 * Give TLS handshake data from the server (if available) to OpenSSL
 	 * for processing.
 	 */
 	if (in_data &&
-	    BIO_write(conn->ssl_in, in_data, in_len) < 0) {
+	    BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data))
+	    < 0) {
 		tls_show_errors(MSG_INFO, __func__,
 				"Handshake failed - BIO_write");
 		return NULL;
 	}
 
 	/* Initiate TLS handshake or continue the existing handshake */
-	res = SSL_connect(conn->ssl);
+	if (server)
+		res = SSL_accept(conn->ssl);
+	else
+		res = SSL_connect(conn->ssl);
 	if (res != 1) {
 		int err = SSL_get_error(conn->ssl, res);
 		if (err == SSL_ERROR_WANT_READ)
@@ -2020,7 +2276,7 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 	/* Get the TLS handshake data to be sent to the server */
 	res = BIO_ctrl_pending(conn->ssl_out);
 	wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
-	out_data = os_malloc(res == 0 ? 1 : res);
+	out_data = wpabuf_alloc(res);
 	if (out_data == NULL) {
 		wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
 			   "handshake output (%d bytes)", res);
@@ -2028,10 +2284,10 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 			tls_show_errors(MSG_INFO, __func__,
 					"BIO_reset failed");
 		}
-		*out_len = 0;
 		return NULL;
 	}
-	res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res);
+	res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data),
+				      res);
 	if (res < 0) {
 		tls_show_errors(MSG_INFO, __func__,
 				"Handshake failed - BIO_read");
@@ -2039,169 +2295,169 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 			tls_show_errors(MSG_INFO, __func__,
 					"BIO_reset failed");
 		}
-		*out_len = 0;
+		wpabuf_free(out_data);
 		return NULL;
 	}
-	*out_len = res;
-
-	if (SSL_is_init_finished(conn->ssl) && appl_data) {
-		*appl_data = os_malloc(in_len);
-		if (*appl_data) {
-			res = SSL_read(conn->ssl, *appl_data, in_len);
-			if (res < 0) {
-				int err = SSL_get_error(conn->ssl, res);
-				if (err == SSL_ERROR_WANT_READ ||
-				    err == SSL_ERROR_WANT_WRITE) {
-					wpa_printf(MSG_DEBUG,
-						   "SSL: No Application Data "
-						   "included");
-				} else {
-					tls_show_errors(MSG_INFO, __func__,
-							"Failed to read "
-							"possible "
-							"Application Data");
-				}
-				os_free(*appl_data);
-				*appl_data = NULL;
-			} else {
-				*appl_data_len = res;
-				wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application"
-						" Data in Finish message",
-						*appl_data, *appl_data_len);
-			}
-		}
-	}
+	wpabuf_put(out_data, res);
 
 	return out_data;
 }
 
 
-u8 * tls_connection_server_handshake(void *ssl_ctx,
-				     struct tls_connection *conn,
-				     const u8 *in_data, size_t in_len,
-				     size_t *out_len)
+static struct wpabuf *
+openssl_get_appl_data(struct tls_connection *conn, size_t max_len)
 {
+	struct wpabuf *appl_data;
 	int res;
-	u8 *out_data;
 
-	/*
-	 * Give TLS handshake data from the client (if available) to OpenSSL
-	 * for processing.
-	 */
-	if (in_data &&
-	    BIO_write(conn->ssl_in, in_data, in_len) < 0) {
-		tls_show_errors(MSG_INFO, __func__,
-				"Handshake failed - BIO_write");
+	appl_data = wpabuf_alloc(max_len + 100);
+	if (appl_data == NULL)
 		return NULL;
-	}
 
-	/* Initiate TLS handshake or continue the existing handshake */
-	res = SSL_accept(conn->ssl);
-	if (res != 1) {
+	res = SSL_read(conn->ssl, wpabuf_mhead(appl_data),
+		       wpabuf_size(appl_data));
+	if (res < 0) {
 		int err = SSL_get_error(conn->ssl, res);
-		if (err == SSL_ERROR_WANT_READ)
-			wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want "
-				   "more data");
-		else if (err == SSL_ERROR_WANT_WRITE)
-			wpa_printf(MSG_DEBUG, "SSL: SSL_accept - want to "
-				   "write");
-		else {
-			tls_show_errors(MSG_INFO, __func__, "SSL_accept");
-			return NULL;
+		if (err == SSL_ERROR_WANT_READ ||
+		    err == SSL_ERROR_WANT_WRITE) {
+			wpa_printf(MSG_DEBUG, "SSL: No Application Data "
+				   "included");
+		} else {
+			tls_show_errors(MSG_INFO, __func__,
+					"Failed to read possible "
+					"Application Data");
 		}
+		wpabuf_free(appl_data);
+		return NULL;
 	}
 
-	/* Get the TLS handshake data to be sent to the client */
-	res = BIO_ctrl_pending(conn->ssl_out);
-	wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
-	out_data = os_malloc(res == 0 ? 1 : res);
-	if (out_data == NULL) {
-		wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
-			   "handshake output (%d bytes)", res);
-		if (BIO_reset(conn->ssl_out) < 0) {
-			tls_show_errors(MSG_INFO, __func__,
-					"BIO_reset failed");
-		}
-		*out_len = 0;
+	wpabuf_put(appl_data, res);
+	wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished "
+			    "message", appl_data);
+
+	return appl_data;
+}
+
+
+static struct wpabuf *
+openssl_connection_handshake(struct tls_connection *conn,
+			     const struct wpabuf *in_data,
+			     struct wpabuf **appl_data, int server)
+{
+	struct wpabuf *out_data;
+
+	if (appl_data)
+		*appl_data = NULL;
+
+	out_data = openssl_handshake(conn, in_data, server);
+	if (out_data == NULL)
 		return NULL;
-	}
-	res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res);
-	if (res < 0) {
-		tls_show_errors(MSG_INFO, __func__,
-				"Handshake failed - BIO_read");
-		if (BIO_reset(conn->ssl_out) < 0) {
-			tls_show_errors(MSG_INFO, __func__,
-					"BIO_reset failed");
-		}
-		*out_len = 0;
-		return NULL;
-	}
-	*out_len = res;
+
+	if (SSL_is_init_finished(conn->ssl) && appl_data && in_data)
+		*appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data));
+
 	return out_data;
 }
 
 
-int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
-			   const u8 *in_data, size_t in_len,
-			   u8 *out_data, size_t out_len)
+struct wpabuf *
+tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
+			 const struct wpabuf *in_data,
+			 struct wpabuf **appl_data)
+{
+	return openssl_connection_handshake(conn, in_data, appl_data, 0);
+}
+
+
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+						struct tls_connection *conn,
+						const struct wpabuf *in_data,
+						struct wpabuf **appl_data)
+{
+	return openssl_connection_handshake(conn, in_data, appl_data, 1);
+}
+
+
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
 {
 	int res;
+	struct wpabuf *buf;
 
 	if (conn == NULL)
-		return -1;
+		return NULL;
 
 	/* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
 	if ((res = BIO_reset(conn->ssl_in)) < 0 ||
 	    (res = BIO_reset(conn->ssl_out)) < 0) {
 		tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
-		return res;
+		return NULL;
 	}
-	res = SSL_write(conn->ssl, in_data, in_len);
+	res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data));
 	if (res < 0) {
 		tls_show_errors(MSG_INFO, __func__,
 				"Encryption failed - SSL_write");
-		return res;
+		return NULL;
 	}
 
 	/* Read encrypted data to be sent to the server */
-	res = BIO_read(conn->ssl_out, out_data, out_len);
+	buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
+	if (buf == NULL)
+		return NULL;
+	res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf));
 	if (res < 0) {
 		tls_show_errors(MSG_INFO, __func__,
 				"Encryption failed - BIO_read");
-		return res;
+		wpabuf_free(buf);
+		return NULL;
 	}
+	wpabuf_put(buf, res);
 
-	return res;
+	return buf;
 }
 
 
-int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
-			   const u8 *in_data, size_t in_len,
-			   u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
 {
 	int res;
+	struct wpabuf *buf;
 
 	/* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */
-	res = BIO_write(conn->ssl_in, in_data, in_len);
+	res = BIO_write(conn->ssl_in, wpabuf_head(in_data),
+			wpabuf_len(in_data));
 	if (res < 0) {
 		tls_show_errors(MSG_INFO, __func__,
 				"Decryption failed - BIO_write");
-		return res;
+		return NULL;
 	}
 	if (BIO_reset(conn->ssl_out) < 0) {
 		tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
-		return res;
+		return NULL;
 	}
 
 	/* Read decrypted data for further processing */
-	res = SSL_read(conn->ssl, out_data, out_len);
+	/*
+	 * Even though we try to disable TLS compression, it is possible that
+	 * this cannot be done with all TLS libraries. Add extra buffer space
+	 * to handle the possibility of the decrypted data being longer than
+	 * input data.
+	 */
+	buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
+	if (buf == NULL)
+		return NULL;
+	res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf));
 	if (res < 0) {
 		tls_show_errors(MSG_INFO, __func__,
 				"Decryption failed - SSL_read");
-		return res;
+		wpabuf_free(buf);
+		return NULL;
 	}
+	wpabuf_put(buf, res);
 
-	return res;
+	return buf;
 }
 
 
@@ -2292,7 +2548,7 @@ int tls_connection_enable_workaround(void *ssl_ctx,
 }
 
 
-#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC)
+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
 /* ClientHello TLS extensions require a patch to openssl, so this function is
  * commented out unless explicitly needed for EAP-FAST in order to be able to
  * build this file with unmodified openssl. */
@@ -2315,7 +2571,7 @@ int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
 
 	return 0;
 }
-#endif /* EAP_FAST || EAP_FAST_DYNAMIC */
+#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
 
 
 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
@@ -2482,12 +2738,10 @@ int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-int tls_connection_ia_send_phase_finished(void *tls_ctx,
-					  struct tls_connection *conn,
-					  int final,
-					  u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_ia_send_phase_finished(
+	void *tls_ctx, struct tls_connection *conn, int final)
 {
-	return -1;
+	return NULL;
 }
 
 
@@ -2506,7 +2760,7 @@ int tls_connection_ia_permute_inner_secret(void *tls_ctx,
 }
 
 
-#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC)
+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
 /* Pre-shared secred requires a patch to openssl, so this function is
  * commented out unless explicitly needed for EAP-FAST in order to be able to
  * build this file with unmodified openssl. */
@@ -2619,7 +2873,7 @@ static int tls_hello_ext_cb(SSL *s, TLS_EXTENSION *ext, void *arg)
 }
 #endif /* SSL_OP_NO_TICKET */
 #endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */
-#endif /* EAP_FAST || EAP_FAST_DYNAMIC */
+#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
 
 
 int tls_connection_set_session_ticket_cb(void *tls_ctx,
@@ -2627,7 +2881,7 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx,
 					 tls_session_ticket_cb cb,
 					 void *ctx)
 {
-#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC)
+#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
 	conn->session_ticket_cb = cb;
 	conn->session_ticket_cb_ctx = ctx;
 
@@ -2665,7 +2919,7 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx,
 	}
 
 	return 0;
-#else /* EAP_FAST || EAP_FAST_DYNAMIC */
+#else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
 	return -1;
-#endif /* EAP_FAST || EAP_FAST_DYNAMIC */
+#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
 }
diff --git a/contrib/wpa/src/crypto/tls_schannel.c b/contrib/wpa/src/crypto/tls_schannel.c
index 87e74353dcf9..4a94e9911982 100644
--- a/contrib/wpa/src/crypto/tls_schannel.c
+++ b/contrib/wpa/src/crypto/tls_schannel.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel
- * Copyright (c) 2005, Jouni Malinen 
+ * SSL/TLS interface functions for Microsoft Schannel
+ * Copyright (c) 2005-2009, Jouni Malinen 
  *
  * 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
@@ -215,9 +215,8 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-static u8 * tls_conn_hs_clienthello(struct tls_global *global,
-				    struct tls_connection *conn,
-				    size_t *out_len)
+static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global,
+					       struct tls_connection *conn)
 {
 	DWORD sspi_flags, sspi_flags_out;
 	SecBufferDesc outbuf;
@@ -260,15 +259,14 @@ static u8 * tls_conn_hs_clienthello(struct tls_global *global,
 	}
 
 	if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
-		u8 *buf;
+		struct wpabuf *buf;
 		wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello",
 			    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
 		conn->start = 0;
-		*out_len = outbufs[0].cbBuffer;
-		buf = os_malloc(*out_len);
+		buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
+					outbufs[0].cbBuffer);
 		if (buf == NULL)
 			return NULL;
-		os_memcpy(buf, outbufs[0].pvBuffer, *out_len);
 		global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
 		return buf;
 	}
@@ -316,28 +314,27 @@ static int tls_get_eap(struct tls_global *global, struct tls_connection *conn)
 }
 
 
-u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
-			      const u8 *in_data, size_t in_len,
-			      size_t *out_len, u8 **appl_data,
-			      size_t *appl_data_len)
+struct wpabuf * tls_connection_handshake(void *tls_ctx,
+					 struct tls_connection *conn,
+					 const struct wpabuf *in_data,
+					 struct wpabuf **appl_data)
 {
-	struct tls_global *global = ssl_ctx;
+	struct tls_global *global = tls_ctx;
 	DWORD sspi_flags, sspi_flags_out;
 	SecBufferDesc inbuf, outbuf;
 	SecBuffer inbufs[2], outbufs[1];
 	SECURITY_STATUS status;
 	TimeStamp ts_expiry;
-	u8 *out_buf = NULL;
+	struct wpabuf *out_buf = NULL;
 
 	if (appl_data)
 		*appl_data = NULL;
 
-	if (conn->start) {
-		return tls_conn_hs_clienthello(global, conn, out_len);
-	}
+	if (conn->start)
+		return tls_conn_hs_clienthello(global, conn);
 
 	wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process",
-		   in_len);
+		   (int) wpabuf_len(in_data));
 
 	sspi_flags = ISC_REQ_REPLAY_DETECT |
 		ISC_REQ_CONFIDENTIALITY |
@@ -346,8 +343,8 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 		ISC_REQ_MANUAL_CRED_VALIDATION;
 
 	/* Input buffer for Schannel */
-	inbufs[0].pvBuffer = (u8 *) in_data;
-	inbufs[0].cbBuffer = in_len;
+	inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data);
+	inbufs[0].cbBuffer = wpabuf_len(in_data);
 	inbufs[0].BufferType = SECBUFFER_TOKEN;
 
 	/* Place for leftover data from Schannel */
@@ -392,11 +389,8 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 		if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) {
 			wpa_hexdump(MSG_MSGDUMP, "SChannel - output",
 				    outbufs[0].pvBuffer, outbufs[0].cbBuffer);
-			*out_len = outbufs[0].cbBuffer;
-			out_buf = os_malloc(*out_len);
-			if (out_buf)
-				os_memcpy(out_buf, outbufs[0].pvBuffer,
-					  *out_len);
+			out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer,
+						    outbufs[0].cbBuffer);
 			global->sspi->FreeContextBuffer(outbufs[0].pvBuffer);
 			outbufs[0].pvBuffer = NULL;
 			if (out_buf == NULL)
@@ -420,19 +414,16 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 
 		/* Need to return something to get final TLS ACK. */
 		if (out_buf == NULL)
-			out_buf = os_malloc(1);
+			out_buf = wpabuf_alloc(0);
 
 		if (inbufs[1].BufferType == SECBUFFER_EXTRA) {
 			wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted "
 				    "application data",
 				    inbufs[1].pvBuffer, inbufs[1].cbBuffer);
 			if (appl_data) {
-				*appl_data_len = outbufs[1].cbBuffer;
-				appl_data = os_malloc(*appl_data_len);
-				if (appl_data)
-					os_memcpy(appl_data,
-						  outbufs[1].pvBuffer,
-						  *appl_data_len);
+				*appl_data = wpabuf_alloc_copy(
+					outbufs[1].pvBuffer,
+					outbufs[1].cbBuffer);
 			}
 			global->sspi->FreeContextBuffer(inbufs[1].pvBuffer);
 			inbufs[1].pvBuffer = NULL;
@@ -470,26 +461,26 @@ u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
 }
 
 
-u8 * tls_connection_server_handshake(void *ssl_ctx,
-				     struct tls_connection *conn,
-				     const u8 *in_data, size_t in_len,
-				     size_t *out_len)
+struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
+						struct tls_connection *conn,
+						const struct wpabuf *in_data,
+						struct wpabuf **appl_data)
 {
 	return NULL;
 }
 
 
-int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
-			   const u8 *in_data, size_t in_len,
-			   u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_encrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
 {
-	struct tls_global *global = ssl_ctx;
+	struct tls_global *global = tls_ctx;
 	SECURITY_STATUS status;
 	SecBufferDesc buf;
 	SecBuffer bufs[4];
 	SecPkgContext_StreamSizes sizes;
 	int i;
-	size_t total_len;
+	struct wpabuf *out;
 
 	status = global->sspi->QueryContextAttributes(&conn->context,
 						      SECPKG_ATTR_STREAM_SIZES,
@@ -497,34 +488,27 @@ int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
 	if (status != SEC_E_OK) {
 		wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed",
 			   __func__);
-		return -1;
+		return NULL;
 	}
 	wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u",
 		   __func__,
 		   (unsigned int) sizes.cbHeader,
 		   (unsigned int) sizes.cbTrailer);
 
-	total_len = sizes.cbHeader + in_len + sizes.cbTrailer;
-
-	if (out_len < total_len) {
-		wpa_printf(MSG_DEBUG, "%s: too short out_data (out_len=%lu "
-			   "in_len=%lu total_len=%lu)", __func__,
-			   (unsigned long) out_len, (unsigned long) in_len,
-			   (unsigned long) total_len);
-		return -1;
-	}
+	out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) +
+			   sizes.cbTrailer);
 
 	os_memset(&bufs, 0, sizeof(bufs));
-	bufs[0].pvBuffer = out_data;
+	bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader);
 	bufs[0].cbBuffer = sizes.cbHeader;
 	bufs[0].BufferType = SECBUFFER_STREAM_HEADER;
 
-	os_memcpy(out_data + sizes.cbHeader, in_data, in_len);
-	bufs[1].pvBuffer = out_data + sizes.cbHeader;
-	bufs[1].cbBuffer = in_len;
+	bufs[1].pvBuffer = wpabuf_put(out, 0);
+	wpabuf_put_buf(out, in_data);
+	bufs[1].cbBuffer = wpabuf_len(in_data);
 	bufs[1].BufferType = SECBUFFER_DATA;
 
-	bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len;
+	bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer);
 	bufs[2].cbBuffer = sizes.cbTrailer;
 	bufs[2].BufferType = SECBUFFER_STREAM_TRAILER;
 
@@ -543,7 +527,7 @@ int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
 		   (int) bufs[2].cbBuffer, (int) bufs[2].BufferType);
 	wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: "
 		   "out_data=%p bufs %p %p %p",
-		   out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
+		   wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer,
 		   bufs[2].pvBuffer);
 
 	for (i = 0; i < 3; i++) {
@@ -556,39 +540,37 @@ int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn,
 
 	if (status == SEC_E_OK) {
 		wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__);
-		wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Encrypted data from "
-				"EncryptMessage", out_data, total_len);
-		return total_len;
+		wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data "
+				    "from EncryptMessage", out);
+		return out;
 	}
 
 	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
 		   __func__, (int) status);
-	return -1;
+	wpabuf_free(out);
+	return NULL;
 }
 
 
-int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
-			   const u8 *in_data, size_t in_len,
-			   u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_decrypt(void *tls_ctx,
+				       struct tls_connection *conn,
+				       const struct wpabuf *in_data)
 {
-	struct tls_global *global = ssl_ctx;
+	struct tls_global *global = tls_ctx;
 	SECURITY_STATUS status;
 	SecBufferDesc buf;
 	SecBuffer bufs[4];
 	int i;
+	struct wpabuf *out, *tmp;
 
-	if (out_len < in_len) {
-		wpa_printf(MSG_DEBUG, "%s: out_len=%lu < in_len=%lu", __func__,
-			   (unsigned long) out_len, (unsigned long) in_len);
-		return -1;
-	}
-
-	wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage",
-		    in_data, in_len);
+	wpa_hexdump_buf(MSG_MSGDUMP,
+			"Schannel: Encrypted data to DecryptMessage", in_data);
 	os_memset(&bufs, 0, sizeof(bufs));
-	os_memcpy(out_data, in_data, in_len);
-	bufs[0].pvBuffer = out_data;
-	bufs[0].cbBuffer = in_len;
+	tmp = wpabuf_dup(in_data);
+	if (tmp == NULL)
+		return NULL;
+	bufs[0].pvBuffer = wpabuf_mhead(tmp);
+	bufs[0].cbBuffer = wpabuf_len(in_data);
 	bufs[0].BufferType = SECBUFFER_DATA;
 
 	bufs[1].BufferType = SECBUFFER_EMPTY;
@@ -611,7 +593,7 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
 		   (int) bufs[3].cbBuffer, (int) bufs[3].BufferType);
 	wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: "
 		   "out_data=%p bufs %p %p %p %p",
-		   out_data, bufs[0].pvBuffer, bufs[1].pvBuffer,
+		   wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer,
 		   bufs[2].pvBuffer, bufs[3].pvBuffer);
 
 	switch (status) {
@@ -628,23 +610,21 @@ int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
 		if (i == 4) {
 			wpa_printf(MSG_DEBUG, "%s: No output data from "
 				   "DecryptMessage", __func__);
-			return -1;
+			wpabuf_free(tmp);
+			return NULL;
 		}
 		wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from "
 				"DecryptMessage",
 				bufs[i].pvBuffer, bufs[i].cbBuffer);
-		if (bufs[i].cbBuffer > out_len) {
-			wpa_printf(MSG_DEBUG, "%s: Too long output data",
-				   __func__);
-			return -1;
-		}
-		os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer);
-		return bufs[i].cbBuffer;
+		out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer);
+		wpabuf_free(tmp);
+		return out;
 	}
 
 	wpa_printf(MSG_DEBUG, "%s: Failed - status=%d",
 		   __func__, (int) status);
-	return -1;
+	wpabuf_free(tmp);
+	return NULL;
 }
 
 
@@ -765,12 +745,10 @@ int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn,
 }
 
 
-int tls_connection_ia_send_phase_finished(void *tls_ctx,
-					  struct tls_connection *conn,
-					  int final,
-					  u8 *out_data, size_t out_len)
+struct wpabuf * tls_connection_ia_send_phase_finished(
+	void *tls_ctx, struct tls_connection *conn, int final);
 {
-	return -1;
+	return NULL;
 }
 
 
diff --git a/contrib/wpa/src/drivers/.gitignore b/contrib/wpa/src/drivers/.gitignore
new file mode 100644
index 000000000000..1d9e0e661afe
--- /dev/null
+++ b/contrib/wpa/src/drivers/.gitignore
@@ -0,0 +1,2 @@
+build.wpa_supplicant
+build.hostapd
diff --git a/contrib/wpa/src/drivers/Makefile b/contrib/wpa/src/drivers/Makefile
index cffba620da04..07600e52c2fd 100644
--- a/contrib/wpa/src/drivers/Makefile
+++ b/contrib/wpa/src/drivers/Makefile
@@ -2,8 +2,8 @@ all:
 	@echo Nothing to be made.
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
 	rm -f *~ *.o *.d
+	rm -f build.wpa_supplicant build.hostapd
 
 install:
 	@echo Nothing to be made.
diff --git a/contrib/wpa/src/drivers/driver.h b/contrib/wpa/src/drivers/driver.h
index c2975d2c1215..fa49da454e83 100644
--- a/contrib/wpa/src/drivers/driver.h
+++ b/contrib/wpa/src/drivers/driver.h
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant - driver interface definition
- * Copyright (c) 2003-2008, Jouni Malinen 
+ * Driver interface definition
+ * Copyright (c) 2003-2010, Jouni Malinen 
  *
  * 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
@@ -10,79 +10,117 @@
  * license.
  *
  * See README and COPYING for more details.
+ *
+ * This file defines a driver interface used by both %wpa_supplicant and
+ * hostapd. The first part of the file defines data structures used in various
+ * driver operations. This is followed by the struct wpa_driver_ops that each
+ * driver wrapper will beed to define with callback functions for requesting
+ * driver operations. After this, there are definitions for driver event
+ * reporting with wpa_supplicant_event() and some convenience helper functions
+ * that can be used to report events.
  */
 
 #ifndef DRIVER_H
 #define DRIVER_H
 
-#define WPA_SUPPLICANT_DRIVER_VERSION 3
+#define WPA_SUPPLICANT_DRIVER_VERSION 4
 
-#include "defs.h"
+#include "common/defs.h"
+
+#define HOSTAPD_CHAN_DISABLED 0x00000001
+#define HOSTAPD_CHAN_PASSIVE_SCAN 0x00000002
+#define HOSTAPD_CHAN_NO_IBSS 0x00000004
+#define HOSTAPD_CHAN_RADAR 0x00000008
+
+/**
+ * struct hostapd_channel_data - Channel information
+ */
+struct hostapd_channel_data {
+	/**
+	 * chan - Channel number (IEEE 802.11)
+	 */
+	short chan;
+
+	/**
+	 * freq - Frequency in MHz
+	 */
+	short freq;
+
+	/**
+	 * flag - Channel flags (HOSTAPD_CHAN_*)
+	 */
+	int flag;
+
+	/**
+	 * max_tx_power - maximum transmit power in dBm
+	 */
+	u8 max_tx_power;
+};
+
+/**
+ * struct hostapd_hw_modes - Supported hardware mode information
+ */
+struct hostapd_hw_modes {
+	/**
+	 * mode - Hardware mode
+	 */
+	enum hostapd_hw_mode mode;
+
+	/**
+	 * num_channels - Number of entries in the channels array
+	 */
+	int num_channels;
+
+	/**
+	 * channels - Array of supported channels
+	 */
+	struct hostapd_channel_data *channels;
+
+	/**
+	 * num_rates - Number of entries in the rates array
+	 */
+	int num_rates;
+
+	/**
+	 * rates - Array of supported rates in 100 kbps units
+	 */
+	int *rates;
+
+	/**
+	 * ht_capab - HT (IEEE 802.11n) capabilities
+	 */
+	u16 ht_capab;
+
+	/**
+	 * mcs_set - MCS (IEEE 802.11n) rate parameters
+	 */
+	u8 mcs_set[16];
+
+	/**
+	 * a_mpdu_params - A-MPDU (IEEE 802.11n) parameters
+	 */
+	u8 a_mpdu_params;
+};
 
-#define AUTH_ALG_OPEN_SYSTEM	0x01
-#define AUTH_ALG_SHARED_KEY	0x02
-#define AUTH_ALG_LEAP		0x04
 
 #define IEEE80211_MODE_INFRA	0
 #define IEEE80211_MODE_IBSS	1
+#define IEEE80211_MODE_AP	2
 
 #define IEEE80211_CAP_ESS	0x0001
 #define IEEE80211_CAP_IBSS	0x0002
 #define IEEE80211_CAP_PRIVACY	0x0010
 
-#define SSID_MAX_WPA_IE_LEN 40
-/**
- * struct wpa_scan_result - Scan results (old structure)
- * @bssid: BSSID
- * @ssid: SSID
- * @ssid_len: length of the ssid
- * @wpa_ie: WPA IE
- * @wpa_ie_len: length of the wpa_ie
- * @rsn_ie: RSN IE
- * @rsn_ie_len: length of the RSN IE
- * @freq: frequency of the channel in MHz (e.g., 2412 = channel 1)
- * @caps: capability information field in host byte order
- * @qual: signal quality
- * @noise: noise level
- * @level: signal level
- * @maxrate: maximum supported rate
- * @mdie_present: Whether MDIE was included in Beacon/ProbeRsp frame
- * @mdie: Mobility domain identifier IE (IEEE 802.11r MDIE) (starting from
- * IE type field)
- * @tsf: Timestamp
- *
- * This structure is used as a generic format for scan results from the
- * driver. Each driver interface implementation is responsible for converting
- * the driver or OS specific scan results into this format.
- *
- * This structure is the old data structure used for scan results. It is
- * obsoleted by the new struct wpa_scan_res structure and the old version is
- * only included for backwards compatibility with existing driver wrapper
- * implementations. New implementations are encouraged to implement for struct
- * wpa_scan_res. The old structure will be removed at some point.
- */
-struct wpa_scan_result {
-	u8 bssid[ETH_ALEN];
-	u8 ssid[32];
-	size_t ssid_len;
-	u8 wpa_ie[SSID_MAX_WPA_IE_LEN];
-	size_t wpa_ie_len;
-	u8 rsn_ie[SSID_MAX_WPA_IE_LEN];
-	size_t rsn_ie_len;
-	int freq;
-	u16 caps;
-	int qual;
-	int noise;
-	int level;
-	int maxrate;
-	int mdie_present;
-	u8 mdie[5];
-	u64 tsf;
-};
-
+#define WPA_SCAN_QUAL_INVALID		BIT(0)
+#define WPA_SCAN_NOISE_INVALID		BIT(1)
+#define WPA_SCAN_LEVEL_INVALID		BIT(2)
+#define WPA_SCAN_LEVEL_DBM		BIT(3)
+#define WPA_SCAN_AUTHENTICATED		BIT(4)
+#define WPA_SCAN_ASSOCIATED		BIT(5)
 
 /**
  * struct wpa_scan_res - Scan result for an BSS/IBSS
+ * @flags: information flags about the BSS/IBSS (WPA_SCAN_*)
  * @bssid: BSSID
  * @freq: frequency of the channel in MHz (e.g., 2412 = channel 1)
  * @beacon_int: beacon interval in TUs (host byte order)
@@ -91,7 +129,10 @@ struct wpa_scan_result {
  * @noise: noise level
  * @level: signal level
  * @tsf: Timestamp
+ * @age: Age of the information in milliseconds (i.e., how many milliseconds
+ * ago the last Beacon or Probe Response frame was received)
  * @ie_len: length of the following IE field in octets
+ * @beacon_ie_len: length of the following Beacon IE field in octets
  *
  * This structure is used as a generic format for scan results from the
  * driver. Each driver interface implementation is responsible for converting
@@ -103,6 +144,7 @@ struct wpa_scan_result {
  * report all IEs to make it easier to support future additions.
  */
 struct wpa_scan_res {
+	unsigned int flags;
 	u8 bssid[ETH_ALEN];
 	int freq;
 	u16 beacon_int;
@@ -111,8 +153,16 @@ struct wpa_scan_res {
 	int noise;
 	int level;
 	u64 tsf;
+	unsigned int age;
 	size_t ie_len;
-	/* followed by ie_len octets of IEs */
+	size_t beacon_ie_len;
+	/*
+	 * Followed by ie_len octets of IEs from Probe Response frame (or if
+	 * the driver does not indicate source of IEs, these may also be from
+	 * Beacon frame). After the first set of IEs, another set of IEs may
+	 * follow (with beacon_ie_len octets of data) if the driver provides
+	 * both IE sets.
+	 */
 };
 
 /**
@@ -142,6 +192,95 @@ struct wpa_interface_info {
 	const char *drv_name;
 };
 
+#define WPAS_MAX_SCAN_SSIDS 4
+
+/**
+ * struct wpa_driver_scan_params - Scan parameters
+ * Data for struct wpa_driver_ops::scan2().
+ */
+struct wpa_driver_scan_params {
+	/**
+	 * ssids - SSIDs to scan for
+	 */
+	struct wpa_driver_scan_ssid {
+		/**
+		 * ssid - specific SSID to scan for (ProbeReq)
+		 * %NULL or zero-length SSID is used to indicate active scan
+		 * with wildcard SSID.
+		 */
+		const u8 *ssid;
+		/**
+		 * ssid_len: Length of the SSID in octets
+		 */
+		size_t ssid_len;
+	} ssids[WPAS_MAX_SCAN_SSIDS];
+
+	/**
+	 * num_ssids - Number of entries in ssids array
+	 * Zero indicates a request for a passive scan.
+	 */
+	size_t num_ssids;
+
+	/**
+	 * extra_ies - Extra IE(s) to add into Probe Request or %NULL
+	 */
+	const u8 *extra_ies;
+
+	/**
+	 * extra_ies_len - Length of extra_ies in octets
+	 */
+	size_t extra_ies_len;
+
+	/**
+	 * freqs - Array of frequencies to scan or %NULL for all frequencies
+	 *
+	 * The frequency is set in MHz. The array is zero-terminated.
+	 */
+	int *freqs;
+
+	/**
+	 * filter_ssids - Filter for reporting SSIDs
+	 *
+	 * This optional parameter can be used to request the driver wrapper to
+	 * filter scan results to include only the specified SSIDs. %NULL
+	 * indicates that no filtering is to be done. This can be used to
+	 * reduce memory needs for scan results in environments that have large
+	 * number of APs with different SSIDs.
+	 *
+	 * The driver wrapper is allowed to take this allocated buffer into its
+	 * own use by setting the pointer to %NULL. In that case, the driver
+	 * wrapper is responsible for freeing the buffer with os_free() once it
+	 * is not needed anymore.
+	 */
+	struct wpa_driver_scan_filter {
+		u8 ssid[32];
+		size_t ssid_len;
+	} *filter_ssids;
+
+	/**
+	 * num_filter_ssids - Number of entries in filter_ssids array
+	 */
+	size_t num_filter_ssids;
+};
+
+/**
+ * struct wpa_driver_auth_params - Authentication parameters
+ * Data for struct wpa_driver_ops::authenticate().
+ */
+struct wpa_driver_auth_params {
+	int freq;
+	const u8 *bssid;
+	const u8 *ssid;
+	size_t ssid_len;
+	int auth_alg;
+	const u8 *ie;
+	size_t ie_len;
+	const u8 *wep_key[4];
+	size_t wep_key_len[4];
+	int wep_tx_keyidx;
+	int local_state_change;
+};
+
 /**
  * struct wpa_driver_associate_params - Association parameters
  * Data for struct wpa_driver_ops::associate().
@@ -157,6 +296,10 @@ struct wpa_driver_associate_params {
 	 * ssid - The selected SSID
 	 */
 	const u8 *ssid;
+
+	/**
+	 * ssid_len - Length of the SSID (1..32)
+	 */
 	size_t ssid_len;
 
 	/**
@@ -185,20 +328,36 @@ struct wpa_driver_associate_params {
 	 * When using WPS, wpa_ie is used for WPS IE instead of WPA/RSN IE.
 	 */
 	const u8 *wpa_ie;
+
 	/**
 	 * wpa_ie_len - length of the wpa_ie
 	 */
 	size_t wpa_ie_len;
 
-	/* The selected pairwise/group cipher and key management
-	 * suites. These are usually ignored if @wpa_ie is used. */
-	wpa_cipher pairwise_suite;
-	wpa_cipher group_suite;
-	wpa_key_mgmt key_mgmt_suite;
+	/**
+	 * pairwise_suite - Selected pairwise cipher suite
+	 *
+	 * This is usually ignored if @wpa_ie is used.
+	 */
+	enum wpa_cipher pairwise_suite;
+
+	/**
+	 * group_suite - Selected group cipher suite
+	 *
+	 * This is usually ignored if @wpa_ie is used.
+	 */
+	enum wpa_cipher group_suite;
+
+	/**
+	 * key_mgmt_suite - Selected key management suite
+	 *
+	 * This is usually ignored if @wpa_ie is used.
+	 */
+	enum wpa_key_mgmt key_mgmt_suite;
 
 	/**
 	 * auth_alg - Allowed authentication algorithms
-	 * Bit field of AUTH_ALG_*
+	 * Bit field of WPA_AUTH_ALG_*
 	 */
 	int auth_alg;
 
@@ -225,11 +384,7 @@ struct wpa_driver_associate_params {
 	/**
 	 * mgmt_frame_protection - IEEE 802.11w management frame protection
 	 */
-	enum {
-		NO_MGMT_FRAME_PROTECTION,
-		MGMT_FRAME_PROTECTION_OPTIONAL,
-		MGMT_FRAME_PROTECTION_REQUIRED
-	} mgmt_frame_protection;
+	enum mfp_options mgmt_frame_protection;
 
 	/**
 	 * ft_ies - IEEE 802.11r / FT information elements
@@ -288,6 +443,23 @@ struct wpa_driver_associate_params {
 	 * be prepared to handle %NULL value as an error.
 	 */
 	const u8 *psk;
+
+	/**
+	 * drop_unencrypted - Enable/disable unencrypted frame filtering
+	 *
+	 * Configure the driver to drop all non-EAPOL frames (both receive and
+	 * transmit paths). Unencrypted EAPOL frames (ethertype 0x888e) must
+	 * still be allowed for key negotiation.
+	 */
+	int drop_unencrypted;
+
+	/**
+	 * prev_bssid - Previously used BSSID in this ESS
+	 *
+	 * When not %NULL, this is a request to use reassociation instead of
+	 * association.
+	 */
+	const u8 *prev_bssid;
 };
 
 /**
@@ -316,59 +488,119 @@ struct wpa_driver_capa {
 
 /* Driver generated WPA/RSN IE */
 #define WPA_DRIVER_FLAGS_DRIVER_IE	0x00000001
+/* Driver needs static WEP key setup after association command */
 #define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002
 #define WPA_DRIVER_FLAGS_USER_SPACE_MLME 0x00000004
 /* Driver takes care of RSN 4-way handshake internally; PMK is configured with
  * struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */
 #define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008
+#define WPA_DRIVER_FLAGS_WIRED		0x00000010
+/* Driver provides separate commands for authentication and association (SME in
+ * wpa_supplicant). */
+#define WPA_DRIVER_FLAGS_SME		0x00000020
+/* Driver supports AP mode */
+#define WPA_DRIVER_FLAGS_AP		0x00000040
+/* Driver needs static WEP key setup after association has been completed */
+#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE	0x00000080
 	unsigned int flags;
+
+	int max_scan_ssids;
+
+	/**
+	 * max_remain_on_chan - Maximum remain-on-channel duration in msec
+	 */
+	unsigned int max_remain_on_chan;
 };
 
 
-#define WPA_CHAN_W_SCAN 0x00000001
-#define WPA_CHAN_W_ACTIVE_SCAN 0x00000002
-#define WPA_CHAN_W_IBSS 0x00000004
+struct hostapd_data;
 
-struct wpa_channel_data {
-	short chan; /* channel number (IEEE 802.11) */
-	short freq; /* frequency in MHz */
-	int flag; /* flag for user space use (WPA_CHAN_*) */
+struct hostap_sta_driver_data {
+	unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes;
+	unsigned long current_tx_rate;
+	unsigned long inactive_msec;
+	unsigned long flags;
+	unsigned long num_ps_buf_frames;
+	unsigned long tx_retry_failed;
+	unsigned long tx_retry_count;
+	int last_rssi;
+	int last_ack_rssi;
 };
 
-#define WPA_RATE_ERP 0x00000001
-#define WPA_RATE_BASIC 0x00000002
-#define WPA_RATE_PREAMBLE2 0x00000004
-#define WPA_RATE_SUPPORTED 0x00000010
-#define WPA_RATE_OFDM 0x00000020
-#define WPA_RATE_CCK 0x00000040
-#define WPA_RATE_MANDATORY 0x00000100
-
-struct wpa_rate_data {
-	int rate; /* rate in 100 kbps */
-	int flags; /* WPA_RATE_ flags */
+struct hostapd_sta_add_params {
+	const u8 *addr;
+	u16 aid;
+	u16 capability;
+	const u8 *supp_rates;
+	size_t supp_rates_len;
+	u16 listen_interval;
+	const struct ieee80211_ht_capabilities *ht_capabilities;
 };
 
-typedef enum {
-	WPA_MODE_IEEE80211B,
-	WPA_MODE_IEEE80211G,
-	WPA_MODE_IEEE80211A,
-	NUM_WPA_MODES
-} wpa_hw_mode;
+struct hostapd_freq_params {
+	int mode;
+	int freq;
+	int channel;
+	int ht_enabled;
+	int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled,
+				 * secondary channel below primary, 1 = HT40
+				 * enabled, secondary channel above primary */
+};
 
-struct wpa_hw_modes {
-	wpa_hw_mode mode;
-	int num_channels;
-	struct wpa_channel_data *channels;
-	int num_rates;
-	struct wpa_rate_data *rates;
+enum wpa_driver_if_type {
+	/**
+	 * WPA_IF_STATION - Station mode interface
+	 */
+	WPA_IF_STATION,
+
+	/**
+	 * WPA_IF_AP_VLAN - AP mode VLAN interface
+	 *
+	 * This interface shares its address and Beacon frame with the main
+	 * BSS.
+	 */
+	WPA_IF_AP_VLAN,
+
+	/**
+	 * WPA_IF_AP_BSS - AP mode BSS interface
+	 *
+	 * This interface has its own address and Beacon frame.
+	 */
+	WPA_IF_AP_BSS,
+};
+
+struct wpa_init_params {
+	const u8 *bssid;
+	const char *ifname;
+	const u8 *ssid;
+	size_t ssid_len;
+	const char *test_socket;
+	int use_pae_group_addr;
+	char **bridge;
+	size_t num_bridge;
+
+	u8 *own_addr; /* buffer for writing own MAC address */
 };
 
 
-struct ieee80211_rx_status {
-        int channel;
-        int ssi;
+struct wpa_bss_params {
+	/** Interface name (for multi-SSID/VLAN support) */
+	const char *ifname;
+	/** Whether IEEE 802.1X or WPA/WPA2 is enabled */
+	int enabled;
+
+	int wpa;
+	int ieee802_1x;
+	int wpa_group;
+	int wpa_pairwise;
+	int wpa_key_mgmt;
+	int rsn_preauth;
 };
 
+#define WPA_STA_AUTHORIZED BIT(0)
+#define WPA_STA_WMM BIT(1)
+#define WPA_STA_SHORT_PREAMBLE BIT(2)
+#define WPA_STA_MFP BIT(3)
 
 /**
  * struct wpa_driver_ops - Driver interface API definition
@@ -413,32 +645,9 @@ struct wpa_driver_ops {
 	 */
 	int (*get_ssid)(void *priv, u8 *ssid);
 
-	/**
-	 * set_wpa - Enable/disable WPA support (OBSOLETE)
-	 * @priv: private driver interface data
-	 * @enabled: 1 = enable, 0 = disable
-	 *
-	 * Returns: 0 on success, -1 on failure
-	 *
-	 * Note: This function is included for backwards compatibility. This is
-	 * called only just after init and just before deinit, so these
-	 * functions can be used to implement same functionality and the driver
-	 * interface need not define this function.
-	 *
-	 * Configure the kernel driver to enable/disable WPA support. This may
-	 * be empty function, if WPA support is always enabled. Common
-	 * configuration items are WPA IE (clearing it when WPA support is
-	 * disabled), Privacy flag configuration for capability field (note:
-	 * this the value need to set in associate handler to allow plaintext
-	 * mode to be used) when trying to associate with, roaming mode (can
-	 * allow wpa_supplicant to control roaming if ap_scan=1 is used;
-	 * however, drivers can also implement roaming if desired, especially
-	 * ap_scan=2 mode is used for this).
-	 */
-	int (*set_wpa)(void *priv, int enabled);
-
 	/**
 	 * set_key - Configure encryption key
+	 * @ifname: Interface name (for multi-SSID/VLAN support)
 	 * @priv: private driver interface data
 	 * @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
 	 *	%WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_PMK);
@@ -480,8 +689,9 @@ struct wpa_driver_ops {
 	 * in driver_*.c set_key() implementation, see driver_ndis.c for an
 	 * example on how this can be done.
 	 */
-	int (*set_key)(void *priv, wpa_alg alg, const u8 *addr,
-		       int key_idx, int set_tx, const u8 *seq, size_t seq_len,
+	int (*set_key)(const char *ifname, void *priv, enum wpa_alg alg,
+		       const u8 *addr, int key_idx, int set_tx,
+		       const u8 *seq, size_t seq_len,
 		       const u8 *key, size_t key_len);
 
 	/**
@@ -542,55 +752,6 @@ struct wpa_driver_ops {
 	 */
 	int (*set_countermeasures)(void *priv, int enabled);
 
-	/**
-	 * set_drop_unencrypted - Enable/disable unencrypted frame filtering
-	 * @priv: private driver interface data
-	 * @enabled: 1 = unencrypted Tx/Rx frames will be dropped, 0 = disabled
-	 *
-	 * Returns: 0 on success, -1 on failure
-	 *
-	 * Configure the driver to drop all non-EAPOL frames (both receive and
-	 * transmit paths). Unencrypted EAPOL frames (ethertype 0x888e) must
-	 * still be allowed for key negotiation.
-	 */
-	int (*set_drop_unencrypted)(void *priv, int enabled);
-
-	/**
-	 * scan - Request the driver to initiate scan
-	 * @priv: private driver interface data
-	 * @ssid: specific SSID to scan for (ProbeReq) or %NULL to scan for
-	 *	all SSIDs (either active scan with broadcast SSID or passive
-	 *	scan
-	 * @ssid_len: length of the SSID
-	 *
-	 * Returns: 0 on success, -1 on failure
-	 *
-	 * Once the scan results are ready, the driver should report scan
-	 * results event for wpa_supplicant which will eventually request the
-	 * results with wpa_driver_get_scan_results().
-	 */
-	int (*scan)(void *priv, const u8 *ssid, size_t ssid_len);
-
-	/**
-	 * get_scan_results - Fetch the latest scan results (old version)
-	 * @priv: private driver interface data
-	 * @results: pointer to buffer for scan results
-	 * @max_size: maximum number of entries (buffer size)
-	 *
-	 * Returns: Number of scan result entries used on success, -1 on
-	 * failure
-	 *
-	 * If scan results include more than max_size BSSes, max_size will be
-	 * returned and the remaining entries will not be included in the
-	 * buffer.
-	 *
-	 * This function is depracated. New driver wrapper implementations
-	 * should implement support for get_scan_results2().
-	 */
-	int (*get_scan_results)(void *priv,
-				struct wpa_scan_result *results,
-				size_t max_size);
-
 	/**
 	 * deauthenticate - Request driver to deauthenticate
 	 * @priv: private driver interface data
@@ -623,27 +784,6 @@ struct wpa_driver_ops {
 	int (*associate)(void *priv,
 			 struct wpa_driver_associate_params *params);
 
-	/**
-	 * set_auth_alg - Set IEEE 802.11 authentication algorithm
-	 * @priv: private driver interface data
-	 * @auth_alg: bit field of AUTH_ALG_*
-	 *
-	 * If the driver supports more than one authentication algorithm at the
-	 * same time, it should configure all supported algorithms. If not, one
-	 * algorithm needs to be selected arbitrarily. Open System
-	 * authentication should be ok for most cases and it is recommended to
-	 * be used if other options are not supported. Static WEP configuration
-	 * may also use Shared Key authentication and LEAP requires its own
-	 * algorithm number. For LEAP, user can make sure that only one
-	 * algorithm is used at a time by configuring LEAP as the only
-	 * supported EAP method. This information is also available in
-	 * associate() params, so set_auth_alg may not be needed in case of
-	 * most drivers.
-	 *
-	 * Returns: 0 on success, -1 on failure
-	 */
-	int (*set_auth_alg)(void *priv, int auth_alg);
-
 	/**
 	 * add_pmkid - Add PMKSA cache entry to the driver
 	 * @priv: private driver interface data
@@ -764,9 +904,9 @@ struct wpa_driver_ops {
 	 * with driver specific functionality. If this function pointer is set,
 	 * l2_packet module is not used at all and the driver interface code is
 	 * responsible for receiving and sending all EAPOL packets. The
-	 * received EAPOL packets are sent to core code by calling
-	 * wpa_supplicant_rx_eapol(). The driver interface is required to
-	 * implement get_mac_addr() handler if send_eapol() is used.
+	 * received EAPOL packets are sent to core code with EVENT_EAPOL_RX
+	 * event. The driver interface is required to implement get_mac_addr()
+	 * handler if send_eapol() is used.
 	 */
 	int (*send_eapol)(void *priv, const u8 *dest, u16 proto,
 			  const u8 *data, size_t data_len);
@@ -813,16 +953,16 @@ struct wpa_driver_ops {
 	 * failure. Caller is responsible for freeing this.
 	 *
 	 * This function is only needed for drivers that export MLME
-	 * (management frame processing) to wpa_supplicant.
+	 * (management frame processing) to %wpa_supplicant or hostapd.
 	 */
-	struct wpa_hw_modes * (*get_hw_feature_data)(void *priv,
-						     u16 *num_modes,
-						     u16 *flags);
+	struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv,
+							 u16 *num_modes,
+							 u16 *flags);
 
 	/**
 	 * set_channel - Set channel
 	 * @priv: Private driver interface data
-	 * @phymode: WPA_MODE_IEEE80211B, ..
+	 * @phymode: HOSTAPD_MODE_IEEE80211B, ..
 	 * @chan: IEEE 802.11 channel number
 	 * @freq: Frequency of the channel in MHz
 	 * Returns: 0 on success, -1 on failure
@@ -830,7 +970,7 @@ struct wpa_driver_ops {
 	 * This function is only needed for drivers that export MLME
 	 * (management frame processing) to wpa_supplicant.
 	 */
-	int (*set_channel)(void *priv, wpa_hw_mode phymode, int chan,
+	int (*set_channel)(void *priv, enum hostapd_hw_mode phymode, int chan,
 			   int freq);
 
 	/**
@@ -940,29 +1080,6 @@ struct wpa_driver_ops {
 	 */
 	 struct wpa_scan_results * (*get_scan_results2)(void *priv);
 
-	/**
-	 * set_probe_req_ie - Set information element(s) for Probe Request
-	 * @priv: private driver interface data
-	 * @ies: Information elements to append or %NULL to remove extra IEs
-	 * @ies_len: Length of the IE buffer in octets
-	 * Returns: 0 on success, -1 on failure
-	 */
-	int (*set_probe_req_ie)(void *priv, const u8 *ies, size_t ies_len);
-
- 	/**
-	 * set_mode - Request driver to set the operating mode
-	 * @priv: private driver interface data
-	 * @mode: Operation mode (infra/ibss) IEEE80211_MODE_*
-	 *
-	 * This handler will be called before any key configuration and call to
-	 * associate() handler in order to allow the operation mode to be
-	 * configured as early as possible. This information is also available
-	 * in associate() params and as such, some driver wrappers may not need
-	 * to implement set_mode() handler.
-	 * Returns: 0 on success, -1 on failure
-	 */
-	int (*set_mode)(void *priv, int mode);
-
 	/**
 	 * set_country - Set country
 	 * @priv: Private driver interface data
@@ -1017,19 +1134,644 @@ struct wpa_driver_ops {
 	 * failure
 	 */
 	struct wpa_interface_info * (*get_interfaces)(void *global_priv);
+
+	/**
+	 * scan2 - Request the driver to initiate scan
+	 * @priv: private driver interface data
+	 * @params: Scan parameters
+	 *
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * Once the scan results are ready, the driver should report scan
+	 * results event for wpa_supplicant which will eventually request the
+	 * results with wpa_driver_get_scan_results2().
+	 */
+	int (*scan2)(void *priv, struct wpa_driver_scan_params *params);
+
+	/**
+	 * authenticate - Request driver to authenticate
+	 * @priv: private driver interface data
+	 * @params: authentication parameters
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This is an optional function that can be used with drivers that
+	 * support separate authentication and association steps, i.e., when
+	 * wpa_supplicant can act as the SME. If not implemented, associate()
+	 * function is expected to take care of IEEE 802.11 authentication,
+	 * too.
+	 */
+	int (*authenticate)(void *priv,
+			    struct wpa_driver_auth_params *params);
+
+	/**
+	 * set_beacon - Set Beacon frame template
+	 * @priv: Private driver interface data
+	 * @head: Beacon head from IEEE 802.11 header to IEs before TIM IE
+	 * @head_len: Length of the head buffer in octets
+	 * @tail: Beacon tail following TIM IE
+	 * @tail_len: Length of the tail buffer in octets
+	 * @dtim_period: DTIM period
+	 * @beacon_int: Beacon interval
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is used to configure Beacon template for the driver in
+	 * AP mode. The driver is responsible for building the full Beacon
+	 * frame by concatenating the head part with TIM IE generated by the
+	 * driver/firmware and finishing with the tail part.
+	 */
+	int (*set_beacon)(void *priv, const u8 *head, size_t head_len,
+			  const u8 *tail, size_t tail_len, int dtim_period,
+			  int beacon_int);
+
+	/**
+	 * hapd_init - Initialize driver interface (hostapd only)
+	 * @hapd: Pointer to hostapd context
+	 * @params: Configuration for the driver wrapper
+	 * Returns: Pointer to private data, %NULL on failure
+	 *
+	 * This function is used instead of init() or init2() when the driver
+	 * wrapper is used withh hostapd.
+	 */
+	void * (*hapd_init)(struct hostapd_data *hapd,
+			    struct wpa_init_params *params);
+
+	/**
+	 * hapd_deinit - Deinitialize driver interface (hostapd only)
+	 * @priv: Private driver interface data from hapd_init()
+	 */
+	void (*hapd_deinit)(void *priv);
+
+	/**
+	 * set_ieee8021x - Enable/disable IEEE 802.1X support (AP only)
+	 * @priv: Private driver interface data
+	 * @params: BSS parameters
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This is an optional function to configure the kernel driver to
+	 * enable/disable IEEE 802.1X support and set WPA/WPA2 parameters. This
+	 * can be left undefined (set to %NULL) if IEEE 802.1X support is
+	 * always enabled and the driver uses set_beacon() to set WPA/RSN IE
+	 * for Beacon frames.
+	 */
+	int (*set_ieee8021x)(void *priv, struct wpa_bss_params *params);
+
+	/**
+	 * set_privacy - Enable/disable privacy (AP only)
+	 * @priv: Private driver interface data
+	 * @enabled: 1 = privacy enabled, 0 = disabled
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This is an optional function to configure privacy field in the
+	 * kernel driver for Beacon frames. This can be left undefined (set to
+	 * %NULL) if the driver uses the Beacon template from set_beacon().
+	 */
+	int (*set_privacy)(void *priv, int enabled);
+
+	/**
+	 * get_seqnum - Fetch the current TSC/packet number (AP only)
+	 * @ifname: The interface name (main or virtual)
+	 * @priv: Private driver interface data
+	 * @addr: MAC address of the station or %NULL for group keys
+	 * @idx: Key index
+	 * @seq: Buffer for returning the latest used TSC/packet number
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is used to fetch the last used TSC/packet number for
+	 * a TKIP, CCMP, or BIP/IGTK key. It is mainly used with group keys, so
+	 * there is no strict requirement on implementing support for unicast
+	 * keys (i.e., addr != %NULL).
+	 */
+	int (*get_seqnum)(const char *ifname, void *priv, const u8 *addr,
+			  int idx, u8 *seq);
+
+	/**
+	 * flush - Flush all association stations (AP only)
+	 * @priv: Private driver interface data
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function requests the driver to disassociate all associated
+	 * stations. This function does not need to be implemented if the
+	 * driver does not process association frames internally.
+	 */
+	int (*flush)(void *priv);
+
+	/**
+	 * set_generic_elem - Add IEs into Beacon/Probe Response frames (AP)
+	 * @priv: Private driver interface data
+	 * @elem: Information elements
+	 * @elem_len: Length of the elem buffer in octets
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This is an optional function to add information elements in the
+	 * kernel driver for Beacon and Probe Response frames. This can be left
+	 * undefined (set to %NULL) if the driver uses the Beacon template from
+	 * set_beacon().
+	 */
+	int (*set_generic_elem)(void *priv, const u8 *elem, size_t elem_len);
+
+	/**
+	 * read_sta_data - Fetch station data (AP only)
+	 * @priv: Private driver interface data
+	 * @data: Buffer for returning station information
+	 * @addr: MAC address of the station
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*read_sta_data)(void *priv, struct hostap_sta_driver_data *data,
+			     const u8 *addr);
+
+	/**
+	 * hapd_send_eapol - Send an EAPOL packet (AP only)
+	 * @priv: private driver interface data
+	 * @addr: Destination MAC address
+	 * @data: EAPOL packet starting with IEEE 802.1X header
+	 * @data_len: Length of the EAPOL packet in octets
+	 * @encrypt: Whether the frame should be encrypted
+	 * @own_addr: Source MAC address
+	 *
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*hapd_send_eapol)(void *priv, const u8 *addr, const u8 *data,
+			       size_t data_len, int encrypt,
+			       const u8 *own_addr);
+
+	/**
+	 * sta_deauth - Deauthenticate a station (AP only)
+	 * @priv: Private driver interface data
+	 * @own_addr: Source address and BSSID for the Deauthentication frame
+	 * @addr: MAC address of the station to deauthenticate
+	 * @reason: Reason code for the Deauthentiation frame
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function requests a specific station to be deauthenticated and
+	 * a Deauthentication frame to be sent to it.
+	 */
+	int (*sta_deauth)(void *priv, const u8 *own_addr, const u8 *addr,
+			  int reason);
+
+	/**
+	 * sta_disassoc - Disassociate a station (AP only)
+	 * @priv: Private driver interface data
+	 * @own_addr: Source address and BSSID for the Disassociation frame
+	 * @addr: MAC address of the station to disassociate
+	 * @reason: Reason code for the Disassociation frame
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function requests a specific station to be disassociated and
+	 * a Disassociation frame to be sent to it.
+	 */
+	int (*sta_disassoc)(void *priv, const u8 *own_addr, const u8 *addr,
+			    int reason);
+
+	/**
+	 * sta_remove - Remove a station entry (AP only)
+	 * @priv: Private driver interface data
+	 * @addr: MAC address of the station to be removed
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*sta_remove)(void *priv, const u8 *addr);
+
+	/**
+	 * hapd_get_ssid - Get the current SSID (AP only)
+	 * @priv: Private driver interface data
+	 * @buf: Buffer for returning the SSID
+	 * @len: Maximum length of the buffer
+	 * Returns: Length of the SSID on success, -1 on failure
+	 *
+	 * This function need not be implemented if the driver uses Beacon
+	 * template from set_beacon() and does not reply to Probe Request
+	 * frames.
+	 */
+	int (*hapd_get_ssid)(void *priv, u8 *buf, int len);
+
+	/**
+	 * hapd_set_ssid - Set SSID (AP only)
+	 * @priv: Private driver interface data
+	 * @buf: SSID
+	 * @len: Length of the SSID in octets
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*hapd_set_ssid)(void *priv, const u8 *buf, int len);
+
+	/**
+	 * hapd_set_countermeasures - Enable/disable TKIP countermeasures (AP)
+	 * @priv: Private driver interface data
+	 * @enabled: 1 = countermeasures enabled, 0 = disabled
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This need not be implemented if the driver does not take care of
+	 * association processing.
+	 */
+	int (*hapd_set_countermeasures)(void *priv, int enabled);
+
+	/**
+	 * sta_add - Add a station entry
+	 * @priv: Private driver interface data
+	 * @params: Station parameters
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is used to add a station entry to the driver once the
+	 * station has completed association. This is only used if the driver
+	 * does not take care of association processing.
+	 */
+	int (*sta_add)(void *priv, struct hostapd_sta_add_params *params);
+
+	/**
+	 * get_inact_sec - Get station inactivity duration (AP only)
+	 * @priv: Private driver interface data
+	 * @addr: Station address
+	 * Returns: Number of seconds station has been inactive, -1 on failure
+	 */
+	int (*get_inact_sec)(void *priv, const u8 *addr);
+
+	/**
+	 * sta_clear_stats - Clear station statistics (AP only)
+	 * @priv: Private driver interface data
+	 * @addr: Station address
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*sta_clear_stats)(void *priv, const u8 *addr);
+
+	/**
+	 * set_freq - Set channel/frequency (AP only)
+	 * @priv: Private driver interface data
+	 * @freq: Channel parameters
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_freq)(void *priv, struct hostapd_freq_params *freq);
+
+	/**
+	 * set_rts - Set RTS threshold
+	 * @priv: Private driver interface data
+	 * @rts: RTS threshold in octets
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_rts)(void *priv, int rts);
+
+	/**
+	 * set_frag - Set fragmentation threshold
+	 * @priv: Private driver interface data
+	 * @frag: Fragmentation threshold in octets
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_frag)(void *priv, int frag);
+
+	/**
+	 * sta_set_flags - Set station flags (AP only)
+	 * @priv: Private driver interface data
+	 * @addr: Station address
+	 * @total_flags: Bitmap of all WPA_STA_* flags currently set
+	 * @flags_or: Bitmap of WPA_STA_* flags to add
+	 * @flags_and: Bitmap of WPA_STA_* flags to us as a mask
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*sta_set_flags)(void *priv, const u8 *addr,
+			     int total_flags, int flags_or, int flags_and);
+
+	/**
+	 * set_rate_sets - Set supported and basic rate sets (AP only)
+	 * @priv: Private driver interface data
+	 * @supp_rates: -1 terminated array of supported rates in 100 kbps
+	 * @basic_rates: -1 terminated array of basic rates in 100 kbps
+	 * @mode: hardware mode (HOSTAPD_MODE_*)
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates,
+			     int mode);
+
+	/**
+	 * set_cts_protect - Set CTS protection mode (AP only)
+	 * @priv: Private driver interface data
+	 * @value: Whether CTS protection is enabled
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_cts_protect)(void *priv, int value);
+
+	/**
+	 * set_preamble - Set preamble mode (AP only)
+	 * @priv: Private driver interface data
+	 * @value: Whether short preamble is enabled
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_preamble)(void *priv, int value);
+
+	/**
+	 * set_short_slot_time - Set short slot time (AP only)
+	 * @priv: Private driver interface data
+	 * @value: Whether short slot time is enabled
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_short_slot_time)(void *priv, int value);
+
+	/**
+	 * set_tx_queue_params - Set TX queue parameters
+	 * @priv: Private driver interface data
+	 * @queue: Queue number
+	 * @aifs: AIFS
+	 * @cw_min: cwMin
+	 * @cw_max: cwMax
+	 * @burst_time: Maximum length for bursting in 0.1 msec units
+	 */
+	int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min,
+				   int cw_max, int burst_time);
+
+	/**
+	 * valid_bss_mask - Validate BSSID mask
+	 * @priv: Private driver interface data
+	 * @addr: Address
+	 * @mask: Mask
+	 * Returns: 0 if mask is valid, -1 if mask is not valid, 1 if mask can
+	 * be used, but the main interface address must be the first address in
+	 * the block if mask is applied
+	 */
+	int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask);
+
+	/**
+	 * if_add - Add a virtual interface
+	 * @priv: Private driver interface data
+	 * @type: Interface type
+	 * @ifname: Interface name for the new virtual interface
+	 * @addr: Local address to use for the interface or %NULL to use the
+	 *	parent interface address
+	 * @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces
+	 * @drv_priv: Pointer for overwriting the driver context or %NULL if
+	 *	not allowed (applies only to %WPA_IF_AP_BSS type)
+	 * @force_ifname: Buffer for returning an interface name that the
+	 *	driver ended up using if it differs from the requested ifname
+	 * @if_addr: Buffer for returning the allocated interface address
+	 *	(this may differ from the requested addr if the driver cannot
+	 *	change interface address)
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*if_add)(void *priv, enum wpa_driver_if_type type,
+		      const char *ifname, const u8 *addr, void *bss_ctx,
+		      void **drv_priv, char *force_ifname, u8 *if_addr);
+
+	/**
+	 * if_remove - Remove a virtual interface
+	 * @priv: Private driver interface data
+	 * @type: Interface type
+	 * @ifname: Interface name of the virtual interface to be removed
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*if_remove)(void *priv, enum wpa_driver_if_type type,
+			 const char *ifname);
+
+	/**
+	 * set_sta_vlan - Bind a station into a specific interface (AP only)
+	 * @priv: Private driver interface data
+	 * @ifname: Interface (main or virtual BSS or VLAN)
+	 * @addr: MAC address of the associated station
+	 * @vlan_id: VLAN ID
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is used to bind a station to a specific virtual
+	 * interface. It is only used if when virtual interfaces are supported,
+	 * e.g., to assign stations to different VLAN interfaces based on
+	 * information from a RADIUS server. This allows separate broadcast
+	 * domains to be used with a single BSS.
+	 */
+	int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname,
+			    int vlan_id);
+
+	/**
+	 * commit - Optional commit changes handler (AP only)
+	 * @priv: driver private data
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This optional handler function can be registered if the driver
+	 * interface implementation needs to commit changes (e.g., by setting
+	 * network interface up) at the end of initial configuration. If set,
+	 * this handler will be called after initial setup has been completed.
+	 */
+	int (*commit)(void *priv);
+
+	/**
+	 * send_ether - Send an ethernet packet (AP only)
+	 * @priv: private driver interface data
+	 * @dst: Destination MAC address
+	 * @src: Source MAC address
+	 * @proto: Ethertype
+	 * @data: EAPOL packet starting with IEEE 802.1X header
+	 * @data_len: Length of the EAPOL packet in octets
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*send_ether)(void *priv, const u8 *dst, const u8 *src, u16 proto,
+			  const u8 *data, size_t data_len);
+
+	/**
+	 * set_radius_acl_auth - Notification of RADIUS ACL change
+	 * @priv: Private driver interface data
+	 * @mac: MAC address of the station
+	 * @accepted: Whether the station was accepted
+	 * @session_timeout: Session timeout for the station
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_radius_acl_auth)(void *priv, const u8 *mac, int accepted, 
+				   u32 session_timeout);
+
+	/**
+	 * set_radius_acl_expire - Notification of RADIUS ACL expiration
+	 * @priv: Private driver interface data
+	 * @mac: MAC address of the station
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_radius_acl_expire)(void *priv, const u8 *mac);
+
+	/**
+	 * set_ht_params - Set HT parameters (AP only)
+	 * @priv: Private driver interface data
+	 * @ht_capab: HT Capabilities IE
+	 * @ht_capab_len: Length of ht_capab in octets
+	 * @ht_oper: HT Operation IE
+	 * @ht_oper_len: Length of ht_oper in octets
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_ht_params)(void *priv,
+			     const u8 *ht_capab, size_t ht_capab_len,
+			     const u8 *ht_oper, size_t ht_oper_len);
+
+	/**
+	 * set_ap_wps_ie - Add WPS IE(s) into Beacon/Probe Response frames (AP)
+	 * @priv: Private driver interface data
+	 * @beacon: WPS IE(s) for Beacon frames or %NULL to remove extra IE(s)
+	 * @proberesp: WPS IE(s) for Probe Response frames or %NULL to remove
+	 *	extra IE(s)
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This is an optional function to add WPS IE in the kernel driver for
+	 * Beacon and Probe Response frames. This can be left undefined (set
+	 * to %NULL) if the driver uses the Beacon template from set_beacon()
+	 * and does not process Probe Request frames.
+	 */
+	int (*set_ap_wps_ie)(void *priv, const struct wpabuf *beacon,
+			     const struct wpabuf *proberesp);
+
+	/**
+	 * set_supp_port - Set IEEE 802.1X Supplicant Port status
+	 * @priv: Private driver interface data
+	 * @authorized: Whether the port is authorized
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_supp_port)(void *priv, int authorized);
+
+	/**
+	 * set_wds_sta - Bind a station into a 4-address WDS (AP only)
+	 * @priv: Private driver interface data
+	 * @addr: MAC address of the associated station
+	 * @aid: Association ID
+	 * @val: 1 = bind to 4-address WDS; 0 = unbind
+	 * Returns: 0 on success, -1 on failure
+	 */
+	int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val);
+
+	/**
+	 * send_action - Transmit an Action frame
+	 * @priv: Private driver interface data
+	 * @freq: Frequency (in MHz) of the channel
+	 * @dst: Destination MAC address (Address 1)
+	 * @src: Source MAC address (Address 2)
+	 * @bssid: BSSID (Address 3)
+	 * @data: Frame body
+	 * @data_len: data length in octets
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This command can be used to request the driver to transmit an action
+	 * frame to the specified destination. If a remain-on-channel duration
+	 * is in progress, the frame is transmitted on that channel. Otherwise,
+	 * the frame is transmitted on the current operational channel if in
+	 * associated state in station mode or if operating as an AP. If none
+	 * of these conditions is in effect, send_action() cannot be used.
+	 */
+	int (*send_action)(void *priv, unsigned int freq,
+			   const u8 *dst, const u8 *src, const u8 *bssid,
+			   const u8 *data, size_t data_len);
+
+	/**
+	 * remain_on_channel - Remain awake on a channel
+	 * @priv: Private driver interface data
+	 * @freq: Frequency (in MHz) of the channel
+	 * @duration: Duration in milliseconds
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This command is used to request the driver to remain awake on the
+	 * specified channel for the specified duration and report received
+	 * Action frames with EVENT_RX_ACTION events. Optionally, received
+	 * Probe Request frames may also be requested to be reported by calling
+	 * probe_req_report(). These will be reported with EVENT_RX_PROBE_REQ.
+	 *
+	 * The driver may not be at the requested channel when this function
+	 * returns, i.e., the return code is only indicating whether the
+	 * request was accepted. The caller will need to wait until the
+	 * EVENT_REMAIN_ON_CHANNEL event indicates that the driver has
+	 * completed the channel change. This may take some time due to other
+	 * need for the radio and the caller should be prepared to timing out
+	 * its wait since there are no guarantees on when this request can be
+	 * executed.
+	 */
+	int (*remain_on_channel)(void *priv, unsigned int freq,
+				 unsigned int duration);
+
+	/**
+	 * cancel_remain_on_channel - Cancel remain-on-channel operation
+	 * @priv: Private driver interface data
+	 *
+	 * This command can be used to cancel a remain-on-channel operation
+	 * before its originally requested duration has passed. This could be
+	 * used, e.g., when remain_on_channel() is used to request extra time
+	 * to receive a response to an Action frame and the response is
+	 * received when there is still unneeded time remaining on the
+	 * remain-on-channel operation.
+	 */
+	int (*cancel_remain_on_channel)(void *priv);
+
+	/**
+	 * probe_req_report - Request Probe Request frames to be indicated
+	 * @priv: Private driver interface data
+	 * @report: Whether to report received Probe Request frames
+	 * Returns: 0 on success, -1 on failure (or if not supported)
+	 *
+	 * This command can be used to request the driver to indicate when
+	 * Probe Request frames are received with EVENT_RX_PROBE_REQ events.
+	 * Since this operation may require extra resources, e.g., due to less
+	 * optimal hardware/firmware RX filtering, many drivers may disable
+	 * Probe Request reporting at least in station mode. This command is
+	 * used to notify the driver when the Probe Request frames need to be
+	 * reported, e.g., during remain-on-channel operations.
+	 */
+	int (*probe_req_report)(void *priv, int report);
+
+	/**
+	 * disable_11b_rates - Set whether IEEE 802.11b rates are used for TX
+	 * @priv: Private driver interface data
+	 * @disabled: Whether IEEE 802.11b rates are disabled
+	 * Returns: 0 on success, -1 on failure (or if not supported)
+	 *
+	 * This command is used to disable IEEE 802.11b rates (1, 2, 5.5, and
+	 * 11 Mbps) as TX rates for data and management frames. This can be
+	 * used to optimize channel use when there is no need to support IEEE
+	 * 802.11b-only devices.
+	 */
+	int (*disable_11b_rates)(void *priv, int disabled);
+
+	/**
+	 * deinit_ap - Deinitialize AP mode
+	 * @priv: Private driver interface data
+	 * Returns: 0 on success, -1 on failure (or if not supported)
+	 *
+	 * This optional function can be used to disable AP mode related
+	 * configuration and change the driver mode to station mode to allow
+	 * normal station operations like scanning to be completed.
+	 */
+	int (*deinit_ap)(void *priv);
+
+	/**
+	 * suspend - Notification on system suspend/hibernate event
+	 * @priv: Private driver interface data
+	 */
+	void (*suspend)(void *priv);
+
+	/**
+	 * resume - Notification on system resume/thaw event
+	 * @priv: Private driver interface data
+	 */
+	void (*resume)(void *priv);
+
+	/**
+	 * signal_monitor - Set signal monitoring parameters
+	 * @priv: Private driver interface data
+	 * @threshold: Threshold value for signal change events; 0 = disabled
+	 * @hysteresis: Minimum change in signal strength before indicating a
+	 *	new event
+	 * Returns: 0 on success, -1 on failure (or if not supported)
+	 *
+	 * This function can be used to configure monitoring of signal strength
+	 * with the current AP. Whenever signal strength drops below the
+	 * %threshold value or increases above it, EVENT_SIGNAL_CHANGE event
+	 * should be generated assuming the signal strength has changed at
+	 * least %hysteresis from the previously indicated signal change event.
+	 */
+	int (*signal_monitor)(void *priv, int threshold, int hysteresis);
+
+	/**
+	 * send_frame - Send IEEE 802.11 frame (testing use only)
+	 * @priv: Private driver interface data
+	 * @data: IEEE 802.11 frame with IEEE 802.11 header
+	 * @data_len: Size of the frame
+	 * @encrypt: Whether to encrypt the frame (if keys are set)
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is only used for debugging purposes and is not
+	 * required to be implemented for normal operations.
+	 */
+	int (*send_frame)(void *priv, const u8 *data, size_t data_len,
+			  int encrypt);
 };
 
-/* Function to check whether a driver is for wired connections */
-static inline int IS_WIRED(const struct wpa_driver_ops *drv)
-{
-	return os_strcmp(drv->name, "wired") == 0 ||
-		os_strcmp(drv->name, "roboswitch") == 0;
-}
 
 /**
  * enum wpa_event_type - Event type for wpa_supplicant_event() calls
  */
-typedef enum wpa_event_type {
+enum wpa_event_type {
 	/**
 	 * EVENT_ASSOC - Association completed
 	 *
@@ -1049,7 +1791,10 @@ typedef enum wpa_event_type {
 	 *
 	 * This event should be called when association is lost either due to
 	 * receiving deauthenticate or disassociate frame from the AP or when
-	 * sending either of these frames to the current AP.
+	 * sending either of these frames to the current AP. If the driver
+	 * supports separate deauthentication event, EVENT_DISASSOC should only
+	 * be used for disassociation and EVENT_DEAUTH for deauthentication.
+	 * In AP mode, union wpa_event_data::disassoc_info is required.
 	 */
 	EVENT_DISASSOC,
 
@@ -1075,7 +1820,8 @@ typedef enum wpa_event_type {
 	 * EVENT_SCAN_RESULTS call. If such event is not available from the
 	 * driver, the driver wrapper code is expected to use a registered
 	 * timeout to generate EVENT_SCAN_RESULTS call after the time that the
-	 * scan is expected to be completed.
+	 * scan is expected to be completed. Optional information about
+	 * completed scan can be provided with union wpa_event_data::scan_info.
 	 */
 	EVENT_SCAN_RESULTS,
 
@@ -1147,8 +1893,161 @@ typedef enum wpa_event_type {
 	 * FT authentication sequence from the AP. The FT IEs are included in
 	 * the extra information in union wpa_event_data::ft_ies.
 	 */
-	EVENT_FT_RESPONSE
-} wpa_event_type;
+	EVENT_FT_RESPONSE,
+
+	/**
+	 * EVENT_IBSS_RSN_START - Request RSN authentication in IBSS
+	 *
+	 * The driver can use this event to inform wpa_supplicant about a STA
+	 * in an IBSS with which protected frames could be exchanged. This
+	 * event starts RSN authentication with the other STA to authenticate
+	 * the STA and set up encryption keys with it.
+	 */
+	EVENT_IBSS_RSN_START,
+
+	/**
+	 * EVENT_AUTH - Authentication result
+	 *
+	 * This event should be called when authentication attempt has been
+	 * completed. This is only used if the driver supports separate
+	 * authentication step (struct wpa_driver_ops::authenticate).
+	 * Information about authentication result is included in
+	 * union wpa_event_data::auth.
+	 */
+	EVENT_AUTH,
+
+	/**
+	 * EVENT_DEAUTH - Authentication lost
+	 *
+	 * This event should be called when authentication is lost either due
+	 * to receiving deauthenticate frame from the AP or when sending that
+	 * frame to the current AP.
+	 * In AP mode, union wpa_event_data::deauth_info is required.
+	 */
+	EVENT_DEAUTH,
+
+	/**
+	 * EVENT_ASSOC_REJECT - Association rejected
+	 *
+	 * This event should be called when (re)association attempt has been
+	 * rejected by the AP. Information about authentication result is
+	 * included in union wpa_event_data::assoc_reject.
+	 */
+	EVENT_ASSOC_REJECT,
+
+	/**
+	 * EVENT_AUTH_TIMED_OUT - Authentication timed out
+	 */
+	EVENT_AUTH_TIMED_OUT,
+
+	/**
+	 * EVENT_ASSOC_TIMED_OUT - Association timed out
+	 */
+	EVENT_ASSOC_TIMED_OUT,
+
+	/**
+	 * EVENT_FT_RRB_RX - FT (IEEE 802.11r) RRB frame received
+	 */
+	EVENT_FT_RRB_RX,
+
+	/**
+	 * EVENT_WPS_BUTTON_PUSHED - Report hardware push button press for WPS
+	 */
+	EVENT_WPS_BUTTON_PUSHED,
+
+	/**
+	 * EVENT_TX_STATUS - Report TX status
+	 */
+	EVENT_TX_STATUS,
+
+	/**
+	 * EVENT_RX_FROM_UNKNOWN - Report RX from unknown STA
+	 */
+	EVENT_RX_FROM_UNKNOWN,
+
+	/**
+	 * EVENT_RX_MGMT - Report RX of a management frame
+	 */
+	EVENT_RX_MGMT,
+
+	/**
+	 * EVENT_RX_ACTION - Action frame received
+	 *
+	 * This event is used to indicate when an Action frame has been
+	 * received. Information about the received frame is included in
+	 * union wpa_event_data::rx_action.
+	 */
+	EVENT_RX_ACTION,
+
+	/**
+	 * EVENT_REMAIN_ON_CHANNEL - Remain-on-channel duration started
+	 *
+	 * This event is used to indicate when the driver has started the
+	 * requested remain-on-channel duration. Information about the
+	 * operation is included in union wpa_event_data::remain_on_channel.
+	 */
+	EVENT_REMAIN_ON_CHANNEL,
+
+	/**
+	 * EVENT_CANCEL_REMAIN_ON_CHANNEL - Remain-on-channel timed out
+	 *
+	 * This event is used to indicate when the driver has completed
+	 * remain-on-channel duration, i.e., may noot be available on the
+	 * requested channel anymore. Information about the
+	 * operation is included in union wpa_event_data::remain_on_channel.
+	 */
+	EVENT_CANCEL_REMAIN_ON_CHANNEL,
+
+	/**
+	 * EVENT_MLME_RX - Report reception of frame for MLME (test use only)
+	 *
+	 * This event is used only by driver_test.c and userspace MLME.
+	 */
+	EVENT_MLME_RX,
+
+	/**
+	 * EVENT_RX_PROBE_REQ - Indicate received Probe Request frame
+	 *
+	 * This event is used to indicate when a Probe Request frame has been
+	 * received. Information about the received frame is included in
+	 * union wpa_event_data::rx_probe_req. The driver is required to report
+	 * these events only after successfully completed probe_req_report()
+	 * commands to request the events (i.e., report parameter is non-zero)
+	 * in station mode. In AP mode, Probe Request frames should always be
+	 * reported.
+	 */
+	EVENT_RX_PROBE_REQ,
+
+	/**
+	 * EVENT_NEW_STA - New wired device noticed
+	 *
+	 * This event is used to indicate that a new device has been detected
+	 * in a network that does not use association-like functionality (i.e.,
+	 * mainly wired Ethernet). This can be used to start EAPOL
+	 * authenticator when receiving a frame from a device. The address of
+	 * the device is included in union wpa_event_data::new_sta.
+	 */
+	EVENT_NEW_STA,
+
+	/**
+	 * EVENT_EAPOL_RX - Report received EAPOL frame
+	 *
+	 * When in AP mode with hostapd, this event is required to be used to
+	 * deliver the receive EAPOL frames from the driver. With
+	 * %wpa_supplicant, this event is used only if the send_eapol() handler
+	 * is used to override the use of l2_packet for EAPOL frame TX.
+	 */
+	EVENT_EAPOL_RX,
+
+	/**
+	 * EVENT_SIGNAL_CHANGE - Indicate change in signal strength
+	 *
+	 * This event is used to indicate changes in the signal strength
+	 * observed in frames received from the current AP if signal strength
+	 * monitoring has been enabled with signal_monitor().
+	 */
+	EVENT_SIGNAL_CHANGE
+};
 
 
 /**
@@ -1175,7 +2074,7 @@ union wpa_event_data {
 		 * This should start with the first IE (fixed fields before IEs
 		 * are not included).
 		 */
-		u8 *req_ies;
+		const u8 *req_ies;
 
 		/**
 		 * req_ies_len - Length of req_ies in bytes
@@ -1193,7 +2092,7 @@ union wpa_event_data {
 		 * This should start with the first IE (fixed fields before IEs
 		 * are not included).
 		 */
-		u8 *resp_ies;
+		const u8 *resp_ies;
 
 		/**
 		 * resp_ies_len - Length of resp_ies in bytes
@@ -1216,18 +2115,61 @@ union wpa_event_data {
 		 * This should start with the first IE (fixed fields before IEs
 		 * are not included).
 		 */
-		u8 *beacon_ies;
+		const u8 *beacon_ies;
 
 		/**
 		 * beacon_ies_len - Length of beacon_ies */
 		size_t beacon_ies_len;
+
+		/**
+		 * freq - Frequency of the operational channel in MHz
+		 */
+		unsigned int freq;
+
+		/**
+		 * addr - Station address (for AP mode)
+		 */
+		const u8 *addr;
 	} assoc_info;
 
+	/**
+	 * struct disassoc_info - Data for EVENT_DISASSOC events
+	 */
+	struct disassoc_info {
+		/**
+		 * addr - Station address (for AP mode)
+		 */
+		const u8 *addr;
+
+		/**
+		 * reason_code - Reason Code (host byte order) used in
+		 *	Deauthentication frame
+		 */
+		u16 reason_code;
+	} disassoc_info;
+
+	/**
+	 * struct deauth_info - Data for EVENT_DEAUTH events
+	 */
+	struct deauth_info {
+		/**
+		 * addr - Station address (for AP mode)
+		 */
+		const u8 *addr;
+
+		/**
+		 * reason_code - Reason Code (host byte order) used in
+		 *	Deauthentication frame
+		 */
+		u16 reason_code;
+	} deauth_info;
+
 	/**
 	 * struct michael_mic_failure - Data for EVENT_MICHAEL_MIC_FAILURE
 	 */
 	struct michael_mic_failure {
 		int unicast;
+		const u8 *src;
 	} michael_mic_failure;
 
 	/**
@@ -1273,7 +2215,228 @@ union wpa_event_data {
 		size_t ies_len;
 		int ft_action;
 		u8 target_ap[ETH_ALEN];
+		/** Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request */
+		const u8 *ric_ies;
+		/** Length of ric_ies buffer in octets */
+		size_t ric_ies_len;
 	} ft_ies;
+
+	/**
+	 * struct ibss_rsn_start - Data for EVENT_IBSS_RSN_START
+	 */
+	struct ibss_rsn_start {
+		u8 peer[ETH_ALEN];
+	} ibss_rsn_start;
+
+	/**
+	 * struct auth_info - Data for EVENT_AUTH events
+	 */
+	struct auth_info {
+		u8 peer[ETH_ALEN];
+		u16 auth_type;
+		u16 status_code;
+		const u8 *ies;
+		size_t ies_len;
+	} auth;
+
+	/**
+	 * struct assoc_reject - Data for EVENT_ASSOC_REJECT events
+	 */
+	struct assoc_reject {
+		/**
+		 * resp_ies - (Re)Association Response IEs
+		 *
+		 * Optional association data from the driver. This data is not
+		 * required WPA, but may be useful for some protocols and as
+		 * such, should be reported if this is available to the driver
+		 * interface.
+		 *
+		 * This should start with the first IE (fixed fields before IEs
+		 * are not included).
+		 */
+		u8 *resp_ies;
+
+		/**
+		 * resp_ies_len - Length of resp_ies in bytes
+		 */
+		size_t resp_ies_len;
+
+		/**
+		 * status_code - Status Code from (Re)association Response
+		 */
+		u16 status_code;
+	} assoc_reject;
+
+	struct timeout_event {
+		u8 addr[ETH_ALEN];
+	} timeout_event;
+
+	/**
+	 * struct ft_rrb_rx - Data for EVENT_FT_RRB_RX events
+	 */
+	struct ft_rrb_rx {
+		const u8 *src;
+		const u8 *data;
+		size_t data_len;
+	} ft_rrb_rx;
+
+	/**
+	 * struct tx_status - Data for EVENT_TX_STATUS events
+	 */
+	struct tx_status {
+		u16 type;
+		u16 stype;
+		const u8 *dst;
+		const u8 *data;
+		size_t data_len;
+		int ack;
+	} tx_status;
+
+	/**
+	 * struct rx_from_unknown - Data for EVENT_RX_FROM_UNKNOWN events
+	 */
+	struct rx_from_unknown {
+		const u8 *frame;
+		size_t len;
+	} rx_from_unknown;
+
+	/**
+	 * struct rx_mgmt - Data for EVENT_RX_MGMT events
+	 */
+	struct rx_mgmt {
+		const u8 *frame;
+		size_t frame_len;
+		u32 datarate;
+		u32 ssi_signal;
+	} rx_mgmt;
+
+	/**
+	 * struct rx_action - Data for EVENT_RX_ACTION events
+	 */
+	struct rx_action {
+		/**
+		 * da - Destination address of the received Action frame
+		 */
+		const u8 *da;
+
+		/**
+		 * sa - Source address of the received Action frame
+		 */
+		const u8 *sa;
+
+		/**
+		 * bssid - Address 3 of the received Action frame
+		 */
+		const u8 *bssid;
+
+		/**
+		 * category - Action frame category
+		 */
+		u8 category;
+
+		/**
+		 * data - Action frame body after category field
+		 */
+		const u8 *data;
+
+		/**
+		 * len - Length of data in octets
+		 */
+		size_t len;
+
+		/**
+		 * freq - Frequency (in MHz) on which the frame was received
+		 */
+		int freq;
+	} rx_action;
+
+	/**
+	 * struct remain_on_channel - Data for EVENT_REMAIN_ON_CHANNEL events
+	 *
+	 * This is also used with EVENT_CANCEL_REMAIN_ON_CHANNEL events.
+	 */
+	struct remain_on_channel {
+		/**
+		 * freq - Channel frequency in MHz
+		 */
+		unsigned int freq;
+
+		/**
+		 * duration - Duration to remain on the channel in milliseconds
+		 */
+		unsigned int duration;
+	} remain_on_channel;
+
+	/**
+	 * struct scan_info - Optional data for EVENT_SCAN_RESULTS events
+	 * @aborted: Whether the scan was aborted
+	 * @freqs: Scanned frequencies in MHz (%NULL = all channels scanned)
+	 * @num_freqs: Number of entries in freqs array
+	 * @ssids: Scanned SSIDs (%NULL or zero-length SSID indicates wildcard
+	 *	SSID)
+	 * @num_ssids: Number of entries in ssids array
+	 */
+	struct scan_info {
+		int aborted;
+		const int *freqs;
+		size_t num_freqs;
+		struct wpa_driver_scan_ssid ssids[WPAS_MAX_SCAN_SSIDS];
+		size_t num_ssids;
+	} scan_info;
+
+	/**
+	 * struct mlme_rx - Data for EVENT_MLME_RX events
+	 */
+	struct mlme_rx {
+		const u8 *buf;
+		size_t len;
+		int freq;
+		int channel;
+		int ssi;
+	} mlme_rx;
+
+	/**
+	 * struct rx_probe_req - Data for EVENT_RX_PROBE_REQ events
+	 */
+	struct rx_probe_req {
+		/**
+		 * sa - Source address of the received Probe Request frame
+		 */
+		const u8 *sa;
+
+		/**
+		 * ie - IEs from the Probe Request body
+		 */
+		const u8 *ie;
+
+		/**
+		 * ie_len - Length of ie buffer in octets
+		 */
+		size_t ie_len;
+	} rx_probe_req;
+
+	/**
+	 * struct new_sta - Data for EVENT_NEW_STA events
+	 */
+	struct new_sta {
+		const u8 *addr;
+	} new_sta;
+
+	/**
+	 * struct eapol_rx - Data for EVENT_EAPOL_RX events
+	 */
+	struct eapol_rx {
+		const u8 *src;
+		const u8 *data;
+		size_t data_len;
+	} eapol_rx;
+
+	/**
+	 * struct signal_change - Data for EVENT_SIGNAL_CHANGE events
+	 */
+	struct signal_change {
+		int above_threshold;
+	} signal_change;
 };
 
 /**
@@ -1286,40 +2449,43 @@ union wpa_event_data {
  * Driver wrapper code should call this function whenever an event is received
  * from the driver.
  */
-void wpa_supplicant_event(void *ctx, wpa_event_type event,
+void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 			  union wpa_event_data *data);
 
-/**
- * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
- * @ctx: Context pointer (wpa_s); this is the ctx variable registered
- *	with struct wpa_driver_ops::init()
- * @src_addr: Source address of the EAPOL frame
- * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
- * @len: Length of the EAPOL data
- *
- * This function is called for each received EAPOL frame. Most driver
- * interfaces rely on more generic OS mechanism for receiving frames through
- * l2_packet, but if such a mechanism is not available, the driver wrapper may
- * take care of received EAPOL frames and deliver them to the core supplicant
- * code by calling this function.
+
+/*
+ * The following inline functions are provided for convenience to simplify
+ * event indication for some of the common events.
  */
-void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
-			     const u8 *buf, size_t len);
 
-void wpa_supplicant_sta_rx(void *ctx, const u8 *buf, size_t len,
-			   struct ieee80211_rx_status *rx_status);
-void wpa_supplicant_sta_free_hw_features(struct wpa_hw_modes *hw_features,
-					 size_t num_hw_features);
+static inline void drv_event_assoc(void *ctx, const u8 *addr, const u8 *ie,
+				   size_t ielen)
+{
+	union wpa_event_data event;
+	os_memset(&event, 0, sizeof(event));
+	event.assoc_info.req_ies = ie;
+	event.assoc_info.req_ies_len = ielen;
+	event.assoc_info.addr = addr;
+	wpa_supplicant_event(ctx, EVENT_ASSOC, &event);
+}
 
-const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie);
-#define WPA_IE_VENDOR_TYPE 0x0050f201
-#define WPS_IE_VENDOR_TYPE 0x0050f204
-const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
-				  u32 vendor_type);
-struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
-					     u32 vendor_type);
-int wpa_scan_get_max_rate(const struct wpa_scan_res *res);
-void wpa_scan_results_free(struct wpa_scan_results *res);
-void wpa_scan_sort_results(struct wpa_scan_results *res);
+static inline void drv_event_disassoc(void *ctx, const u8 *addr)
+{
+	union wpa_event_data event;
+	os_memset(&event, 0, sizeof(event));
+	event.disassoc_info.addr = addr;
+	wpa_supplicant_event(ctx, EVENT_DISASSOC, &event);
+}
+
+static inline void drv_event_eapol_rx(void *ctx, const u8 *src, const u8 *data,
+				      size_t data_len)
+{
+	union wpa_event_data event;
+	os_memset(&event, 0, sizeof(event));
+	event.eapol_rx.src = src;
+	event.eapol_rx.data = data;
+	event.eapol_rx.data_len = data_len;
+	wpa_supplicant_event(ctx, EVENT_EAPOL_RX, &event);
+}
 
 #endif /* DRIVER_H */
diff --git a/contrib/wpa/src/drivers/driver_ndis.c b/contrib/wpa/src/drivers/driver_ndis.c
index 0bda20a36d1c..9344a99394d0 100644
--- a/contrib/wpa/src/drivers/driver_ndis.c
+++ b/contrib/wpa/src/drivers/driver_ndis.c
@@ -40,7 +40,7 @@ int close(int fd);
 #include "common.h"
 #include "driver.h"
 #include "eloop.h"
-#include "ieee802_11_defs.h"
+#include "common/ieee802_11_defs.h"
 #include "driver_ndis.h"
 
 int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
@@ -354,6 +354,47 @@ typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST {
 #endif /* OID_802_11_CAPABILITY */
 
 
+#ifndef OID_DOT11_CURRENT_OPERATION_MODE
+/* Native 802.11 OIDs */
+#define OID_DOT11_NDIS_START 0x0D010300
+#define OID_DOT11_CURRENT_OPERATION_MODE (OID_DOT11_NDIS_START + 8)
+#define OID_DOT11_SCAN_REQUEST (OID_DOT11_NDIS_START + 11)
+
+typedef enum _DOT11_BSS_TYPE {
+	dot11_BSS_type_infrastructure = 1,
+	dot11_BSS_type_independent = 2,
+	dot11_BSS_type_any = 3
+} DOT11_BSS_TYPE, * PDOT11_BSS_TYPE;
+
+typedef UCHAR DOT11_MAC_ADDRESS[6];
+typedef DOT11_MAC_ADDRESS * PDOT11_MAC_ADDRESS;
+
+typedef enum _DOT11_SCAN_TYPE {
+	dot11_scan_type_active = 1,
+	dot11_scan_type_passive = 2,
+	dot11_scan_type_auto = 3,
+	dot11_scan_type_forced = 0x80000000
+} DOT11_SCAN_TYPE, * PDOT11_SCAN_TYPE;
+
+typedef struct _DOT11_SCAN_REQUEST_V2 {
+	DOT11_BSS_TYPE dot11BSSType;
+	DOT11_MAC_ADDRESS dot11BSSID;
+	DOT11_SCAN_TYPE dot11ScanType;
+	BOOLEAN bRestrictedScan;
+	ULONG udot11SSIDsOffset;
+	ULONG uNumOfdot11SSIDs;
+	BOOLEAN bUseRequestIE;
+	ULONG uRequestIDsOffset;
+	ULONG uNumOfRequestIDs;
+	ULONG uPhyTypeInfosOffset;
+	ULONG uNumOfPhyTypeInfos;
+	ULONG uIEsOffset;
+	ULONG uIEsLength;
+	UCHAR ucBuffer[1];
+} DOT11_SCAN_REQUEST_V2, * PDOT11_SCAN_REQUEST_V2;
+
+#endif /* OID_DOT11_CURRENT_OPERATION_MODE */
+
 #ifdef CONFIG_USE_NDISUIO
 #ifndef _WIN32_WCE
 #ifdef __MINGW32_VERSION
@@ -699,13 +740,6 @@ static int wpa_driver_ndis_disassociate(void *priv, const u8 *addr,
 }
 
 
-static int wpa_driver_ndis_set_wpa(void *priv, int enabled)
-{
-	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
-	return 0;
-}
-
-
 static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
@@ -713,11 +747,35 @@ static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx)
 }
 
 
-static int wpa_driver_ndis_scan(void *priv, const u8 *ssid, size_t ssid_len)
+static int wpa_driver_ndis_scan_native80211(
+	struct wpa_driver_ndis_data *drv,
+	struct wpa_driver_scan_params *params)
+{
+	DOT11_SCAN_REQUEST_V2 req;
+	int res;
+
+	os_memset(&req, 0, sizeof(req));
+	req.dot11BSSType = dot11_BSS_type_any;
+	os_memset(req.dot11BSSID, 0xff, ETH_ALEN);
+	req.dot11ScanType = dot11_scan_type_auto;
+	res = ndis_set_oid(drv, OID_DOT11_SCAN_REQUEST, (char *) &req,
+			   sizeof(req));
+	eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx);
+	eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv,
+			       drv->ctx);
+	return res;
+}
+
+
+static int wpa_driver_ndis_scan(void *priv,
+				struct wpa_driver_scan_params *params)
 {
 	struct wpa_driver_ndis_data *drv = priv;
 	int res;
 
+	if (drv->native80211)
+		return wpa_driver_ndis_scan_native80211(drv, params);
+
 	if (!drv->radio_enabled) {
 		wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first"
 			   " scan");
@@ -735,6 +793,25 @@ static int wpa_driver_ndis_scan(void *priv, const u8 *ssid, size_t ssid_len)
 }
 
 
+static const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
+{
+	const u8 *end, *pos;
+
+	pos = (const u8 *) (res + 1);
+	end = pos + res->ie_len;
+
+	while (pos + 1 < end) {
+		if (pos + 2 + pos[1] > end)
+			break;
+		if (pos[0] == ie)
+			return pos;
+		pos += 2 + pos[1];
+	}
+
+	return NULL;
+}
+
+
 static struct wpa_scan_res * wpa_driver_ndis_add_scan_ssid(
 	struct wpa_scan_res *r, NDIS_802_11_SSID *ssid)
 {
@@ -913,7 +990,8 @@ static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv,
 }
 
 
-static int wpa_driver_ndis_set_key(void *priv, wpa_alg alg, const u8 *addr,
+static int wpa_driver_ndis_set_key(const char *ifname, void *priv,
+				   enum wpa_alg alg, const u8 *addr,
 				   int key_idx, int set_tx,
 				   const u8 *seq, size_t seq_len,
 				   const u8 *key, size_t key_len)
@@ -1021,7 +1099,8 @@ wpa_driver_ndis_associate(void *priv,
 				continue;
 			wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP "
 				   "key %d", i);
-			wpa_driver_ndis_set_key(drv, WPA_ALG_WEP, bcast, i,
+			wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP,
+						bcast, i,
 						i == params->wep_tx_keyidx,
 						NULL, 0, params->wep_key[i],
 						params->wep_key_len[i]);
@@ -1029,8 +1108,8 @@ wpa_driver_ndis_associate(void *priv,
 	}
 
 	if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
-		if (params->auth_alg & AUTH_ALG_SHARED_KEY) {
-			if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM)
+		if (params->auth_alg & WPA_AUTH_ALG_SHARED) {
+			if (params->auth_alg & WPA_AUTH_ALG_OPEN)
 				auth_mode = Ndis802_11AuthModeAutoSwitch;
 			else
 				auth_mode = Ndis802_11AuthModeShared;
@@ -2802,16 +2881,31 @@ static void * wpa_driver_ndis_init(void *ctx, const char *ifname)
 	mode = Ndis802_11Infrastructure;
 	if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
 			 (char *) &mode, sizeof(mode)) < 0) {
+		char buf[8];
+		int res;
 		wpa_printf(MSG_DEBUG, "NDIS: Failed to set "
 			   "OID_802_11_INFRASTRUCTURE_MODE (%d)",
 			   (int) mode);
 		/* Try to continue anyway */
 
-		if (!drv->has_capability && drv->capa.enc == 0) {
+		res = ndis_get_oid(drv, OID_DOT11_CURRENT_OPERATION_MODE, buf,
+				   sizeof(buf));
+		if (res > 0) {
+			wpa_printf(MSG_INFO, "NDIS: The driver seems to use "
+				   "Native 802.11 OIDs. These are not yet "
+				   "fully supported.");
+			drv->native80211 = 1;
+		} else if (!drv->has_capability || drv->capa.enc == 0) {
+			/*
+			 * Note: This will also happen with NDIS 6 drivers with
+			 * Vista.
+			 */
 			wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide "
 				   "any wireless capabilities - assume it is "
 				   "a wired interface");
 			drv->wired = 1;
+			drv->capa.flags |= WPA_DRIVER_FLAGS_WIRED;
+			drv->has_capability = 1;
 			ndis_add_multicast(drv);
 		}
 	}
@@ -3097,19 +3191,14 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
 	"Windows NDIS driver",
 	wpa_driver_ndis_get_bssid,
 	wpa_driver_ndis_get_ssid,
-	wpa_driver_ndis_set_wpa,
 	wpa_driver_ndis_set_key,
 	wpa_driver_ndis_init,
 	wpa_driver_ndis_deinit,
 	NULL /* set_param */,
 	NULL /* set_countermeasures */,
-	NULL /* set_drop_unencrypted */,
-	wpa_driver_ndis_scan,
-	NULL /* get_scan_results */,
 	wpa_driver_ndis_deauthenticate,
 	wpa_driver_ndis_disassociate,
 	wpa_driver_ndis_associate,
-	NULL /* set_auth_alg */,
 	wpa_driver_ndis_add_pmkid,
 	wpa_driver_ndis_remove_pmkid,
 	wpa_driver_ndis_flush_pmkid,
@@ -3130,11 +3219,61 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
 	NULL /* update_ft_ies */,
 	NULL /* send_ft_action */,
 	wpa_driver_ndis_get_scan_results,
-	NULL /* set_probe_req_ie */,
-	NULL /* set_mode */,
 	NULL /* set_country */,
 	NULL /* global_init */,
 	NULL /* global_deinit */,
 	NULL /* init2 */,
-	wpa_driver_ndis_get_interfaces
+	wpa_driver_ndis_get_interfaces,
+	wpa_driver_ndis_scan,
+	NULL /* authenticate */,
+	NULL /* set_beacon */,
+	NULL /* hapd_init */,
+	NULL /* hapd_deinit */,
+	NULL /* set_ieee8021x */,
+	NULL /* set_privacy */,
+	NULL /* get_seqnum */,
+	NULL /* flush */,
+	NULL /* set_generic_elem */,
+	NULL /* read_sta_data */,
+	NULL /* hapd_send_eapol */,
+	NULL /* sta_deauth */,
+	NULL /* sta_disassoc */,
+	NULL /* sta_remove */,
+	NULL /* hapd_get_ssid */,
+	NULL /* hapd_set_ssid */,
+	NULL /* hapd_set_countermeasures */,
+	NULL /* sta_add */,
+	NULL /* get_inact_sec */,
+	NULL /* sta_clear_stats */,
+	NULL /* set_freq */,
+	NULL /* set_rts */,
+	NULL /* set_frag */,
+	NULL /* sta_set_flags */,
+	NULL /* set_rate_sets */,
+	NULL /* set_cts_protect */,
+	NULL /* set_preamble */,
+	NULL /* set_short_slot_time */,
+	NULL /* set_tx_queue_params */,
+	NULL /* valid_bss_mask */,
+	NULL /* if_add */,
+	NULL /* if_remove */,
+	NULL /* set_sta_vlan */,
+	NULL /* commit */,
+	NULL /* send_ether */,
+	NULL /* set_radius_acl_auth */,
+	NULL /* set_radius_acl_expire */,
+	NULL /* set_ht_params */,
+	NULL /* set_ap_wps_ie */,
+	NULL /* set_supp_port */,
+	NULL /* set_wds_sta */,
+	NULL /* send_action */,
+	NULL /* remain_on_channel */,
+	NULL /* cancel_remain_on_channel */,
+	NULL /* probe_req_report */,
+	NULL /* disable_11b_rates */,
+	NULL /* deinit_ap */,
+	NULL /* suspend */,
+	NULL /* resume */,
+	NULL /* signal_monitor */,
+	NULL /* send_frame */
 };
diff --git a/contrib/wpa/src/drivers/driver_ndis.h b/contrib/wpa/src/drivers/driver_ndis.h
index cdce4bac85ab..f263f0e43585 100644
--- a/contrib/wpa/src/drivers/driver_ndis.h
+++ b/contrib/wpa/src/drivers/driver_ndis.h
@@ -52,6 +52,7 @@ struct wpa_driver_ndis_data {
 	struct ndis_pmkid_entry *pmkid;
 	char *adapter_desc;
 	int wired;
+	int native80211;
 	int mode;
 	int wzc_disabled;
 	int oid_bssid_set;
diff --git a/contrib/wpa/src/drivers/driver_ndiswrapper.c b/contrib/wpa/src/drivers/driver_ndiswrapper.c
index b5c534a74d08..cd2f61e468a0 100644
--- a/contrib/wpa/src/drivers/driver_ndiswrapper.c
+++ b/contrib/wpa/src/drivers/driver_ndiswrapper.c
@@ -33,9 +33,8 @@ struct wpa_driver_ndiswrapper_data {
 };
 
 
-struct wpa_key
-{
-	wpa_alg alg;
+struct wpa_key {
+	enum wpa_alg alg;
 	const u8 *addr;
 	int key_index;
 	int set_tx;
@@ -45,17 +44,16 @@ struct wpa_key
 	size_t key_len;
 };
 
-struct wpa_assoc_info
-{
+struct wpa_assoc_info {
 	const u8 *bssid;
 	const u8 *ssid;
 	size_t ssid_len;
 	int freq;
 	const u8 *wpa_ie;
 	size_t wpa_ie_len;
-	wpa_cipher pairwise_suite;
-	wpa_cipher group_suite;
-	wpa_key_mgmt key_mgmt_suite;
+	enum wpa_cipher pairwise_suite;
+	enum wpa_cipher group_suite;
+	enum wpa_key_mgmt key_mgmt_suite;
 	int auth_alg;
 	int mode;
 };
@@ -73,6 +71,8 @@ struct wpa_assoc_info
 #define WPA_DEINIT			SIOCIWFIRSTPRIV+10
 #define WPA_GET_CAPA		 	SIOCIWFIRSTPRIV+11
 
+static int wpa_ndiswrapper_set_auth_alg(void *priv, int auth_alg);
+
 static int get_socket(void)
 {
 	static const int families[] = {
@@ -111,7 +111,8 @@ static int wpa_ndiswrapper_set_wpa(void *priv, int enabled)
 	return ret;
 }
 
-static int wpa_ndiswrapper_set_key(void *priv, wpa_alg alg, const u8 *addr,
+static int wpa_ndiswrapper_set_key(const char *ifname, void *priv,
+				   enum wpa_alg alg, const u8 *addr,
 				   int key_idx, int set_tx,
 				   const u8 *seq, size_t seq_len,
 				   const u8 *key, size_t key_len)
@@ -146,8 +147,8 @@ static int wpa_ndiswrapper_set_key(void *priv, wpa_alg alg, const u8 *addr,
 		 * did not associate. Try to make sure the keys are cleared so
 		 * that plaintext APs can be used in all cases.
 		 */
-		wpa_driver_wext_set_key(drv->wext, alg, addr, key_idx, set_tx,
-					seq, seq_len, key, key_len);
+		wpa_driver_wext_set_key(ifname, drv->wext, alg, addr, key_idx,
+					set_tx, seq, seq_len, key, key_len);
 	}
 
 	return ret;
@@ -223,6 +224,12 @@ wpa_ndiswrapper_associate(void *priv,
 	struct wpa_assoc_info wpa_assoc_info;
 	struct iwreq priv_req;
 
+	if (wpa_ndiswrapper_set_drop_unencrypted(drv,
+						 params->drop_unencrypted) < 0)
+		ret = -1;
+	if (wpa_ndiswrapper_set_auth_alg(drv, params->auth_alg) < 0)
+		ret = -1;
+
 	os_memset(&priv_req, 0, sizeof(priv_req));
 	os_memset(&wpa_assoc_info, 0, sizeof(wpa_assoc_info));
 
@@ -274,10 +281,11 @@ static int wpa_ndiswrapper_get_ssid(void *priv, u8 *ssid)
 }
 
 
-static int wpa_ndiswrapper_scan(void *priv, const u8 *ssid, size_t ssid_len)
+static int wpa_ndiswrapper_scan(void *priv,
+				struct wpa_driver_scan_params *params)
 {
 	struct wpa_driver_ndiswrapper_data *drv = priv;
-	return wpa_driver_wext_scan(drv->wext, ssid, ssid_len);
+	return wpa_driver_wext_scan(drv->wext, params);
 }
 
 
@@ -334,6 +342,8 @@ static void * wpa_ndiswrapper_init(void *ctx, const char *ifname)
 		return NULL;
 	}
 
+	wpa_ndiswrapper_set_wpa(drv, 1);
+
 	return drv;
 }
 
@@ -341,6 +351,7 @@ static void * wpa_ndiswrapper_init(void *ctx, const char *ifname)
 static void wpa_ndiswrapper_deinit(void *priv)
 {
 	struct wpa_driver_ndiswrapper_data *drv = priv;
+	wpa_ndiswrapper_set_wpa(drv, 0);
 	wpa_driver_wext_deinit(drv->wext);
 	close(drv->sock);
 	os_free(drv);
@@ -350,18 +361,15 @@ static void wpa_ndiswrapper_deinit(void *priv)
 const struct wpa_driver_ops wpa_driver_ndiswrapper_ops = {
 	.name = "ndiswrapper",
 	.desc = "Linux ndiswrapper (deprecated; use wext)",
-	.set_wpa = wpa_ndiswrapper_set_wpa,
 	.set_key = wpa_ndiswrapper_set_key,
 	.set_countermeasures = wpa_ndiswrapper_set_countermeasures,
-	.set_drop_unencrypted = wpa_ndiswrapper_set_drop_unencrypted,
 	.deauthenticate = wpa_ndiswrapper_deauthenticate,
 	.disassociate = wpa_ndiswrapper_disassociate,
 	.associate = wpa_ndiswrapper_associate,
-	.set_auth_alg = wpa_ndiswrapper_set_auth_alg,
 
 	.get_bssid = wpa_ndiswrapper_get_bssid,
 	.get_ssid = wpa_ndiswrapper_get_ssid,
-	.scan = wpa_ndiswrapper_scan,
+	.scan2 = wpa_ndiswrapper_scan,
 	.get_scan_results2 = wpa_ndiswrapper_get_scan_results,
 	.init = wpa_ndiswrapper_init,
 	.deinit = wpa_ndiswrapper_deinit,
diff --git a/contrib/wpa/src/drivers/driver_wired.c b/contrib/wpa/src/drivers/driver_wired.c
index 098991a1a44d..2b197f0ab6c7 100644
--- a/contrib/wpa/src/drivers/driver_wired.c
+++ b/contrib/wpa/src/drivers/driver_wired.c
@@ -1,6 +1,7 @@
 /*
- * WPA Supplicant - wired Ethernet driver interface
- * Copyright (c) 2005-2007, Jouni Malinen 
+ * Wired Ethernet driver interface
+ * Copyright (c) 2005-2009, Jouni Malinen 
+ * Copyright (c) 2004, Gunter Burchardt 
  *
  * 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
@@ -17,27 +18,374 @@
 #include 
 #ifdef __linux__
 #include 
+#include 
+#include 
 #endif /* __linux__ */
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
 #include 
-#endif /* defined(__FreeBSD__) || defined(__DragonFly__) */
+#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */
 
 #include "common.h"
+#include "eloop.h"
 #include "driver.h"
 
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
+struct ieee8023_hdr {
+	u8 dest[6];
+	u8 src[6];
+	u16 ethertype;
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
 
 static const u8 pae_group_addr[ETH_ALEN] =
 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
 
 
 struct wpa_driver_wired_data {
-	void *ctx;
-	int pf_sock;
 	char ifname[IFNAMSIZ + 1];
+	void *ctx;
+
+	int sock; /* raw packet socket for driver access */
+	int dhcp_sock; /* socket for dhcp packets */
+	int use_pae_group_addr;
+
+	int pf_sock;
 	int membership, multi, iff_allmulti, iff_up;
 };
 
 
+/* TODO: detecting new devices should eventually be changed from using DHCP
+ * snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
+ * based on ebtables, etc. */
+
+struct dhcp_message {
+	u_int8_t op;
+	u_int8_t htype;
+	u_int8_t hlen;
+	u_int8_t hops;
+	u_int32_t xid;
+	u_int16_t secs;
+	u_int16_t flags;
+	u_int32_t ciaddr;
+	u_int32_t yiaddr;
+	u_int32_t siaddr;
+	u_int32_t giaddr;
+	u_int8_t chaddr[16];
+	u_int8_t sname[64];
+	u_int8_t file[128];
+	u_int32_t cookie;
+	u_int8_t options[308]; /* 312 - cookie */
+};
+
+
+static int wired_multicast_membership(int sock, int ifindex,
+				      const u8 *addr, int add)
+{
+#ifdef __linux__
+	struct packet_mreq mreq;
+
+	if (sock < 0)
+		return -1;
+
+	os_memset(&mreq, 0, sizeof(mreq));
+	mreq.mr_ifindex = ifindex;
+	mreq.mr_type = PACKET_MR_MULTICAST;
+	mreq.mr_alen = ETH_ALEN;
+	os_memcpy(mreq.mr_address, addr, ETH_ALEN);
+
+	if (setsockopt(sock, SOL_PACKET,
+		       add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
+		       &mreq, sizeof(mreq)) < 0) {
+		perror("setsockopt");
+		return -1;
+	}
+	return 0;
+#else /* __linux__ */
+	return -1;
+#endif /* __linux__ */
+}
+
+
+#ifdef __linux__
+static void handle_data(void *ctx, unsigned char *buf, size_t len)
+{
+#ifdef HOSTAPD
+	struct ieee8023_hdr *hdr;
+	u8 *pos, *sa;
+	size_t left;
+	union wpa_event_data event;
+
+	/* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
+	 * 2 byte ethertype */
+	if (len < 14) {
+		wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)",
+			   (unsigned long) len);
+		return;
+	}
+
+	hdr = (struct ieee8023_hdr *) buf;
+
+	switch (ntohs(hdr->ethertype)) {
+		case ETH_P_PAE:
+			wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
+			sa = hdr->src;
+			os_memset(&event, 0, sizeof(event));
+			event.new_sta.addr = sa;
+			wpa_supplicant_event(ctx, EVENT_NEW_STA, &event);
+
+			pos = (u8 *) (hdr + 1);
+			left = len - sizeof(*hdr);
+			drv_event_eapol_rx(ctx, sa, pos, left);
+		break;
+
+	default:
+		wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
+			   ntohs(hdr->ethertype));
+		break;
+	}
+#endif /* HOSTAPD */
+}
+
+
+static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	int len;
+	unsigned char buf[3000];
+
+	len = recv(sock, buf, sizeof(buf), 0);
+	if (len < 0) {
+		perror("recv");
+		return;
+	}
+
+	handle_data(eloop_ctx, buf, len);
+}
+
+
+static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	int len;
+	unsigned char buf[3000];
+	struct dhcp_message *msg;
+	u8 *mac_address;
+	union wpa_event_data event;
+
+	len = recv(sock, buf, sizeof(buf), 0);
+	if (len < 0) {
+		perror("recv");
+		return;
+	}
+
+	/* must contain at least dhcp_message->chaddr */
+	if (len < 44) {
+		wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len);
+		return;
+	}
+
+	msg = (struct dhcp_message *) buf;
+	mac_address = (u8 *) &(msg->chaddr);
+
+	wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR,
+		   MAC2STR(mac_address));
+
+	os_memset(&event, 0, sizeof(event));
+	event.new_sta.addr = mac_address;
+	wpa_supplicant_event(eloop_ctx, EVENT_NEW_STA, &event);
+}
+#endif /* __linux__ */
+
+
+static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
+{
+#ifdef __linux__
+	struct ifreq ifr;
+	struct sockaddr_ll addr;
+	struct sockaddr_in addr2;
+	int n = 1;
+
+	drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
+	if (drv->sock < 0) {
+		perror("socket[PF_PACKET,SOCK_RAW]");
+		return -1;
+	}
+
+	if (eloop_register_read_sock(drv->sock, handle_read, drv->ctx, NULL)) {
+		printf("Could not register read socket\n");
+		return -1;
+	}
+
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
+	if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
+		perror("ioctl(SIOCGIFINDEX)");
+		return -1;
+	}
+
+	os_memset(&addr, 0, sizeof(addr));
+	addr.sll_family = AF_PACKET;
+	addr.sll_ifindex = ifr.ifr_ifindex;
+	wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
+		   addr.sll_ifindex);
+
+	if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("bind");
+		return -1;
+	}
+
+	/* filter multicast address */
+	if (wired_multicast_membership(drv->sock, ifr.ifr_ifindex,
+				       pae_group_addr, 1) < 0) {
+		wpa_printf(MSG_ERROR, "wired: Failed to add multicast group "
+			   "membership");
+		return -1;
+	}
+
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
+	if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
+		perror("ioctl(SIOCGIFHWADDR)");
+		return -1;
+	}
+
+	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+		printf("Invalid HW-addr family 0x%04x\n",
+		       ifr.ifr_hwaddr.sa_family);
+		return -1;
+	}
+	os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+	/* setup dhcp listen socket for sta detection */
+	if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+		perror("socket call failed for dhcp");
+		return -1;
+	}
+
+	if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, drv->ctx,
+				     NULL)) {
+		printf("Could not register read socket\n");
+		return -1;
+	}
+
+	os_memset(&addr2, 0, sizeof(addr2));
+	addr2.sin_family = AF_INET;
+	addr2.sin_port = htons(67);
+	addr2.sin_addr.s_addr = INADDR_ANY;
+
+	if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n,
+		       sizeof(n)) == -1) {
+		perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]");
+		return -1;
+	}
+	if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n,
+		       sizeof(n)) == -1) {
+		perror("setsockopt[SOL_SOCKET,SO_BROADCAST]");
+		return -1;
+	}
+
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->ifname, IFNAMSIZ);
+	if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE,
+		       (char *) &ifr, sizeof(ifr)) < 0) {
+		perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]");
+		return -1;
+	}
+
+	if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2,
+		 sizeof(struct sockaddr)) == -1) {
+		perror("bind");
+		return -1;
+	}
+
+	return 0;
+#else /* __linux__ */
+	return -1;
+#endif /* __linux__ */
+}
+
+
+static int wired_send_eapol(void *priv, const u8 *addr,
+			    const u8 *data, size_t data_len, int encrypt,
+			    const u8 *own_addr)
+{
+	struct wpa_driver_wired_data *drv = priv;
+	struct ieee8023_hdr *hdr;
+	size_t len;
+	u8 *pos;
+	int res;
+
+	len = sizeof(*hdr) + data_len;
+	hdr = os_zalloc(len);
+	if (hdr == NULL) {
+		printf("malloc() failed for wired_send_eapol(len=%lu)\n",
+		       (unsigned long) len);
+		return -1;
+	}
+
+	os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
+		  ETH_ALEN);
+	os_memcpy(hdr->src, own_addr, ETH_ALEN);
+	hdr->ethertype = htons(ETH_P_PAE);
+
+	pos = (u8 *) (hdr + 1);
+	os_memcpy(pos, data, data_len);
+
+	res = send(drv->sock, (u8 *) hdr, len, 0);
+	os_free(hdr);
+
+	if (res < 0) {
+		perror("wired_send_eapol: send");
+		printf("wired_send_eapol - packet len: %lu - failed\n",
+		       (unsigned long) len);
+	}
+
+	return res;
+}
+
+
+static void * wired_driver_hapd_init(struct hostapd_data *hapd,
+				     struct wpa_init_params *params)
+{
+	struct wpa_driver_wired_data *drv;
+
+	drv = os_zalloc(sizeof(struct wpa_driver_wired_data));
+	if (drv == NULL) {
+		printf("Could not allocate memory for wired driver data\n");
+		return NULL;
+	}
+
+	drv->ctx = hapd;
+	os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname));
+	drv->use_pae_group_addr = params->use_pae_group_addr;
+
+	if (wired_init_sockets(drv, params->own_addr)) {
+		os_free(drv);
+		return NULL;
+	}
+
+	return drv;
+}
+
+
+static void wired_driver_hapd_deinit(void *priv)
+{
+	struct wpa_driver_wired_data *drv = priv;
+
+	if (drv->sock >= 0)
+		close(drv->sock);
+
+	if (drv->dhcp_sock >= 0)
+		close(drv->dhcp_sock);
+
+	os_free(drv);
+}
+
+
 static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid)
 {
 	ssid[0] = 0;
@@ -53,6 +401,14 @@ static int wpa_driver_wired_get_bssid(void *priv, u8 *bssid)
 }
 
 
+static int wpa_driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa)
+{
+	os_memset(capa, 0, sizeof(*capa));
+	capa->flags = WPA_DRIVER_FLAGS_WIRED;
+	return 0;
+}
+
+
 static int wpa_driver_wired_get_ifflags(const char *ifname, int *flags)
 {
 	struct ifreq ifr;
@@ -118,7 +474,7 @@ static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
 	ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
 	os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
 #endif /* __linux__ */
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
 	{
 		struct sockaddr_dl *dlp;
 		dlp = (struct sockaddr_dl *) &ifr.ifr_addr;
@@ -128,9 +484,9 @@ static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
 		dlp->sdl_nlen = 0;
 		dlp->sdl_alen = ETH_ALEN;
 		dlp->sdl_slen = 0;
-		os_memcpy(LLADDR(dlp), addr, ETH_ALEN); 
+		os_memcpy(LLADDR(dlp), addr, ETH_ALEN);
 	}
-#endif /* defined(__FreeBSD__) || defined(__DragonFly__) */
+#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
 	{
 		struct sockaddr *sap;
@@ -151,34 +507,6 @@ static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
 }
 
 
-static int wpa_driver_wired_membership(struct wpa_driver_wired_data *drv,
-				       const u8 *addr, int add)
-{
-#ifdef __linux__
-	struct packet_mreq mreq;
-
-	if (drv->pf_sock == -1)
-		return -1;
-
-	os_memset(&mreq, 0, sizeof(mreq));
-	mreq.mr_ifindex = if_nametoindex(drv->ifname);
-	mreq.mr_type = PACKET_MR_MULTICAST;
-	mreq.mr_alen = ETH_ALEN;
-	os_memcpy(mreq.mr_address, addr, ETH_ALEN);
-
-	if (setsockopt(drv->pf_sock, SOL_PACKET,
-		       add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
-		       &mreq, sizeof(mreq)) < 0) {
-		perror("setsockopt");
-		return -1;
-	}
-	return 0;
-#else /* __linux__ */
-	return -1;
-#endif /* __linux__ */
-}
-
-
 static void * wpa_driver_wired_init(void *ctx, const char *ifname)
 {
 	struct wpa_driver_wired_data *drv;
@@ -195,16 +523,18 @@ static void * wpa_driver_wired_init(void *ctx, const char *ifname)
 	if (drv->pf_sock < 0)
 		perror("socket(PF_PACKET)");
 #else /* __linux__ */
-	drv->pf_sock = -1;       
+	drv->pf_sock = -1;
 #endif /* __linux__ */
-	
+
 	if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 &&
 	    !(flags & IFF_UP) &&
 	    wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) {
 		drv->iff_up = 1;
 	}
 
-	if (wpa_driver_wired_membership(drv, pae_group_addr, 1) == 0) {
+	if (wired_multicast_membership(drv->pf_sock,
+				       if_nametoindex(drv->ifname),
+				       pae_group_addr, 1) == 0) {
 		wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
 			   "packet socket", __func__);
 		drv->membership = 1;
@@ -242,7 +572,9 @@ static void wpa_driver_wired_deinit(void *priv)
 	int flags;
 
 	if (drv->membership &&
-	    wpa_driver_wired_membership(drv, pae_group_addr, 0) < 0) {
+	    wired_multicast_membership(drv->pf_sock,
+				       if_nametoindex(drv->ifname),
+				       pae_group_addr, 0) < 0) {
 		wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
 			   "group (PACKET)", __func__);
 	}
@@ -271,16 +603,20 @@ static void wpa_driver_wired_deinit(void *priv)
 
 	if (drv->pf_sock != -1)
 		close(drv->pf_sock);
-	
+
 	os_free(drv);
 }
 
 
 const struct wpa_driver_ops wpa_driver_wired_ops = {
 	.name = "wired",
-	.desc = "wpa_supplicant wired Ethernet driver",
+	.desc = "Wired Ethernet driver",
+	.hapd_init = wired_driver_hapd_init,
+	.hapd_deinit = wired_driver_hapd_deinit,
+	.hapd_send_eapol = wired_send_eapol,
 	.get_ssid = wpa_driver_wired_get_ssid,
 	.get_bssid = wpa_driver_wired_get_bssid,
+	.get_capa = wpa_driver_wired_get_capa,
 	.init = wpa_driver_wired_init,
 	.deinit = wpa_driver_wired_deinit,
 };
diff --git a/contrib/wpa/src/drivers/drivers.c b/contrib/wpa/src/drivers/drivers.c
index d278797d7de2..bffbbde72b77 100644
--- a/contrib/wpa/src/drivers/drivers.c
+++ b/contrib/wpa/src/drivers/drivers.c
@@ -1,5 +1,5 @@
 /*
- * WPA Supplicant / driver interface list
+ * Driver interface list
  * Copyright (c) 2004-2005, Jouni Malinen 
  *
  * This program is free software; you can redistribute it and/or modify
@@ -24,9 +24,6 @@ extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */
 #ifdef CONFIG_DRIVER_HOSTAP
 extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
 #endif /* CONFIG_DRIVER_HOSTAP */
-#ifdef CONFIG_DRIVER_PRISM54
-extern struct wpa_driver_ops wpa_driver_prism54_ops; /* driver_prism54.c */
-#endif /* CONFIG_DRIVER_PRISM54 */
 #ifdef CONFIG_DRIVER_HERMES
 extern struct wpa_driver_ops wpa_driver_hermes_ops; /* driver_hermes.c */
 #endif /* CONFIG_DRIVER_HERMES */
@@ -64,9 +61,6 @@ extern struct wpa_driver_ops wpa_driver_ralink_ops; /* driver_ralink.c */
 #ifdef CONFIG_DRIVER_OSX
 extern struct wpa_driver_ops wpa_driver_osx_ops; /* driver_osx.m */
 #endif /* CONFIG_DRIVER_OSX */
-#ifdef CONFIG_DRIVER_PS3
-extern struct wpa_driver_ops wpa_driver_ps3_ops; /* driver_ps3.c */
-#endif /* CONFIG_DRIVER_PS3 */
 #ifdef CONFIG_DRIVER_IPHONE
 extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */
 #endif /* CONFIG_DRIVER_IPHONE */
@@ -74,9 +68,15 @@ extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */
 /* driver_roboswitch.c */
 extern struct wpa_driver_ops wpa_driver_roboswitch_ops;
 #endif /* CONFIG_DRIVER_ROBOSWITCH */
+#ifdef CONFIG_DRIVER_ATHEROS
+extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */
+#endif /* CONFIG_DRIVER_ATHEROS */
+#ifdef CONFIG_DRIVER_NONE
+extern struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */
+#endif /* CONFIG_DRIVER_NONE */
 
 
-struct wpa_driver_ops *wpa_supplicant_drivers[] =
+struct wpa_driver_ops *wpa_drivers[] =
 {
 #ifdef CONFIG_DRIVER_WEXT
 	&wpa_driver_wext_ops,
@@ -87,9 +87,6 @@ struct wpa_driver_ops *wpa_supplicant_drivers[] =
 #ifdef CONFIG_DRIVER_HOSTAP
 	&wpa_driver_hostap_ops,
 #endif /* CONFIG_DRIVER_HOSTAP */
-#ifdef CONFIG_DRIVER_PRISM54
-	&wpa_driver_prism54_ops,
-#endif /* CONFIG_DRIVER_PRISM54 */
 #ifdef CONFIG_DRIVER_HERMES
 	&wpa_driver_hermes_ops,
 #endif /* CONFIG_DRIVER_HERMES */
@@ -126,14 +123,17 @@ struct wpa_driver_ops *wpa_supplicant_drivers[] =
 #ifdef CONFIG_DRIVER_OSX
 	&wpa_driver_osx_ops,
 #endif /* CONFIG_DRIVER_OSX */
-#ifdef CONFIG_DRIVER_PS3
-	&wpa_driver_ps3_ops,
-#endif /* CONFIG_DRIVER_PS3 */
 #ifdef CONFIG_DRIVER_IPHONE
 	&wpa_driver_iphone_ops,
 #endif /* CONFIG_DRIVER_IPHONE */
 #ifdef CONFIG_DRIVER_ROBOSWITCH
 	&wpa_driver_roboswitch_ops,
 #endif /* CONFIG_DRIVER_ROBOSWITCH */
+#ifdef CONFIG_DRIVER_ATHEROS
+	&wpa_driver_atheros_ops,
+#endif /* CONFIG_DRIVER_ATHEROS */
+#ifdef CONFIG_DRIVER_NONE
+	&wpa_driver_none_ops,
+#endif /* CONFIG_DRIVER_NONE */
 	NULL
 };
diff --git a/contrib/wpa/src/drivers/drivers.mak b/contrib/wpa/src/drivers/drivers.mak
new file mode 100644
index 000000000000..b76b22953a38
--- /dev/null
+++ b/contrib/wpa/src/drivers/drivers.mak
@@ -0,0 +1,181 @@
+##### COMMON DRIVERS
+
+ifdef CONFIG_DRIVER_HOSTAP
+DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP
+DRV_OBJS += ../src/drivers/driver_hostap.o
+CONFIG_WIRELESS_EXTENSION=y
+NEED_AP_MLME=y
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+endif
+
+ifdef CONFIG_DRIVER_WIRED
+DRV_CFLAGS += -DCONFIG_DRIVER_WIRED
+DRV_OBJS += ../src/drivers/driver_wired.o
+endif
+
+ifdef CONFIG_DRIVER_MADWIFI
+DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI
+DRV_OBJS += ../src/drivers/driver_madwifi.o
+CONFIG_WIRELESS_EXTENSION=y
+CONFIG_L2_PACKET=linux
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+endif
+
+ifdef CONFIG_DRIVER_NL80211
+DRV_CFLAGS += -DCONFIG_DRIVER_NL80211
+DRV_OBJS += ../src/drivers/driver_nl80211.o
+DRV_OBJS += ../src/utils/radiotap.o
+NEED_SME=y
+NEED_AP_MLME=y
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+DRV_LIBS += -lnl
+
+ifdef CONFIG_LIBNL20
+DRV_LIBS += -lnl-genl
+DRV_CFLAGS += -DCONFIG_LIBNL20
+endif
+endif
+
+ifdef CONFIG_DRIVER_BSD
+ifndef CONFIG_L2_PACKET
+CONFIG_L2_PACKET=freebsd
+endif
+DRV_CFLAGS += -DCONFIG_DRIVER_BSD
+DRV_OBJS += ../src/drivers/driver_bsd.o
+CONFIG_L2_FREEBSD=y
+CONFIG_DNET_PCAP=y
+endif
+
+ifdef CONFIG_DRIVER_TEST
+DRV_CFLAGS += -DCONFIG_DRIVER_TEST
+DRV_OBJS += ../src/drivers/driver_test.o
+NEED_AP_MLME=y
+endif
+
+ifdef CONFIG_DRIVER_NONE
+DRV_CFLAGS += -DCONFIG_DRIVER_NONE
+DRV_OBJS += ../src/drivers/driver_none.o
+endif
+
+##### PURE AP DRIVERS
+
+ifdef CONFIG_DRIVER_ATHEROS
+DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS
+DRV_AP_OBJS += ../src/drivers/driver_atheros.o
+CONFIG_L2_PACKET=linux
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+endif
+
+##### PURE CLIENT DRIVERS
+
+ifdef CONFIG_DRIVER_WEXT
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT
+CONFIG_WIRELESS_EXTENSION=y
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+endif
+
+ifdef CONFIG_DRIVER_HERMES
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_HERMES
+DRV_WPA_OBJS += ../src/drivers/driver_hermes.o
+CONFIG_WIRELESS_EXTENSION=y
+endif
+
+ifdef CONFIG_DRIVER_ATMEL
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_ATMEL
+DRV_WPA_OBJS += ../src/drivers/driver_atmel.o
+CONFIG_WIRELESS_EXTENSION=y
+endif
+
+ifdef CONFIG_DRIVER_NDISWRAPPER
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDISWRAPPER
+DRV_WPA_OBJS += ../src/drivers/driver_ndiswrapper.o
+CONFIG_WIRELESS_EXTENSION=y
+endif
+
+ifdef CONFIG_DRIVER_RALINK
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_RALINK
+DRV_WPA_OBJS += ../src/drivers/driver_ralink.o
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+endif
+
+ifdef CONFIG_DRIVER_BROADCOM
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_BROADCOM
+DRV_WPA_OBJS += ../src/drivers/driver_broadcom.o
+endif
+
+ifdef CONFIG_DRIVER_IPW
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_IPW
+DRV_WPA_OBJS += ../src/drivers/driver_ipw.o
+CONFIG_WIRELESS_EXTENSION=y
+endif
+
+ifdef CONFIG_DRIVER_NDIS
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDIS
+DRV_WPA_OBJS += ../src/drivers/driver_ndis.o
+ifdef CONFIG_NDIS_EVENTS_INTEGRATED
+DRV_WPA_OBJS += ../src/drivers/driver_ndis_.o
+endif
+ifndef CONFIG_L2_PACKET
+CONFIG_L2_PACKET=pcap
+endif
+CONFIG_WINPCAP=y
+ifdef CONFIG_USE_NDISUIO
+DRV_WPA_CFLAGS += -DCONFIG_USE_NDISUIO
+endif
+endif
+
+ifdef CONFIG_DRIVER_OSX
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_OSX
+DRV_WPA_OBJS += ../src/drivers/driver_osx.o
+DRV_WPA_LDFLAGS += -framework CoreFoundation
+DRV_WPA_LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211
+endif
+
+ifdef CONFIG_DRIVER_IPHONE
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_IPHONE
+DRV_WPA_OBJS += ../src/drivers/driver_iphone.o
+DRV_WPA_OBJS += ../src/drivers/MobileApple80211.o
+DRV_WPA_LDFLAGS += -framework CoreFoundation
+endif
+
+ifdef CONFIG_DRIVER_ROBOSWITCH
+DRV_WPA_CFLAGS += -DCONFIG_DRIVER_ROBOSWITCH
+DRV_WPA_OBJS += ../src/drivers/driver_roboswitch.o
+endif
+
+ifdef CONFIG_WIRELESS_EXTENSION
+DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION
+DRV_WPA_OBJS += ../src/drivers/driver_wext.o
+endif
+
+ifdef NEED_NETLINK
+DRV_OBJS += ../src/drivers/netlink.o
+endif
+
+ifdef NEED_LINUX_IOCTL
+DRV_OBJS += ../src/drivers/linux_ioctl.o
+endif
+
+
+##### COMMON VARS
+DRV_BOTH_CFLAGS := $(DRV_CFLAGS) $(DRV_WPA_CFLAGS) $(DRV_AP_CFLAGS)
+DRV_WPA_CFLAGS += $(DRV_CFLAGS)
+DRV_AP_CFLAGS += $(DRV_CFLAGS)
+
+DRV_BOTH_LIBS := $(DRV_LIBS) $(DRV_WPA_LIBS) $(DRV_AP_LIBS)
+DRV_WPA_LIBS += $(DRV_LIBS)
+DRV_AP_LIBS += $(DRV_LIBS)
+
+DRV_BOTH_OBJS := $(DRV_OBJS) $(DRV_WPA_OBJS) $(DRV_AP_OBJS)
+DRV_WPA_OBJS += $(DRV_OBJS)
+DRV_AP_OBJS += $(DRV_OBJS)
+
+DRV_BOTH_LDFLAGS := $(DRV_LDFLAGS) $(DRV_WPA_LDFLAGS) $(DRV_AP_LDFLAGS)
+DRV_WPA_LDFLAGS += $(DRV_LDFLAGS)
+DRV_AP_LDFLAGS += $(DRV_LDFLAGS)
diff --git a/contrib/wpa/src/drivers/radiotap.c b/contrib/wpa/src/drivers/radiotap.c
deleted file mode 100644
index 804473fa4bfb..000000000000
--- a/contrib/wpa/src/drivers/radiotap.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Radiotap parser
- *
- * Copyright 2007		Andy Green 
- *
- * 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.
- *
- *
- * Modified for userspace by Johannes Berg 
- * I only modified some things on top to ease syncing should bugs be found.
- */
-
-#include "includes.h"
-
-#include "common.h"
-#include "radiotap_iter.h"
-
-#define le16_to_cpu		le_to_host16
-#define le32_to_cpu		le_to_host32
-#define __le32			uint32_t
-#define ulong			unsigned long
-#define unlikely(cond)		(cond)
-#define get_unaligned(p)					\
-({								\
-	struct packed_dummy_struct {				\
-		typeof(*(p)) __val;				\
-	} __attribute__((packed)) *__ptr = (void *) (p);	\
-								\
-	__ptr->__val;						\
-})
-
-/* function prototypes and related defs are in radiotap_iter.h */
-
-/**
- * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
- * @iterator: radiotap_iterator to initialize
- * @radiotap_header: radiotap header to parse
- * @max_length: total length we can parse into (eg, whole packet length)
- *
- * Returns: 0 or a negative error code if there is a problem.
- *
- * This function initializes an opaque iterator struct which can then
- * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
- * argument which is present in the header.  It knows about extended
- * present headers and handles them.
- *
- * How to use:
- * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
- * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
- * checking for a good 0 return code.  Then loop calling
- * __ieee80211_radiotap_iterator_next()... it returns either 0,
- * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
- * The iterator's @this_arg member points to the start of the argument
- * associated with the current argument index that is present, which can be
- * found in the iterator's @this_arg_index member.  This arg index corresponds
- * to the IEEE80211_RADIOTAP_... defines.
- *
- * Radiotap header length:
- * You can find the CPU-endian total radiotap header length in
- * iterator->max_length after executing ieee80211_radiotap_iterator_init()
- * successfully.
- *
- * Alignment Gotcha:
- * You must take care when dereferencing iterator.this_arg
- * for multibyte types... the pointer is not aligned.  Use
- * get_unaligned((type *)iterator.this_arg) to dereference
- * iterator.this_arg for type "type" safely on all arches.
- *
- * Example code:
- * See Documentation/networking/radiotap-headers.txt
- */
-
-int ieee80211_radiotap_iterator_init(
-    struct ieee80211_radiotap_iterator *iterator,
-    struct ieee80211_radiotap_header *radiotap_header,
-    int max_length)
-{
-	/* Linux only supports version 0 radiotap format */
-	if (radiotap_header->it_version)
-		return -EINVAL;
-
-	/* sanity check for allowed length and radiotap length field */
-	if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len)))
-		return -EINVAL;
-
-	iterator->rtheader = radiotap_header;
-	iterator->max_length = le16_to_cpu(get_unaligned(
-						&radiotap_header->it_len));
-	iterator->arg_index = 0;
-	iterator->bitmap_shifter = le32_to_cpu(get_unaligned(
-						&radiotap_header->it_present));
-	iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
-	iterator->this_arg = NULL;
-
-	/* find payload start allowing for extended bitmap(s) */
-
-	if (unlikely(iterator->bitmap_shifter & (1<arg)) &
-				   (1<arg += sizeof(u32);
-
-			/*
-			 * check for insanity where the present bitmaps
-			 * keep claiming to extend up to or even beyond the
-			 * stated radiotap header length
-			 */
-
-			if (((ulong)iterator->arg - (ulong)iterator->rtheader)
-			    > (ulong)iterator->max_length)
-				return -EINVAL;
-		}
-
-		iterator->arg += sizeof(u32);
-
-		/*
-		 * no need to check again for blowing past stated radiotap
-		 * header length, because ieee80211_radiotap_iterator_next
-		 * checks it before it is dereferenced
-		 */
-	}
-
-	/* we are all initialized happily */
-
-	return 0;
-}
-
-
-/**
- * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
- * @iterator: radiotap_iterator to move to next arg (if any)
- *
- * Returns: 0 if there is an argument to handle,
- * -ENOENT if there are no more args or -EINVAL
- * if there is something else wrong.
- *
- * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
- * in @this_arg_index and sets @this_arg to point to the
- * payload for the field.  It takes care of alignment handling and extended
- * present fields.  @this_arg can be changed by the caller (eg,
- * incremented to move inside a compound argument like
- * IEEE80211_RADIOTAP_CHANNEL).  The args pointed to are in
- * little-endian format whatever the endianess of your CPU.
- *
- * Alignment Gotcha:
- * You must take care when dereferencing iterator.this_arg
- * for multibyte types... the pointer is not aligned.  Use
- * get_unaligned((type *)iterator.this_arg) to dereference
- * iterator.this_arg for type "type" safely on all arches.
- */
-
-int ieee80211_radiotap_iterator_next(
-    struct ieee80211_radiotap_iterator *iterator)
-{
-
-	/*
-	 * small length lookup table for all radiotap types we heard of
-	 * starting from b0 in the bitmap, so we can walk the payload
-	 * area of the radiotap header
-	 *
-	 * There is a requirement to pad args, so that args
-	 * of a given length must begin at a boundary of that length
-	 * -- but note that compound args are allowed (eg, 2 x u16
-	 * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
-	 * a reliable indicator of alignment requirement.
-	 *
-	 * upper nybble: content alignment for arg
-	 * lower nybble: content length for arg
-	 */
-
-	static const u8 rt_sizes[] = {
-		[IEEE80211_RADIOTAP_TSFT] = 0x88,
-		[IEEE80211_RADIOTAP_FLAGS] = 0x11,
-		[IEEE80211_RADIOTAP_RATE] = 0x11,
-		[IEEE80211_RADIOTAP_CHANNEL] = 0x24,
-		[IEEE80211_RADIOTAP_FHSS] = 0x22,
-		[IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
-		[IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
-		[IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
-		[IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
-		[IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
-		[IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
-		[IEEE80211_RADIOTAP_ANTENNA] = 0x11,
-		[IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
-		[IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11,
-		[IEEE80211_RADIOTAP_RX_FLAGS] = 0x22,
-		[IEEE80211_RADIOTAP_TX_FLAGS] = 0x22,
-		[IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11,
-		[IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11,
-		/*
-		 * add more here as they are defined in
-		 * include/net/ieee80211_radiotap.h
-		 */
-	};
-
-	/*
-	 * for every radiotap entry we can at
-	 * least skip (by knowing the length)...
-	 */
-
-	while (iterator->arg_index < (int) sizeof(rt_sizes)) {
-		int hit = 0;
-		int pad;
-
-		if (!(iterator->bitmap_shifter & 1))
-			goto next_entry; /* arg not present */
-
-		/*
-		 * arg is present, account for alignment padding
-		 *  8-bit args can be at any alignment
-		 * 16-bit args must start on 16-bit boundary
-		 * 32-bit args must start on 32-bit boundary
-		 * 64-bit args must start on 64-bit boundary
-		 *
-		 * note that total arg size can differ from alignment of
-		 * elements inside arg, so we use upper nybble of length
-		 * table to base alignment on
-		 *
-		 * also note: these alignments are ** relative to the
-		 * start of the radiotap header **.  There is no guarantee
-		 * that the radiotap header itself is aligned on any
-		 * kind of boundary.
-		 *
-		 * the above is why get_unaligned() is used to dereference
-		 * multibyte elements from the radiotap area
-		 */
-
-		pad = (((ulong)iterator->arg) -
-			((ulong)iterator->rtheader)) &
-			((rt_sizes[iterator->arg_index] >> 4) - 1);
-
-		if (pad)
-			iterator->arg +=
-				(rt_sizes[iterator->arg_index] >> 4) - pad;
-
-		/*
-		 * this is what we will return to user, but we need to
-		 * move on first so next call has something fresh to test
-		 */
-		iterator->this_arg_index = iterator->arg_index;
-		iterator->this_arg = iterator->arg;
-		hit = 1;
-
-		/* internally move on the size of this arg */
-		iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
-
-		/*
-		 * check for insanity where we are given a bitmap that
-		 * claims to have more arg content than the length of the
-		 * radiotap section.  We will normally end up equalling this
-		 * max_length on the last arg, never exceeding it.
-		 */
-
-		if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
-		    (ulong) iterator->max_length)
-			return -EINVAL;
-
-	next_entry:
-		iterator->arg_index++;
-		if (unlikely((iterator->arg_index & 31) == 0)) {
-			/* completed current u32 bitmap */
-			if (iterator->bitmap_shifter & 1) {
-				/* b31 was set, there is more */
-				/* move to next u32 bitmap */
-				iterator->bitmap_shifter = le32_to_cpu(
-					get_unaligned(iterator->next_bitmap));
-				iterator->next_bitmap++;
-			} else
-				/* no more bitmaps: end */
-				iterator->arg_index = sizeof(rt_sizes);
-		} else /* just try the next bit */
-			iterator->bitmap_shifter >>= 1;
-
-		/* if we found a valid arg earlier, return it now */
-		if (hit)
-			return 0;
-	}
-
-	/* we don't know how to handle any more args, we're done */
-	return -ENOENT;
-}
diff --git a/contrib/wpa/src/drivers/radiotap_iter.h b/contrib/wpa/src/drivers/radiotap_iter.h
deleted file mode 100644
index 92a798a67023..000000000000
--- a/contrib/wpa/src/drivers/radiotap_iter.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef __RADIOTAP_ITER_H
-#define __RADIOTAP_ITER_H
-
-#include "radiotap.h"
-
-/* Radiotap header iteration
- *   implemented in radiotap.c
- */
-/**
- * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
- * @rtheader: pointer to the radiotap header we are walking through
- * @max_length: length of radiotap header in cpu byte ordering
- * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg
- * @this_arg: pointer to current radiotap arg
- * @arg_index: internal next argument index
- * @arg: internal next argument pointer
- * @next_bitmap: internal pointer to next present u32
- * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
- */
-
-struct ieee80211_radiotap_iterator {
-	struct ieee80211_radiotap_header *rtheader;
-	int max_length;
-	int this_arg_index;
-	unsigned char *this_arg;
-
-	int arg_index;
-	unsigned char *arg;
-	uint32_t *next_bitmap;
-	uint32_t bitmap_shifter;
-};
-
-extern int ieee80211_radiotap_iterator_init(
-   struct ieee80211_radiotap_iterator *iterator,
-   struct ieee80211_radiotap_header *radiotap_header,
-   int max_length);
-
-extern int ieee80211_radiotap_iterator_next(
-   struct ieee80211_radiotap_iterator *iterator);
-
-#endif /* __RADIOTAP_ITER_H */
diff --git a/contrib/wpa/src/drivers/scan_helpers.c b/contrib/wpa/src/drivers/scan_helpers.c
deleted file mode 100644
index 63387701ea9a..000000000000
--- a/contrib/wpa/src/drivers/scan_helpers.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * WPA Supplicant - Helper functions for scan result processing
- * Copyright (c) 2007-2008, Jouni Malinen 
- *
- * 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 "drivers/driver.h"
-#include "ieee802_11_defs.h"
-
-
-const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
-{
-	const u8 *end, *pos;
-
-	pos = (const u8 *) (res + 1);
-	end = pos + res->ie_len;
-
-	while (pos + 1 < end) {
-		if (pos + 2 + pos[1] > end)
-			break;
-		if (pos[0] == ie)
-			return pos;
-		pos += 2 + pos[1];
-	}
-
-	return NULL;
-}
-
-
-const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
-				  u32 vendor_type)
-{
-	const u8 *end, *pos;
-
-	pos = (const u8 *) (res + 1);
-	end = pos + res->ie_len;
-
-	while (pos + 1 < end) {
-		if (pos + 2 + pos[1] > end)
-			break;
-		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
-		    vendor_type == WPA_GET_BE32(&pos[2]))
-			return pos;
-		pos += 2 + pos[1];
-	}
-
-	return NULL;
-}
-
-
-struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
-					     u32 vendor_type)
-{
-	struct wpabuf *buf;
-	const u8 *end, *pos;
-
-	buf = wpabuf_alloc(res->ie_len);
-	if (buf == NULL)
-		return NULL;
-
-	pos = (const u8 *) (res + 1);
-	end = pos + res->ie_len;
-
-	while (pos + 1 < end) {
-		if (pos + 2 + pos[1] > end)
-			break;
-		if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
-		    vendor_type == WPA_GET_BE32(&pos[2]))
-			wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
-		pos += 2 + pos[1];
-	}
-
-	if (wpabuf_len(buf) == 0) {
-		wpabuf_free(buf);
-		buf = NULL;
-	}
-
-	return buf;
-}
-
-
-int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
-{
-	int rate = 0;
-	const u8 *ie;
-	int i;
-
-	ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES);
-	for (i = 0; ie && i < ie[1]; i++) {
-		if ((ie[i + 2] & 0x7f) > rate)
-			rate = ie[i + 2] & 0x7f;
-	}
-
-	ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES);
-	for (i = 0; ie && i < ie[1]; i++) {
-		if ((ie[i + 2] & 0x7f) > rate)
-			rate = ie[i + 2] & 0x7f;
-	}
-
-	return rate;
-}
-
-
-void wpa_scan_results_free(struct wpa_scan_results *res)
-{
-	size_t i;
-
-	if (res == NULL)
-		return;
-
-	for (i = 0; i < res->num; i++)
-		os_free(res->res[i]);
-	os_free(res->res);
-	os_free(res);
-}
-
-
-/* Compare function for sorting scan results. Return >0 if @b is considered
- * better. */
-static int wpa_scan_result_compar(const void *a, const void *b)
-{
-	struct wpa_scan_res **_wa = (void *) a;
-	struct wpa_scan_res **_wb = (void *) b;
-	struct wpa_scan_res *wa = *_wa;
-	struct wpa_scan_res *wb = *_wb;
-	int wpa_a, wpa_b, maxrate_a, maxrate_b;
-
-	/* WPA/WPA2 support preferred */
-	wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
-		wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
-	wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
-		wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
-
-	if (wpa_b && !wpa_a)
-		return 1;
-	if (!wpa_b && wpa_a)
-		return -1;
-
-	/* privacy support preferred */
-	if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
-	    (wb->caps & IEEE80211_CAP_PRIVACY))
-		return 1;
-	if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
-	    (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
-		return -1;
-
-	/* best/max rate preferred if signal level close enough XXX */
-	if ((wa->level && wb->level && abs(wb->level - wa->level) < 5) ||
-	    (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
-		maxrate_a = wpa_scan_get_max_rate(wa);
-		maxrate_b = wpa_scan_get_max_rate(wb);
-		if (maxrate_a != maxrate_b)
-			return maxrate_b - maxrate_a;
-	}
-
-	/* use freq for channel preference */
-
-	/* all things being equal, use signal level; if signal levels are
-	 * identical, use quality values since some drivers may only report
-	 * that value and leave the signal level zero */
-	if (wb->level == wa->level)
-		return wb->qual - wa->qual;
-	return wb->level - wa->level;
-}
-
-
-void wpa_scan_sort_results(struct wpa_scan_results *res)
-{
-	qsort(res->res, res->num, sizeof(struct wpa_scan_res *),
-	      wpa_scan_result_compar);
-}
diff --git a/contrib/wpa/src/eap_common/Makefile b/contrib/wpa/src/eap_common/Makefile
index cffba620da04..9c41962fd7e1 100644
--- a/contrib/wpa/src/eap_common/Makefile
+++ b/contrib/wpa/src/eap_common/Makefile
@@ -2,7 +2,6 @@ all:
 	@echo Nothing to be made.
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
 	rm -f *~ *.o *.d
 
 install:
diff --git a/contrib/wpa/src/eap_common/chap.c b/contrib/wpa/src/eap_common/chap.c
index a088aff64e2d..60bfc1c8168f 100644
--- a/contrib/wpa/src/eap_common/chap.c
+++ b/contrib/wpa/src/eap_common/chap.c
@@ -1,6 +1,6 @@
 /*
  * CHAP-MD5 (RFC 1994)
- * Copyright (c) 2007, Jouni Malinen 
+ * Copyright (c) 2007-2009, Jouni Malinen 
  *
  * 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
@@ -15,11 +15,10 @@
 #include "includes.h"
 
 #include "common.h"
-#include "md5.h"
-#include "crypto.h"
+#include "crypto/crypto.h"
 #include "chap.h"
 
-void chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge,
+int chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge,
 	      size_t challenge_len, u8 *response)
 {
 	const u8 *addr[3];
@@ -31,5 +30,5 @@ void chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge,
 	len[1] = secret_len;
 	addr[2] = challenge;
 	len[2] = challenge_len;
-	md5_vector(3, addr, len, response);
+	return md5_vector(3, addr, len, response);
 }
diff --git a/contrib/wpa/src/eap_common/chap.h b/contrib/wpa/src/eap_common/chap.h
index 209dc8a48f0f..b9c400c7c7f4 100644
--- a/contrib/wpa/src/eap_common/chap.h
+++ b/contrib/wpa/src/eap_common/chap.h
@@ -1,6 +1,6 @@
 /*
  * CHAP-MD5 (RFC 1994)
- * Copyright (c) 2007, Jouni Malinen 
+ * Copyright (c) 2007-2009, Jouni Malinen 
  *
  * 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
@@ -17,7 +17,7 @@
 
 #define CHAP_MD5_LEN 16
 
-void chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge,
-	      size_t challenge_len, u8 *response);
+int chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge,
+	     size_t challenge_len, u8 *response);
 
 #endif /* CHAP_H */
diff --git a/contrib/wpa/src/eap_common/eap_fast_common.c b/contrib/wpa/src/eap_common/eap_fast_common.c
index 4d3deafa0cec..4de34a87b611 100644
--- a/contrib/wpa/src/eap_common/eap_fast_common.c
+++ b/contrib/wpa/src/eap_common/eap_fast_common.c
@@ -15,8 +15,8 @@
 #include "includes.h"
 
 #include "common.h"
-#include "sha1.h"
-#include "tls.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "eap_defs.h"
 #include "eap_tlv_common.h"
 #include "eap_fast_common.h"
diff --git a/contrib/wpa/src/eap_common/eap_gpsk_common.c b/contrib/wpa/src/eap_common/eap_gpsk_common.c
index 414610cf5a4e..407626288061 100644
--- a/contrib/wpa/src/eap_common/eap_gpsk_common.c
+++ b/contrib/wpa/src/eap_common/eap_gpsk_common.c
@@ -15,12 +15,9 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/sha256.h"
 #include "eap_defs.h"
-#include "aes_wrap.h"
-#include "crypto.h"
-#ifdef EAP_GPSK_SHA256
-#include "sha256.h"
-#endif /* EAP_GPSK_SHA256 */
 #include "eap_gpsk_common.h"
 
 
diff --git a/contrib/wpa/src/eap_common/eap_pax_common.c b/contrib/wpa/src/eap_common/eap_pax_common.c
index 80110469dcc3..32dc80c74dc5 100644
--- a/contrib/wpa/src/eap_common/eap_pax_common.c
+++ b/contrib/wpa/src/eap_common/eap_pax_common.c
@@ -15,7 +15,7 @@
 #include "includes.h"
 
 #include "common.h"
-#include "sha1.h"
+#include "crypto/sha1.h"
 #include "eap_pax_common.h"
 
 
diff --git a/contrib/wpa/src/eap_common/eap_peap_common.c b/contrib/wpa/src/eap_common/eap_peap_common.c
index 14625f963921..3a64b8ecc44c 100644
--- a/contrib/wpa/src/eap_common/eap_peap_common.c
+++ b/contrib/wpa/src/eap_common/eap_peap_common.c
@@ -15,7 +15,7 @@
 #include "includes.h"
 
 #include "common.h"
-#include "sha1.h"
+#include "crypto/sha1.h"
 #include "eap_peap_common.h"
 
 void peap_prfplus(int version, const u8 *key, size_t key_len,
diff --git a/contrib/wpa/src/eap_common/eap_psk_common.c b/contrib/wpa/src/eap_common/eap_psk_common.c
index 0def3e885371..7417d5c73df5 100644
--- a/contrib/wpa/src/eap_common/eap_psk_common.c
+++ b/contrib/wpa/src/eap_common/eap_psk_common.c
@@ -15,7 +15,7 @@
 #include "includes.h"
 
 #include "common.h"
-#include "aes_wrap.h"
+#include "crypto/aes_wrap.h"
 #include "eap_defs.h"
 #include "eap_psk_common.h"
 
diff --git a/contrib/wpa/src/eap_common/eap_sake_common.c b/contrib/wpa/src/eap_common/eap_sake_common.c
index eafad1d11723..9002b0ca328a 100644
--- a/contrib/wpa/src/eap_common/eap_sake_common.c
+++ b/contrib/wpa/src/eap_common/eap_sake_common.c
@@ -15,8 +15,8 @@
 #include "includes.h"
 
 #include "common.h"
-#include "sha1.h"
 #include "wpabuf.h"
+#include "crypto/sha1.h"
 #include "eap_defs.h"
 #include "eap_sake_common.h"
 
diff --git a/contrib/wpa/src/eap_common/eap_sim_common.c b/contrib/wpa/src/eap_common/eap_sim_common.c
index fccda02417aa..56b4ded45963 100644
--- a/contrib/wpa/src/eap_common/eap_sim_common.c
+++ b/contrib/wpa/src/eap_common/eap_sim_common.c
@@ -15,12 +15,12 @@
 #include "includes.h"
 
 #include "common.h"
-#include "eap_common/eap_defs.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "crypto.h"
-#include "aes_wrap.h"
 #include "wpabuf.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/crypto.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "eap_common/eap_defs.h"
 #include "eap_common/eap_sim_common.h"
 
 
@@ -233,7 +233,7 @@ void eap_sim_add_mac(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac,
 }
 
 
-#ifdef EAP_AKA_PRIME
+#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
 static void prf_prime(const u8 *k, const char *seed1,
 		      const u8 *seed2, size_t seed2_len,
 		      const u8 *seed3, size_t seed3_len,
@@ -496,7 +496,7 @@ void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak,
 	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK'", ck, EAP_AKA_CK_LEN);
 	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK'", ik, EAP_AKA_IK_LEN);
 }
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
 
 
 int eap_sim_parse_attr(const u8 *start, const u8 *end,
@@ -858,7 +858,7 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
 			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RESULT_IND");
 			attr->result_ind = 1;
 			break;
-#ifdef EAP_AKA_PRIME
+#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
 		case EAP_SIM_AT_KDF_INPUT:
 			if (aka != 2) {
 				wpa_printf(MSG_INFO, "EAP-AKA: Unexpected "
@@ -913,7 +913,7 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
 			}
 			attr->bidding = apos;
 			break;
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
 		default:
 			if (pos[0] < 128) {
 				wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized "
@@ -1023,14 +1023,14 @@ struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut,
 	eap = wpabuf_mhead(msg->buf);
 	eap->length = host_to_be16(wpabuf_len(msg->buf));
 
-#ifdef EAP_AKA_PRIME
+#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
 	if (k_aut && msg->mac && msg->type == EAP_TYPE_AKA_PRIME) {
 		eap_sim_add_mac_sha256(k_aut, (u8 *) wpabuf_head(msg->buf),
 				       wpabuf_len(msg->buf),
 				       (u8 *) wpabuf_mhead(msg->buf) +
 				       msg->mac, extra, extra_len);
 	} else
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
 	if (k_aut && msg->mac) {
 		eap_sim_add_mac(k_aut, (u8 *) wpabuf_head(msg->buf),
 				wpabuf_len(msg->buf),
diff --git a/contrib/wpa/src/eap_common/eap_sim_common.h b/contrib/wpa/src/eap_common/eap_sim_common.h
index a8080e27a7b3..48c8eaac0a09 100644
--- a/contrib/wpa/src/eap_common/eap_sim_common.h
+++ b/contrib/wpa/src/eap_common/eap_sim_common.h
@@ -94,7 +94,7 @@ int eap_sim_verify_mac(const u8 *k_aut, const struct wpabuf *req,
 void eap_sim_add_mac(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac,
 		     const u8 *extra, size_t extra_len);
 
-#ifdef EAP_AKA_PRIME
+#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
 void eap_aka_prime_derive_keys(const u8 *identity, size_t identity_len,
 			       const u8 *ik, const u8 *ck, u8 *k_encr,
 			       u8 *k_aut, u8 *k_re, u8 *msk, u8 *emsk);
@@ -110,7 +110,7 @@ void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len,
 void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak,
 				      const u8 *network_name,
 				      size_t network_name_len);
-#else /* EAP_AKA_PRIME */
+#else /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
 static inline void eap_aka_prime_derive_keys(const u8 *identity,
 					     size_t identity_len,
 					     const u8 *ik, const u8 *ck,
@@ -135,7 +135,7 @@ static inline int eap_sim_verify_mac_sha256(const u8 *k_aut,
 {
 	return -1;
 }
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
 
 
 /* EAP-SIM/AKA Attributes (0..127 non-skippable) */
diff --git a/contrib/wpa/src/eap_common/ikev2_common.c b/contrib/wpa/src/eap_common/ikev2_common.c
index 818b5bdbaad8..67754d8159d0 100644
--- a/contrib/wpa/src/eap_common/ikev2_common.c
+++ b/contrib/wpa/src/eap_common/ikev2_common.c
@@ -15,9 +15,9 @@
 #include "includes.h"
 
 #include "common.h"
-#include "sha1.h"
-#include "md5.h"
-#include "crypto.h"
+#include "crypto/crypto.h"
+#include "crypto/md5.h"
+#include "crypto/sha1.h"
 #include "ikev2_common.h"
 
 
diff --git a/contrib/wpa/src/eap_peer/Makefile b/contrib/wpa/src/eap_peer/Makefile
index d9449a28da42..365105611049 100644
--- a/contrib/wpa/src/eap_peer/Makefile
+++ b/contrib/wpa/src/eap_peer/Makefile
@@ -2,7 +2,6 @@ all:
 	@echo Nothing to be made.
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
 	rm -f *~ *.o *.so *.d
 
 install:
diff --git a/contrib/wpa/src/eap_peer/eap.c b/contrib/wpa/src/eap_peer/eap.c
index e8e504af5495..b9f186bf17d0 100644
--- a/contrib/wpa/src/eap_peer/eap.c
+++ b/contrib/wpa/src/eap_peer/eap.c
@@ -1,6 +1,6 @@
 /*
  * EAP peer state machines (RFC 4137)
- * Copyright (c) 2004-2008, Jouni Malinen 
+ * Copyright (c) 2004-2010, Jouni Malinen 
  *
  * 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
@@ -24,14 +24,14 @@
 #include "includes.h"
 
 #include "common.h"
+#include "pcsc_funcs.h"
+#include "state_machine.h"
+#include "crypto/crypto.h"
+#include "crypto/tls.h"
+#include "common/wpa_ctrl.h"
+#include "eap_common/eap_wsc_common.h"
 #include "eap_i.h"
 #include "eap_config.h"
-#include "tls.h"
-#include "crypto.h"
-#include "pcsc_funcs.h"
-#include "wpa_ctrl.h"
-#include "state_machine.h"
-#include "eap_common/eap_wsc_common.h"
 
 #define STATE_MACHINE_DATA struct eap_sm
 #define STATE_MACHINE_DEBUG_PREFIX "EAP"
@@ -228,9 +228,15 @@ SM_STATE(EAP, GET_METHOD)
 	if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) {
 		wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed",
 			   sm->reqVendor, method);
+		wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
+			"vendor=%u method=%u -> NAK",
+			sm->reqVendor, method);
 		goto nak;
 	}
 
+	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
+		"vendor=%u method=%u", sm->reqVendor, method);
+
 	/*
 	 * RFC 4137 does not define specific operation for fast
 	 * re-authentication (session resumption). The design here is to allow
@@ -1154,6 +1160,60 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req)
 }
 
 
+static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
+				  union tls_event_data *data)
+{
+	struct eap_sm *sm = ctx;
+	char *hash_hex = NULL;
+	char *cert_hex = NULL;
+
+	switch (ev) {
+	case TLS_CERT_CHAIN_FAILURE:
+		wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
+			"reason=%d depth=%d subject='%s' err='%s'",
+			data->cert_fail.reason,
+			data->cert_fail.depth,
+			data->cert_fail.subject,
+			data->cert_fail.reason_txt);
+		break;
+	case TLS_PEER_CERTIFICATE:
+		if (data->peer_cert.hash) {
+			size_t len = data->peer_cert.hash_len * 2 + 1;
+			hash_hex = os_malloc(len);
+			if (hash_hex) {
+				wpa_snprintf_hex(hash_hex, len,
+						 data->peer_cert.hash,
+						 data->peer_cert.hash_len);
+			}
+		}
+		wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PEER_CERT
+			"depth=%d subject='%s'%s%s",
+			data->peer_cert.depth, data->peer_cert.subject,
+			hash_hex ? " hash=" : "", hash_hex ? hash_hex : "");
+
+		if (data->peer_cert.cert) {
+			size_t len = wpabuf_len(data->peer_cert.cert) * 2 + 1;
+			cert_hex = os_malloc(len);
+			if (cert_hex == NULL)
+				break;
+			wpa_snprintf_hex(cert_hex, len,
+					 wpabuf_head(data->peer_cert.cert),
+					 wpabuf_len(data->peer_cert.cert));
+			wpa_msg_ctrl(sm->msg_ctx, MSG_INFO,
+				     WPA_EVENT_EAP_PEER_CERT
+				     "depth=%d subject='%s' cert=%s",
+				     data->peer_cert.depth,
+				     data->peer_cert.subject,
+				     cert_hex);
+		}
+		break;
+	}
+
+	os_free(hash_hex);
+	os_free(cert_hex);
+}
+
+
 /**
  * eap_peer_sm_init - Allocate and initialize EAP peer state machine
  * @eapol_ctx: Context data to be used with eapol_cb calls
@@ -1188,6 +1248,11 @@ struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
 	tlsconf.opensc_engine_path = conf->opensc_engine_path;
 	tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
 	tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
+#ifdef CONFIG_FIPS
+	tlsconf.fips_mode = 1;
+#endif /* CONFIG_FIPS */
+	tlsconf.event_cb = eap_peer_sm_tls_event;
+	tlsconf.cb_ctx = sm;
 	sm->ssl_ctx = tls_init(&tlsconf);
 	if (sm->ssl_ctx == NULL) {
 		wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
diff --git a/contrib/wpa/src/eap_peer/eap.h b/contrib/wpa/src/eap_peer/eap.h
index d7a562812bb3..40d0b6929ce9 100644
--- a/contrib/wpa/src/eap_peer/eap.h
+++ b/contrib/wpa/src/eap_peer/eap.h
@@ -15,7 +15,7 @@
 #ifndef EAP_H
 #define EAP_H
 
-#include "defs.h"
+#include "common/defs.h"
 #include "eap_common/eap_defs.h"
 #include "eap_peer/eap_methods.h"
 
diff --git a/contrib/wpa/src/eap_peer/eap_aka.c b/contrib/wpa/src/eap_peer/eap_aka.c
index f23714142586..182f01a5e60a 100644
--- a/contrib/wpa/src/eap_peer/eap_aka.c
+++ b/contrib/wpa/src/eap_peer/eap_aka.c
@@ -15,16 +15,14 @@
 #include "includes.h"
 
 #include "common.h"
-#include "eap_peer/eap_i.h"
 #include "pcsc_funcs.h"
+#include "crypto/crypto.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "crypto/milenage.h"
 #include "eap_common/eap_sim_common.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "crypto.h"
-#include "eap_peer/eap_config.h"
-#ifdef CONFIG_USIM_SIMULATOR
-#include "hlr_auc_gw/milenage.h"
-#endif /* CONFIG_USIM_SIMULATOR */
+#include "eap_config.h"
+#include "eap_i.h"
 
 
 struct eap_aka_data {
diff --git a/contrib/wpa/src/eap_peer/eap_config.h b/contrib/wpa/src/eap_peer/eap_config.h
index 94245c3d03dd..b64b68f4b76c 100644
--- a/contrib/wpa/src/eap_peer/eap_config.h
+++ b/contrib/wpa/src/eap_peer/eap_config.h
@@ -85,6 +85,15 @@ struct eap_peer_config {
 	 * Alternatively, a named configuration blob can be used by setting
 	 * this to blob://blob_name.
 	 *
+	 * Alternatively, this can be used to only perform matching of the
+	 * server certificate (SHA-256 hash of the DER encoded X.509
+	 * certificate). In this case, the possible CA certificates in the
+	 * server certificate chain are ignored and only the server certificate
+	 * is verified. This is configured with the following format:
+	 * hash:://server/sha256/cert_hash_in_hex
+	 * For example: "hash://server/sha256/
+	 * 5a1bc1296205e6fdbe3979728efe3920798885c1c4590b5f90f43222d239ca6a"
+	 *
 	 * On Windows, trusted CA certificates can be loaded from the system
 	 * certificate store by setting this to cert_store://name, e.g.,
 	 * ca_cert="cert_store://CA" or ca_cert="cert_store://ROOT".
diff --git a/contrib/wpa/src/eap_peer/eap_fast.c b/contrib/wpa/src/eap_peer/eap_fast.c
index d00867099aa3..5d3e69d3cdfe 100644
--- a/contrib/wpa/src/eap_peer/eap_fast.c
+++ b/contrib/wpa/src/eap_peer/eap_fast.c
@@ -15,12 +15,12 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/tls.h"
+#include "crypto/sha1.h"
+#include "eap_common/eap_tlv_common.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
 #include "eap_config.h"
-#include "tls.h"
-#include "eap_common/eap_tlv_common.h"
-#include "sha1.h"
 #include "eap_fast_pac.h"
 
 #ifdef EAP_FAST_DYNAMIC
@@ -1445,9 +1445,9 @@ static int eap_fast_process_start(struct eap_sm *sm,
 
 	/* EAP-FAST Version negotiation (section 3.1) */
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Start (server ver=%d, own ver=%d)",
-		   flags & EAP_PEAP_VERSION_MASK, data->fast_version);
-	if ((flags & EAP_PEAP_VERSION_MASK) < data->fast_version)
-		data->fast_version = flags & EAP_PEAP_VERSION_MASK;
+		   flags & EAP_TLS_VERSION_MASK, data->fast_version);
+	if ((flags & EAP_TLS_VERSION_MASK) < data->fast_version)
+		data->fast_version = flags & EAP_TLS_VERSION_MASK;
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Using FAST version %d",
 		   data->fast_version);
 
diff --git a/contrib/wpa/src/eap_peer/eap_fast_pac.c b/contrib/wpa/src/eap_peer/eap_fast_pac.c
index 77893d619597..541cce50dc01 100644
--- a/contrib/wpa/src/eap_peer/eap_fast_pac.c
+++ b/contrib/wpa/src/eap_peer/eap_fast_pac.c
@@ -480,8 +480,10 @@ static void eap_fast_write(char **buf, char **pos, size_t *buf_len,
 {
 	size_t i, need;
 	int ret;
+	char *end;
 
-	if (data == NULL || *buf == NULL)
+	if (data == NULL || buf == NULL || *buf == NULL ||
+	    pos == NULL || *pos == NULL || *pos < *buf)
 		return;
 
 	need = os_strlen(field) + len * 2 + 30;
@@ -498,32 +500,31 @@ static void eap_fast_write(char **buf, char **pos, size_t *buf_len,
 		*buf = nbuf;
 		*buf_len += need;
 	}
+	end = *buf + *buf_len;
 
-	ret = os_snprintf(*pos, *buf + *buf_len - *pos, "%s=", field);
-	if (ret < 0 || ret >= *buf + *buf_len - *pos)
+	ret = os_snprintf(*pos, end - *pos, "%s=", field);
+	if (ret < 0 || ret >= end - *pos)
 		return;
 	*pos += ret;
-	*pos += wpa_snprintf_hex(*pos, *buf + *buf_len - *pos, data, len);
-	ret = os_snprintf(*pos, *buf + *buf_len - *pos, "\n");
-	if (ret < 0 || ret >= *buf + *buf_len - *pos)
+	*pos += wpa_snprintf_hex(*pos, end - *pos, data, len);
+	ret = os_snprintf(*pos, end - *pos, "\n");
+	if (ret < 0 || ret >= end - *pos)
 		return;
 	*pos += ret;
 
 	if (txt) {
-		ret = os_snprintf(*pos, *buf + *buf_len - *pos,
-				  "%s-txt=", field);
-		if (ret < 0 || ret >= *buf + *buf_len - *pos)
+		ret = os_snprintf(*pos, end - *pos, "%s-txt=", field);
+		if (ret < 0 || ret >= end - *pos)
 			return;
 		*pos += ret;
 		for (i = 0; i < len; i++) {
-			ret = os_snprintf(*pos, *buf + *buf_len - *pos,
-					  "%c", data[i]);
-			if (ret < 0 || ret >= *buf + *buf_len - *pos)
+			ret = os_snprintf(*pos, end - *pos, "%c", data[i]);
+			if (ret < 0 || ret >= end - *pos)
 				return;
 			*pos += ret;
 		}
-		ret = os_snprintf(*pos, *buf + *buf_len - *pos, "\n");
-		if (ret < 0 || ret >= *buf + *buf_len - *pos)
+		ret = os_snprintf(*pos, end - *pos, "\n");
+		if (ret < 0 || ret >= end - *pos)
 			return;
 		*pos += ret;
 	}
diff --git a/contrib/wpa/src/eap_peer/eap_leap.c b/contrib/wpa/src/eap_peer/eap_leap.c
index 01c1f160abce..a7c94a4d4480 100644
--- a/contrib/wpa/src/eap_peer/eap_leap.c
+++ b/contrib/wpa/src/eap_peer/eap_leap.c
@@ -15,9 +15,9 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/ms_funcs.h"
+#include "crypto/crypto.h"
 #include "eap_i.h"
-#include "ms_funcs.h"
-#include "crypto.h"
 
 #define LEAP_VERSION 1
 #define LEAP_CHALLENGE_LEN 8
@@ -233,10 +233,16 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv,
 	os_memcpy(data->ap_response, pos, LEAP_RESPONSE_LEN);
 
 	if (pwhash) {
-		hash_nt_password_hash(password, pw_hash_hash);
+		if (hash_nt_password_hash(password, pw_hash_hash)) {
+			ret->ignore = TRUE;
+			return NULL;
+		}
 	} else {
-		nt_password_hash(password, password_len, pw_hash);
-		hash_nt_password_hash(pw_hash, pw_hash_hash);
+		if (nt_password_hash(password, password_len, pw_hash) ||
+		    hash_nt_password_hash(pw_hash, pw_hash_hash)) {
+			ret->ignore = TRUE;
+			return NULL;
+		}
 	}
 	challenge_response(data->ap_challenge, pw_hash_hash, expected);
 
@@ -345,11 +351,17 @@ static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
 	if (key == NULL)
 		return NULL;
 
-	if (pwhash)
-		hash_nt_password_hash(password, pw_hash_hash);
-	else {
-		nt_password_hash(password, password_len, pw_hash);
-		hash_nt_password_hash(pw_hash, pw_hash_hash);
+	if (pwhash) {
+		if (hash_nt_password_hash(password, pw_hash_hash)) {
+			os_free(key);
+			return NULL;
+		}
+	} else {
+		if (nt_password_hash(password, password_len, pw_hash) ||
+		    hash_nt_password_hash(pw_hash, pw_hash_hash)) {
+			os_free(key);
+			return NULL;
+		}
 	}
 	wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: pw_hash_hash",
 			pw_hash_hash, 16);
diff --git a/contrib/wpa/src/eap_peer/eap_md5.c b/contrib/wpa/src/eap_peer/eap_md5.c
index 7961143a00c9..0edbae8f74d3 100644
--- a/contrib/wpa/src/eap_peer/eap_md5.c
+++ b/contrib/wpa/src/eap_peer/eap_md5.c
@@ -76,7 +76,7 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv,
 
 	wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response");
 	ret->methodState = METHOD_DONE;
-	ret->decision = DECISION_UNCOND_SUCC;
+	ret->decision = DECISION_COND_SUCC;
 	ret->allowNotifications = TRUE;
 
 	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN,
diff --git a/contrib/wpa/src/eap_peer/eap_methods.c b/contrib/wpa/src/eap_peer/eap_methods.c
index 2374e5e4225c..3b0af055b39c 100644
--- a/contrib/wpa/src/eap_peer/eap_methods.c
+++ b/contrib/wpa/src/eap_peer/eap_methods.c
@@ -339,161 +339,6 @@ int eap_peer_method_register(struct eap_method *method)
 }
 
 
-/**
- * eap_peer_register_methods - Register statically linked EAP peer methods
- * Returns: 0 on success, -1 on failure
- *
- * This function is called at program initialization to register all EAP peer
- * methods that were linked in statically.
- */
-int eap_peer_register_methods(void)
-{
-	int ret = 0;
-
-#ifdef EAP_MD5
-	if (ret == 0) {
-		int eap_peer_md5_register(void);
-		ret = eap_peer_md5_register();
-	}
-#endif /* EAP_MD5 */
-
-#ifdef EAP_TLS
-	if (ret == 0) {
-		int eap_peer_tls_register(void);
-		ret = eap_peer_tls_register();
-	}
-#endif /* EAP_TLS */
-
-#ifdef EAP_MSCHAPv2
-	if (ret == 0) {
-		int eap_peer_mschapv2_register(void);
-		ret = eap_peer_mschapv2_register();
-	}
-#endif /* EAP_MSCHAPv2 */
-
-#ifdef EAP_PEAP
-	if (ret == 0) {
-		int eap_peer_peap_register(void);
-		ret = eap_peer_peap_register();
-	}
-#endif /* EAP_PEAP */
-
-#ifdef EAP_TTLS
-	if (ret == 0) {
-		int eap_peer_ttls_register(void);
-		ret = eap_peer_ttls_register();
-	}
-#endif /* EAP_TTLS */
-
-#ifdef EAP_GTC
-	if (ret == 0) {
-		int eap_peer_gtc_register(void);
-		ret = eap_peer_gtc_register();
-	}
-#endif /* EAP_GTC */
-
-#ifdef EAP_OTP
-	if (ret == 0) {
-		int eap_peer_otp_register(void);
-		ret = eap_peer_otp_register();
-	}
-#endif /* EAP_OTP */
-
-#ifdef EAP_SIM
-	if (ret == 0) {
-		int eap_peer_sim_register(void);
-		ret = eap_peer_sim_register();
-	}
-#endif /* EAP_SIM */
-
-#ifdef EAP_LEAP
-	if (ret == 0) {
-		int eap_peer_leap_register(void);
-		ret = eap_peer_leap_register();
-	}
-#endif /* EAP_LEAP */
-
-#ifdef EAP_PSK
-	if (ret == 0) {
-		int eap_peer_psk_register(void);
-		ret = eap_peer_psk_register();
-	}
-#endif /* EAP_PSK */
-
-#ifdef EAP_AKA
-	if (ret == 0) {
-		int eap_peer_aka_register(void);
-		ret = eap_peer_aka_register();
-	}
-#endif /* EAP_AKA */
-
-#ifdef EAP_AKA_PRIME
-	if (ret == 0) {
-		int eap_peer_aka_prime_register(void);
-		ret = eap_peer_aka_prime_register();
-	}
-#endif /* EAP_AKA_PRIME */
-
-#ifdef EAP_FAST
-	if (ret == 0) {
-		int eap_peer_fast_register(void);
-		ret = eap_peer_fast_register();
-	}
-#endif /* EAP_FAST */
-
-#ifdef EAP_PAX
-	if (ret == 0) {
-		int eap_peer_pax_register(void);
-		ret = eap_peer_pax_register();
-	}
-#endif /* EAP_PAX */
-
-#ifdef EAP_SAKE
-	if (ret == 0) {
-		int eap_peer_sake_register(void);
-		ret = eap_peer_sake_register();
-	}
-#endif /* EAP_SAKE */
-
-#ifdef EAP_GPSK
-	if (ret == 0) {
-		int eap_peer_gpsk_register(void);
-		ret = eap_peer_gpsk_register();
-	}
-#endif /* EAP_GPSK */
-
-#ifdef EAP_WSC
-	if (ret == 0) {
-		int eap_peer_wsc_register(void);
-		ret = eap_peer_wsc_register();
-	}
-#endif /* EAP_WSC */
-
-#ifdef EAP_IKEV2
-	if (ret == 0) {
-		int eap_peer_ikev2_register(void);
-		ret = eap_peer_ikev2_register();
-	}
-#endif /* EAP_IKEV2 */
-
-#ifdef EAP_VENDOR_TEST
-	if (ret == 0) {
-		int eap_peer_vendor_test_register(void);
-		ret = eap_peer_vendor_test_register();
-	}
-#endif /* EAP_VENDOR_TEST */
-
-#ifdef EAP_TNC
-	if (ret == 0) {
-		int eap_peer_tnc_register(void);
-		ret = eap_peer_tnc_register();
-	}
-#endif /* EAP_TNC */
-
-	return ret;
-}
-
-
 /**
  * eap_peer_unregister_methods - Unregister EAP peer methods
  *
diff --git a/contrib/wpa/src/eap_peer/eap_methods.h b/contrib/wpa/src/eap_peer/eap_methods.h
index 9fd9b517c79e..384c61bb70ae 100644
--- a/contrib/wpa/src/eap_peer/eap_methods.h
+++ b/contrib/wpa/src/eap_peer/eap_methods.h
@@ -32,7 +32,6 @@ EapType eap_peer_get_type(const char *name, int *vendor);
 const char * eap_get_name(int vendor, EapType type);
 size_t eap_get_names(char *buf, size_t buflen);
 char ** eap_get_names_as_string_array(size_t *num);
-int eap_peer_register_methods(void);
 void eap_peer_unregister_methods(void);
 
 #else /* IEEE8021X_EAPOL */
@@ -89,4 +88,26 @@ static inline int eap_peer_method_unload(struct eap_method *method)
 
 #endif /* CONFIG_DYNAMIC_EAP_METHODS */
 
+/* EAP peer method registration calls for statically linked in methods */
+int eap_peer_md5_register(void);
+int eap_peer_tls_register(void);
+int eap_peer_mschapv2_register(void);
+int eap_peer_peap_register(void);
+int eap_peer_ttls_register(void);
+int eap_peer_gtc_register(void);
+int eap_peer_otp_register(void);
+int eap_peer_sim_register(void);
+int eap_peer_leap_register(void);
+int eap_peer_psk_register(void);
+int eap_peer_aka_register(void);
+int eap_peer_aka_prime_register(void);
+int eap_peer_fast_register(void);
+int eap_peer_pax_register(void);
+int eap_peer_sake_register(void);
+int eap_peer_gpsk_register(void);
+int eap_peer_wsc_register(void);
+int eap_peer_ikev2_register(void);
+int eap_peer_vendor_test_register(void);
+int eap_peer_tnc_register(void);
+
 #endif /* EAP_METHODS_H */
diff --git a/contrib/wpa/src/eap_peer/eap_mschapv2.c b/contrib/wpa/src/eap_peer/eap_mschapv2.c
index b0c3ab77632b..cd410d91b5df 100644
--- a/contrib/wpa/src/eap_peer/eap_mschapv2.c
+++ b/contrib/wpa/src/eap_peer/eap_mschapv2.c
@@ -22,11 +22,11 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/ms_funcs.h"
+#include "common/wpa_ctrl.h"
+#include "mschapv2.h"
 #include "eap_i.h"
 #include "eap_config.h"
-#include "ms_funcs.h"
-#include "wpa_ctrl.h"
-#include "mschapv2.h"
 
 
 #ifdef _MSC_VER
@@ -209,10 +209,15 @@ static struct wpabuf * eap_mschapv2_challenge_reply(
 			   "in Phase 1");
 		auth_challenge = data->auth_challenge;
 	}
-	mschapv2_derive_response(identity, identity_len, password,
-				 password_len, pwhash, auth_challenge,
-				 peer_challenge, r->nt_response,
-				 data->auth_response, data->master_key);
+	if (mschapv2_derive_response(identity, identity_len, password,
+				     password_len, pwhash, auth_challenge,
+				     peer_challenge, r->nt_response,
+				     data->auth_response, data->master_key)) {
+		wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to derive "
+			   "response");
+		wpabuf_free(resp);
+		return NULL;
+	}
 	data->auth_response_valid = 1;
 	data->master_key_valid = 1;
 
diff --git a/contrib/wpa/src/eap_peer/eap_pax.c b/contrib/wpa/src/eap_peer/eap_pax.c
index afd56dd49b7f..2e04831ae53d 100644
--- a/contrib/wpa/src/eap_peer/eap_pax.c
+++ b/contrib/wpa/src/eap_peer/eap_pax.c
@@ -15,10 +15,8 @@
 #include "includes.h"
 
 #include "common.h"
-#include "eap_peer/eap_i.h"
 #include "eap_common/eap_pax_common.h"
-#include "sha1.h"
-#include "crypto.h"
+#include "eap_i.h"
 
 /*
  * Note: only PAX_STD subprotocol is currently supported
diff --git a/contrib/wpa/src/eap_peer/eap_peap.c b/contrib/wpa/src/eap_peer/eap_peap.c
index 894fc632fda3..2b72084e5433 100644
--- a/contrib/wpa/src/eap_peer/eap_peap.c
+++ b/contrib/wpa/src/eap_peer/eap_peap.c
@@ -16,12 +16,12 @@
 
 #include "common.h"
 #include "crypto/sha1.h"
+#include "crypto/tls.h"
+#include "eap_common/eap_tlv_common.h"
+#include "eap_common/eap_peap_common.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
 #include "eap_config.h"
-#include "tls.h"
-#include "eap_common/eap_tlv_common.h"
-#include "eap_common/eap_peap_common.h"
 #include "tncc.h"
 
 
@@ -1048,10 +1048,10 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
 
 	if (flags & EAP_TLS_FLAGS_START) {
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own "
-			   "ver=%d)", flags & EAP_PEAP_VERSION_MASK,
+			   "ver=%d)", flags & EAP_TLS_VERSION_MASK,
 			data->peap_version);
-		if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version)
-			data->peap_version = flags & EAP_PEAP_VERSION_MASK;
+		if ((flags & EAP_TLS_VERSION_MASK) < data->peap_version)
+			data->peap_version = flags & EAP_TLS_VERSION_MASK;
 		if (data->force_peap_version >= 0 &&
 		    data->force_peap_version != data->peap_version) {
 			wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select "
diff --git a/contrib/wpa/src/eap_peer/eap_psk.c b/contrib/wpa/src/eap_peer/eap_psk.c
index 1ce635663982..ccf871e13ba0 100644
--- a/contrib/wpa/src/eap_peer/eap_psk.c
+++ b/contrib/wpa/src/eap_peer/eap_psk.c
@@ -18,9 +18,9 @@
 #include "includes.h"
 
 #include "common.h"
-#include "eap_peer/eap_i.h"
-#include "aes_wrap.h"
+#include "crypto/aes_wrap.h"
 #include "eap_common/eap_psk_common.h"
+#include "eap_i.h"
 
 
 struct eap_psk_data {
diff --git a/contrib/wpa/src/eap_peer/eap_sim.c b/contrib/wpa/src/eap_peer/eap_sim.c
index 5e30d1f7ed41..3d8afb22fb00 100644
--- a/contrib/wpa/src/eap_peer/eap_sim.c
+++ b/contrib/wpa/src/eap_peer/eap_sim.c
@@ -15,13 +15,11 @@
 #include "includes.h"
 
 #include "common.h"
+#include "pcsc_funcs.h"
+#include "crypto/milenage.h"
 #include "eap_peer/eap_i.h"
 #include "eap_config.h"
-#include "pcsc_funcs.h"
 #include "eap_common/eap_sim_common.h"
-#ifdef CONFIG_SIM_SIMULATOR
-#include "hlr_auc_gw/milenage.h"
-#endif /* CONFIG_SIM_SIMULATOR */
 
 
 struct eap_sim_data {
diff --git a/contrib/wpa/src/eap_peer/eap_tls.c b/contrib/wpa/src/eap_peer/eap_tls.c
index 31344a9136b2..20b2212e1cdc 100644
--- a/contrib/wpa/src/eap_peer/eap_tls.c
+++ b/contrib/wpa/src/eap_peer/eap_tls.c
@@ -15,10 +15,10 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/tls.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
 #include "eap_config.h"
-#include "tls.h"
 
 
 static void eap_tls_deinit(struct eap_sm *sm, void *priv);
diff --git a/contrib/wpa/src/eap_peer/eap_tls_common.c b/contrib/wpa/src/eap_peer/eap_tls_common.c
index 186feaada442..7bd50f677bc8 100644
--- a/contrib/wpa/src/eap_peer/eap_tls_common.c
+++ b/contrib/wpa/src/eap_peer/eap_tls_common.c
@@ -1,6 +1,6 @@
 /*
  * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2008, Jouni Malinen 
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -15,11 +15,11 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
 #include "eap_config.h"
-#include "sha1.h"
-#include "tls.h"
 
 
 static int eap_tls_check_blob(struct eap_sm *sm, const char **name,
@@ -169,10 +169,14 @@ static int eap_tls_init_connection(struct eap_sm *sm,
 		config->pin = NULL;
 		eap_sm_request_pin(sm);
 		sm->ignore = TRUE;
+		tls_connection_deinit(sm->ssl_ctx, data->conn);
+		data->conn = NULL;
 		return -1;
 	} else if (res) {
 		wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection "
 			   "parameters");
+		tls_connection_deinit(sm->ssl_ctx, data->conn);
+		data->conn = NULL;
 		return -1;
 	}
 
@@ -310,27 +314,29 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
  * eap_peer_tls_reassemble_fragment - Reassemble a received fragment
  * @data: Data for TLS processing
  * @in_data: Next incoming TLS segment
- * @in_len: Length of in_data
  * Returns: 0 on success, 1 if more data is needed for the full message, or
  * -1 on error
  */
 static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
-					    const u8 *in_data, size_t in_len)
+					    const struct wpabuf *in_data)
 {
-	u8 *buf;
+	size_t tls_in_len, in_len;
 
-	if (data->tls_in_len + in_len == 0) {
+	tls_in_len = data->tls_in ? wpabuf_len(data->tls_in) : 0;
+	in_len = in_data ? wpabuf_len(in_data) : 0;
+
+	if (tls_in_len + in_len == 0) {
 		/* No message data received?! */
 		wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: "
 			   "tls_in_left=%lu tls_in_len=%lu in_len=%lu",
 			   (unsigned long) data->tls_in_left,
-			   (unsigned long) data->tls_in_len,
+			   (unsigned long) tls_in_len,
 			   (unsigned long) in_len);
 		eap_peer_tls_reset_input(data);
 		return -1;
 	}
 
-	if (data->tls_in_len + in_len > 65536) {
+	if (tls_in_len + in_len > 65536) {
 		/*
 		 * Limit length to avoid rogue servers from causing large
 		 * memory allocations.
@@ -349,16 +355,13 @@ static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
 		return -1;
 	}
 
-	buf = os_realloc(data->tls_in, data->tls_in_len + in_len);
-	if (buf == NULL) {
+	if (wpabuf_resize(&data->tls_in, in_len) < 0) {
 		wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS "
 			   "data");
 		eap_peer_tls_reset_input(data);
 		return -1;
 	}
-	os_memcpy(buf + data->tls_in_len, in_data, in_len);
-	data->tls_in = buf;
-	data->tls_in_len += in_len;
+	wpabuf_put_buf(data->tls_in, in_data);
 	data->tls_in_left -= in_len;
 
 	if (data->tls_in_left > 0) {
@@ -375,8 +378,6 @@ static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
  * eap_peer_tls_data_reassemble - Reassemble TLS data
  * @data: Data for TLS processing
  * @in_data: Next incoming TLS segment
- * @in_len: Length of in_data
- * @out_len: Variable for returning length of the reassembled message
  * @need_more_input: Variable for returning whether more input data is needed
  * to reassemble this TLS packet
  * Returns: Pointer to output data, %NULL on error or when more data is needed
@@ -385,16 +386,15 @@ static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data,
  * This function reassembles TLS fragments. Caller must not free the returned
  * data buffer since an internal pointer to it is maintained.
  */
-const u8 * eap_peer_tls_data_reassemble(
-	struct eap_ssl_data *data, const u8 *in_data, size_t in_len,
-	size_t *out_len, int *need_more_input)
+static const struct wpabuf * eap_peer_tls_data_reassemble(
+	struct eap_ssl_data *data, const struct wpabuf *in_data,
+	int *need_more_input)
 {
 	*need_more_input = 0;
 
-	if (data->tls_in_left > in_len || data->tls_in) {
+	if (data->tls_in_left > wpabuf_len(in_data) || data->tls_in) {
 		/* Message has fragments */
-		int res = eap_peer_tls_reassemble_fragment(data, in_data,
-							   in_len);
+		int res = eap_peer_tls_reassemble_fragment(data, in_data);
 		if (res) {
 			if (res == 1)
 				*need_more_input = 1;
@@ -405,14 +405,11 @@ const u8 * eap_peer_tls_data_reassemble(
 	} else {
 		/* No fragments in this message, so just make a copy of it. */
 		data->tls_in_left = 0;
-		data->tls_in = os_malloc(in_len ? in_len : 1);
+		data->tls_in = wpabuf_dup(in_data);
 		if (data->tls_in == NULL)
 			return NULL;
-		os_memcpy(data->tls_in, in_data, in_len);
-		data->tls_in_len = in_len;
 	}
 
-	*out_len = data->tls_in_len;
 	return data->tls_in;
 }
 
@@ -431,14 +428,13 @@ static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
 				 const u8 *in_data, size_t in_len,
 				 struct wpabuf **out_data)
 {
-	const u8 *msg;
-	size_t msg_len;
+	const struct wpabuf *msg;
 	int need_more_input;
-	u8 *appl_data;
-	size_t appl_data_len;
+	struct wpabuf *appl_data;
+	struct wpabuf buf;
 
-	msg = eap_peer_tls_data_reassemble(data, in_data, in_len,
-					   &msg_len, &need_more_input);
+	wpabuf_set(&buf, in_data, in_len);
+	msg = eap_peer_tls_data_reassemble(data, &buf, &need_more_input);
 	if (msg == NULL)
 		return need_more_input ? 1 : -1;
 
@@ -447,31 +443,25 @@ static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
 		/* This should not happen.. */
 		wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending "
 			   "tls_out data even though tls_out_len = 0");
-		os_free(data->tls_out);
+		wpabuf_free(data->tls_out);
 		WPA_ASSERT(data->tls_out == NULL);
 	}
 	appl_data = NULL;
 	data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
-						 msg, msg_len,
-						 &data->tls_out_len,
-						 &appl_data, &appl_data_len);
+						 msg, &appl_data);
 
 	eap_peer_tls_reset_input(data);
 
 	if (appl_data &&
 	    tls_connection_established(sm->ssl_ctx, data->conn) &&
 	    !tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
-		wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data",
-				appl_data, appl_data_len);
-		*out_data = wpabuf_alloc_ext_data(appl_data, appl_data_len);
-		if (*out_data == NULL) {
-			os_free(appl_data);
-			return -1;
-		}
+		wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application data",
+				    appl_data);
+		*out_data = appl_data;
 		return 2;
 	}
 
-	os_free(appl_data);
+	wpabuf_free(appl_data);
 
 	return 0;
 }
@@ -494,11 +484,14 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
 	size_t len;
 	u8 *flags;
 	int more_fragments, length_included;
-	
-	len = data->tls_out_len - data->tls_out_pos;
+
+	if (data->tls_out == NULL)
+		return -1;
+	len = wpabuf_len(data->tls_out) - data->tls_out_pos;
 	wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
 		   "%lu bytes)",
-		   (unsigned long) len, (unsigned long) data->tls_out_len);
+		   (unsigned long) len,
+		   (unsigned long) wpabuf_len(data->tls_out));
 
 	/*
 	 * Limit outgoing message to the configured maximum size. Fragment
@@ -513,7 +506,7 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
 		more_fragments = 0;
 
 	length_included = data->tls_out_pos == 0 &&
-		(data->tls_out_len > data->tls_out_limit ||
+		(wpabuf_len(data->tls_out) > data->tls_out_limit ||
 		 data->include_tls_length);
 	if (!length_included &&
 	    eap_type == EAP_TYPE_PEAP && peap_version == 0 &&
@@ -539,10 +532,12 @@ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
 		*flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
 	if (length_included) {
 		*flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
-		wpabuf_put_be32(*out_data, data->tls_out_len);
+		wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out));
 	}
 
-	wpabuf_put_data(*out_data, &data->tls_out[data->tls_out_pos], len);
+	wpabuf_put_data(*out_data,
+			wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
+			len);
 	data->tls_out_pos += len;
 
 	if (!more_fragments)
@@ -590,13 +585,13 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
 
 	*out_data = NULL;
 
-	if (data->tls_out_len > 0 && in_len > 0) {
+	if (data->tls_out && wpabuf_len(data->tls_out) > 0 && in_len > 0) {
 		wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output "
 			   "fragments are waiting to be sent out");
 		return -1;
 	}
 
-	if (data->tls_out_len == 0) {
+	if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) {
 		/*
 		 * No more data to send out - expect to receive more data from
 		 * the AS.
@@ -635,14 +630,14 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
 		/* TODO: clean pin if engine used? */
 	}
 
-	if (data->tls_out_len == 0) {
+	if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) {
 		/*
 		 * TLS negotiation should now be complete since all other cases
 		 * needing more data should have been caught above based on
 		 * the TLS Message Length field.
 		 */
 		wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
-		os_free(data->tls_out);
+		wpabuf_free(data->tls_out);
 		data->tls_out = NULL;
 		return 1;
 	}
@@ -794,9 +789,8 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
 		if (data->tls_in_left == 0) {
 			data->tls_in_total = tls_msg_len;
 			data->tls_in_left = tls_msg_len;
-			os_free(data->tls_in);
+			wpabuf_free(data->tls_in);
 			data->tls_in = NULL;
-			data->tls_in_len = 0;
 		}
 		pos += 4;
 		left -= 4;
@@ -821,8 +815,8 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm,
  */
 void eap_peer_tls_reset_input(struct eap_ssl_data *data)
 {
-	data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
-	os_free(data->tls_in);
+	data->tls_in_left = data->tls_in_total = 0;
+	wpabuf_free(data->tls_in);
 	data->tls_in = NULL;
 }
 
@@ -836,9 +830,8 @@ void eap_peer_tls_reset_input(struct eap_ssl_data *data)
  */
 void eap_peer_tls_reset_output(struct eap_ssl_data *data)
 {
-	data->tls_out_len = 0;
 	data->tls_out_pos = 0;
-	os_free(data->tls_out);
+	wpabuf_free(data->tls_out);
 	data->tls_out = NULL;
 }
 
@@ -855,44 +848,19 @@ int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data,
 			 const struct wpabuf *in_data,
 			 struct wpabuf **in_decrypted)
 {
-	int res;
-	const u8 *msg;
-	size_t msg_len, buf_len;
+	const struct wpabuf *msg;
 	int need_more_input;
 
-	msg = eap_peer_tls_data_reassemble(data, wpabuf_head(in_data),
-					   wpabuf_len(in_data), &msg_len,
-					   &need_more_input);
+	msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input);
 	if (msg == NULL)
 		return need_more_input ? 1 : -1;
 
-	buf_len = wpabuf_len(in_data);
-	if (data->tls_in_total > buf_len)
-		buf_len = data->tls_in_total;
-	/*
-	 * Even though we try to disable TLS compression, it is possible that
-	 * this cannot be done with all TLS libraries. Add extra buffer space
-	 * to handle the possibility of the decrypted data being longer than
-	 * input data.
-	 */
-	buf_len += 500;
-	buf_len *= 3;
-	*in_decrypted = wpabuf_alloc(buf_len ? buf_len : 1);
-	if (*in_decrypted == NULL) {
-		eap_peer_tls_reset_input(data);
-		wpa_printf(MSG_WARNING, "SSL: Failed to allocate memory for "
-			   "decryption");
-		return -1;
-	}
-
-	res = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg, msg_len,
-				     wpabuf_mhead(*in_decrypted), buf_len);
+	*in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg);
 	eap_peer_tls_reset_input(data);
-	if (res < 0) {
+	if (*in_decrypted == NULL) {
 		wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data");
 		return -1;
 	}
-	wpabuf_put(*in_decrypted, res);
 	return 0;
 }
 
@@ -913,29 +881,17 @@ int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data,
 			 const struct wpabuf *in_data,
 			 struct wpabuf **out_data)
 {
-	int res;
-	size_t len;
-
 	if (in_data) {
 		eap_peer_tls_reset_output(data);
-		len = wpabuf_len(in_data) + 300;
-		data->tls_out = os_malloc(len);
-		if (data->tls_out == NULL)
-			return -1;
-
-		res = tls_connection_encrypt(sm->ssl_ctx, data->conn,
-					     wpabuf_head(in_data),
-					     wpabuf_len(in_data),
-					     data->tls_out, len);
-		if (res < 0) {
+		data->tls_out = tls_connection_encrypt(sm->ssl_ctx, data->conn,
+						       in_data);
+		if (data->tls_out == NULL) {
 			wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 "
 				   "data (in_len=%lu)",
 				   (unsigned long) wpabuf_len(in_data));
 			eap_peer_tls_reset_output(data);
 			return -1;
 		}
-
-		data->tls_out_len = res;
 	}
 
 	return eap_tls_process_output(data, eap_type, peap_version, id, 0,
diff --git a/contrib/wpa/src/eap_peer/eap_tls_common.h b/contrib/wpa/src/eap_peer/eap_tls_common.h
index 2c87427c28f5..e9e0998098cc 100644
--- a/contrib/wpa/src/eap_peer/eap_tls_common.h
+++ b/contrib/wpa/src/eap_peer/eap_tls_common.h
@@ -1,6 +1,6 @@
 /*
  * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2006, Jouni Malinen 
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -27,12 +27,7 @@ struct eap_ssl_data {
 	/**
 	 * tls_out - TLS message to be sent out in fragments
 	 */
-	u8 *tls_out;
-
-	/**
-	 * tls_out_len - Total length of the outgoing TLS message
-	 */
-	size_t tls_out_len;
+	struct wpabuf *tls_out;
 
 	/**
 	 * tls_out_pos - The current position in the outgoing TLS message
@@ -47,12 +42,7 @@ struct eap_ssl_data {
 	/**
 	 * tls_in - Received TLS message buffer for re-assembly
 	 */
-	u8 *tls_in;
-
-	/**
-	 * tls_in_len - Number of bytes of the received TLS message in tls_in
-	 */
-	size_t tls_in_len;
+	struct wpabuf *tls_in;
 
 	/**
 	 * tls_in_left - Number of remaining bytes in the incoming TLS message
@@ -81,7 +71,7 @@ struct eap_ssl_data {
 	int tls_ia;
 
 	/**
-	 * eap - Pointer to EAP state machine allocated with eap_peer_sm_init()
+	 * eap - EAP state machine allocated with eap_peer_sm_init()
 	 */
 	struct eap_sm *eap;
 };
@@ -91,7 +81,7 @@ struct eap_ssl_data {
 #define EAP_TLS_FLAGS_LENGTH_INCLUDED 0x80
 #define EAP_TLS_FLAGS_MORE_FRAGMENTS 0x40
 #define EAP_TLS_FLAGS_START 0x20
-#define EAP_PEAP_VERSION_MASK 0x07
+#define EAP_TLS_VERSION_MASK 0x07
 
  /* could be up to 128 bytes, but only the first 64 bytes are used */
 #define EAP_TLS_KEY_LEN 64
@@ -102,9 +92,6 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
 u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 			     const char *label, size_t len);
-const u8 * eap_peer_tls_data_reassemble(
-	struct eap_ssl_data *data, const u8 *in_data, size_t in_len,
-	size_t *out_len, int *need_more_input);
 int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
 				EapType eap_type, int peap_version,
 				u8 id, const u8 *in_data, size_t in_len,
diff --git a/contrib/wpa/src/eap_peer/eap_tnc.c b/contrib/wpa/src/eap_peer/eap_tnc.c
index c56001528113..6c95f72c1507 100644
--- a/contrib/wpa/src/eap_peer/eap_tnc.c
+++ b/contrib/wpa/src/eap_peer/eap_tnc.c
@@ -73,12 +73,13 @@ static struct wpabuf * eap_tnc_build_frag_ack(u8 id, u8 code)
 {
 	struct wpabuf *msg;
 
-	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 0, code, id);
+	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, code, id);
 	if (msg == NULL) {
 		wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory "
 			   "for fragment ack");
 		return NULL;
 	}
+	wpabuf_put_u8(msg, EAP_TNC_VERSION); /* Flags */
 
 	wpa_printf(MSG_DEBUG, "EAP-TNC: Send fragment ack");
 
@@ -262,7 +263,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv,
 		   "Message Length %u", flags, message_length);
 
 	if (data->state == WAIT_FRAG_ACK) {
-		if (len != 0) {
+		if (len > 1) {
 			wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload in "
 				   "WAIT_FRAG_ACK state");
 			ret->ignore = TRUE;
diff --git a/contrib/wpa/src/eap_peer/eap_ttls.c b/contrib/wpa/src/eap_peer/eap_ttls.c
index 0851f8bb4d50..25737803beed 100644
--- a/contrib/wpa/src/eap_peer/eap_ttls.c
+++ b/contrib/wpa/src/eap_peer/eap_ttls.c
@@ -15,15 +15,15 @@
 #include "includes.h"
 
 #include "common.h"
-#include "eap_peer/eap_i.h"
-#include "eap_peer/eap_tls_common.h"
-#include "eap_peer/eap_config.h"
-#include "ms_funcs.h"
-#include "sha1.h"
+#include "crypto/ms_funcs.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "eap_common/chap.h"
-#include "tls.h"
-#include "mschapv2.h"
 #include "eap_common/eap_ttls.h"
+#include "mschapv2.h"
+#include "eap_i.h"
+#include "eap_tls_common.h"
+#include "eap_config.h"
 
 
 /* Maximum supported TTLS version
@@ -691,10 +691,15 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
 	pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
 	os_memset(pos, 0, 8); /* Reserved, must be zero */
 	pos += 8;
-	mschapv2_derive_response(identity, identity_len, password,
-				 password_len, pwhash, challenge,
-				 peer_challenge, pos, data->auth_response,
-				 data->master_key);
+	if (mschapv2_derive_response(identity, identity_len, password,
+				     password_len, pwhash, challenge,
+				     peer_challenge, pos, data->auth_response,
+				     data->master_key)) {
+		wpabuf_free(msg);
+		wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
+			   "response");
+		return -1;
+	}
 	data->auth_response_valid = 1;
 
 	eap_ttlsv1_permute_inner(sm, data);
@@ -1026,27 +1031,25 @@ static int eap_ttls_phase2_request(struct eap_sm *sm,
 static struct wpabuf * eap_ttls_build_phase_finished(
 	struct eap_sm *sm, struct eap_ttls_data *data, int id, int final)
 {
-	int len;
-	struct wpabuf *req;
-	u8 *pos;
-	const int max_len = 300;
+	struct wpabuf *req, *buf;
 
-	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, 1 + max_len,
-			    EAP_CODE_RESPONSE, id);
-	if (req == NULL)
+	buf = tls_connection_ia_send_phase_finished(sm->ssl_ctx,
+						    data->ssl.conn,
+						    final);
+	if (buf == NULL)
 		return NULL;
 
-	wpabuf_put_u8(req, data->ttls_version);
-
-	pos = wpabuf_put(req, 0);
-	len = tls_connection_ia_send_phase_finished(sm->ssl_ctx,
-						    data->ssl.conn,
-						    final, pos, max_len);
-	if (len < 0) {
-		wpabuf_free(req);
+	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS,
+			    1 + wpabuf_len(buf),
+			    EAP_CODE_RESPONSE, id);
+	if (req == NULL) {
+		wpabuf_free(buf);
 		return NULL;
 	}
-	wpabuf_put(req, len);
+
+	wpabuf_put_u8(req, data->ttls_version);
+	wpabuf_put_buf(req, buf);
+	wpabuf_free(buf);
 	eap_update_len(req);
 
 	return req;
@@ -1666,10 +1669,10 @@ static int eap_ttls_process_start(struct eap_sm *sm,
 	struct eap_peer_config *config = eap_get_config(sm);
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own ver=%d)",
-		   flags & EAP_PEAP_VERSION_MASK, data->ttls_version);
+		   flags & EAP_TLS_VERSION_MASK, data->ttls_version);
 #if EAP_TTLS_VERSION > 0
-	if ((flags & EAP_PEAP_VERSION_MASK) < data->ttls_version)
-		data->ttls_version = flags & EAP_PEAP_VERSION_MASK;
+	if ((flags & EAP_TLS_VERSION_MASK) < data->ttls_version)
+		data->ttls_version = flags & EAP_TLS_VERSION_MASK;
 	if (data->force_ttls_version >= 0 &&
 	    data->force_ttls_version != data->ttls_version) {
 		wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to select "
diff --git a/contrib/wpa/src/eap_peer/eap_wsc.c b/contrib/wpa/src/eap_peer/eap_wsc.c
index 7c8ad2fdad98..8317f728f8ea 100644
--- a/contrib/wpa/src/eap_peer/eap_wsc.c
+++ b/contrib/wpa/src/eap_peer/eap_wsc.c
@@ -1,6 +1,6 @@
 /*
  * EAP-WSC peer for Wi-Fi Protected Setup
- * Copyright (c) 2007-2008, Jouni Malinen 
+ * Copyright (c) 2007-2009, Jouni Malinen 
  *
  * 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
@@ -65,6 +65,72 @@ static void eap_wsc_state(struct eap_wsc_data *data, int state)
 }
 
 
+static int eap_wsc_new_ap_settings(struct wps_credential *cred,
+				   const char *params)
+{
+	const char *pos, *end;
+	size_t len;
+
+	os_memset(cred, 0, sizeof(*cred));
+
+	pos = os_strstr(params, "new_ssid=");
+	if (pos == NULL)
+		return 0;
+	pos += 9;
+	end = os_strchr(pos, ' ');
+	if (end == NULL)
+		len = os_strlen(pos);
+	else
+		len = end - pos;
+	if ((len & 1) || len > 2 * sizeof(cred->ssid) ||
+	    hexstr2bin(pos, cred->ssid, len / 2))
+		return -1;
+	cred->ssid_len = len / 2;
+
+	pos = os_strstr(params, "new_auth=");
+	if (pos == NULL)
+		return -1;
+	if (os_strncmp(pos + 9, "OPEN", 4) == 0)
+		cred->auth_type = WPS_AUTH_OPEN;
+	else if (os_strncmp(pos + 9, "WPAPSK", 6) == 0)
+		cred->auth_type = WPS_AUTH_WPAPSK;
+	else if (os_strncmp(pos + 9, "WPA2PSK", 7) == 0)
+		cred->auth_type = WPS_AUTH_WPA2PSK;
+	else
+		return -1;
+
+	pos = os_strstr(params, "new_encr=");
+	if (pos == NULL)
+		return -1;
+	if (os_strncmp(pos + 9, "NONE", 4) == 0)
+		cred->encr_type = WPS_ENCR_NONE;
+	else if (os_strncmp(pos + 9, "WEP", 3) == 0)
+		cred->encr_type = WPS_ENCR_WEP;
+	else if (os_strncmp(pos + 9, "TKIP", 4) == 0)
+		cred->encr_type = WPS_ENCR_TKIP;
+	else if (os_strncmp(pos + 9, "CCMP", 4) == 0)
+		cred->encr_type = WPS_ENCR_AES;
+	else
+		return -1;
+
+	pos = os_strstr(params, "new_key=");
+	if (pos == NULL)
+		return 0;
+	pos += 8;
+	end = os_strchr(pos, ' ');
+	if (end == NULL)
+		len = os_strlen(pos);
+	else
+		len = end - pos;
+	if ((len & 1) || len > 2 * sizeof(cred->key) ||
+	    hexstr2bin(pos, cred->key, len / 2))
+		return -1;
+	cred->key_len = len / 2;
+
+	return 1;
+}
+
+
 static void * eap_wsc_init(struct eap_sm *sm)
 {
 	struct eap_wsc_data *data;
@@ -75,6 +141,8 @@ static void * eap_wsc_init(struct eap_sm *sm)
 	const char *pos;
 	const char *phase1;
 	struct wps_context *wps;
+	struct wps_credential new_ap_settings;
+	int res;
 
 	wps = sm->wps;
 	if (wps == NULL) {
@@ -135,6 +203,17 @@ static void * eap_wsc_init(struct eap_sm *sm)
 		return NULL;
 	}
 
+	res = eap_wsc_new_ap_settings(&new_ap_settings, phase1);
+	if (res < 0) {
+		os_free(data);
+		return NULL;
+	}
+	if (res == 1) {
+		wpa_printf(MSG_DEBUG, "EAP-WSC: Provide new AP settings for "
+			   "WPS");
+		cfg.new_ap_settings = &new_ap_settings;
+	}
+
 	data->wps = wps_init(&cfg);
 	if (data->wps == NULL) {
 		os_free(data);
@@ -147,6 +226,10 @@ static void * eap_wsc_init(struct eap_sm *sm)
 				      cfg.pin, cfg.pin_len, 0);
 	}
 
+	/* Use reduced client timeout for WPS to avoid long wait */
+	if (sm->ClientTimeout > 30)
+		sm->ClientTimeout = 30;
+
 	return data;
 }
 
@@ -302,6 +385,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv,
 	u16 message_length = 0;
 	enum wps_process_res res;
 	struct wpabuf tmpbuf;
+	struct wpabuf *r;
 
 	pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, reqData,
 			       &len);
@@ -427,7 +511,13 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv,
 	}
 
 	eap_wsc_state(data, MESG);
-	return eap_wsc_build_msg(data, ret, id);
+	r = eap_wsc_build_msg(data, ret, id);
+	if (data->state == FAIL && ret->methodState == METHOD_DONE) {
+		/* Use reduced client timeout for WPS to avoid long wait */
+		if (sm->ClientTimeout > 2)
+			sm->ClientTimeout = 2;
+	}
+	return r;
 }
 
 
diff --git a/contrib/wpa/src/eap_peer/ikev2.c b/contrib/wpa/src/eap_peer/ikev2.c
index 9172e1f3481d..309a331124eb 100644
--- a/contrib/wpa/src/eap_peer/ikev2.c
+++ b/contrib/wpa/src/eap_peer/ikev2.c
@@ -15,7 +15,7 @@
 #include "includes.h"
 
 #include "common.h"
-#include "dh_groups.h"
+#include "crypto/dh_groups.h"
 #include "ikev2.h"
 
 
diff --git a/contrib/wpa/src/eap_peer/mschapv2.c b/contrib/wpa/src/eap_peer/mschapv2.c
index 01c22d89753f..b8fb07502fd7 100644
--- a/contrib/wpa/src/eap_peer/mschapv2.c
+++ b/contrib/wpa/src/eap_peer/mschapv2.c
@@ -15,7 +15,7 @@
 #include "includes.h"
 
 #include "common.h"
-#include "ms_funcs.h"
+#include "crypto/ms_funcs.h"
 #include "mschapv2.h"
 
 const u8 * mschapv2_remove_domain(const u8 *username, size_t *len)
@@ -39,13 +39,13 @@ const u8 * mschapv2_remove_domain(const u8 *username, size_t *len)
 }
 
 
-void mschapv2_derive_response(const u8 *identity, size_t identity_len,
-			      const u8 *password, size_t password_len,
-			      int pwhash,
-			      const u8 *auth_challenge,
-			      const u8 *peer_challenge,
-			      u8 *nt_response, u8 *auth_response,
-			      u8 *master_key)
+int mschapv2_derive_response(const u8 *identity, size_t identity_len,
+			     const u8 *password, size_t password_len,
+			     int pwhash,
+			     const u8 *auth_challenge,
+			     const u8 *peer_challenge,
+			     u8 *nt_response, u8 *auth_response,
+			     u8 *master_key)
 {
 	const u8 *username;
 	size_t username_len;
@@ -93,14 +93,18 @@ void mschapv2_derive_response(const u8 *identity, size_t identity_len,
 
 	/* Generate master_key here since we have the needed data available. */
 	if (pwhash) {
-		hash_nt_password_hash(password, password_hash_hash);
+		if (hash_nt_password_hash(password, password_hash_hash))
+			return -1;
 	} else {
-		nt_password_hash(password, password_len, password_hash);
-		hash_nt_password_hash(password_hash, password_hash_hash);
+		if (nt_password_hash(password, password_len, password_hash) ||
+		    hash_nt_password_hash(password_hash, password_hash_hash))
+			return -1;
 	}
 	get_master_key(password_hash_hash, nt_response, master_key);
 	wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key",
 			master_key, MSCHAPV2_MASTER_KEY_LEN);
+
+	return 0;
 }
 
 
diff --git a/contrib/wpa/src/eap_peer/mschapv2.h b/contrib/wpa/src/eap_peer/mschapv2.h
index c7c36f772178..90dad31ef72a 100644
--- a/contrib/wpa/src/eap_peer/mschapv2.h
+++ b/contrib/wpa/src/eap_peer/mschapv2.h
@@ -21,13 +21,13 @@
 #define MSCHAPV2_MASTER_KEY_LEN 16
 
 const u8 * mschapv2_remove_domain(const u8 *username, size_t *len);
-void mschapv2_derive_response(const u8 *username, size_t username_len,
-			      const u8 *password, size_t password_len,
-			      int pwhash,
-			      const u8 *auth_challenge,
-			      const u8 *peer_challenge,
-			      u8 *nt_response, u8 *auth_response,
-			      u8 *master_key);
+int mschapv2_derive_response(const u8 *username, size_t username_len,
+			     const u8 *password, size_t password_len,
+			     int pwhash,
+			     const u8 *auth_challenge,
+			     const u8 *peer_challenge,
+			     u8 *nt_response, u8 *auth_response,
+			     u8 *master_key);
 int mschapv2_verify_auth_response(const u8 *auth_response,
 				  const u8 *buf, size_t buf_len);
 
diff --git a/contrib/wpa/src/eap_server/Makefile b/contrib/wpa/src/eap_server/Makefile
index cffba620da04..9c41962fd7e1 100644
--- a/contrib/wpa/src/eap_server/Makefile
+++ b/contrib/wpa/src/eap_server/Makefile
@@ -2,7 +2,6 @@ all:
 	@echo Nothing to be made.
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
 	rm -f *~ *.o *.d
 
 install:
diff --git a/contrib/wpa/src/eap_server/eap.h b/contrib/wpa/src/eap_server/eap.h
index 6a20da4f46b0..92400a5680c4 100644
--- a/contrib/wpa/src/eap_server/eap.h
+++ b/contrib/wpa/src/eap_server/eap.h
@@ -15,7 +15,7 @@
 #ifndef EAP_H
 #define EAP_H
 
-#include "defs.h"
+#include "common/defs.h"
 #include "eap_common/eap_defs.h"
 #include "eap_server/eap_methods.h"
 #include "wpabuf.h"
@@ -91,6 +91,7 @@ struct eapol_callbacks {
 
 struct eap_config {
 	void *ssl_ctx;
+	void *msg_ctx;
 	void *eap_sim_db_priv;
 	Boolean backend_auth;
 	int eap_server;
@@ -105,6 +106,7 @@ struct eap_config {
 	int tnc;
 	struct wps_context *wps;
 	const struct wpabuf *assoc_wps_ie;
+	const u8 *peer_addr;
 };
 
 
diff --git a/contrib/wpa/src/eap_server/eap_i.h b/contrib/wpa/src/eap_server/eap_i.h
index d52b86f9558f..4269a8cfd6a0 100644
--- a/contrib/wpa/src/eap_server/eap_i.h
+++ b/contrib/wpa/src/eap_server/eap_i.h
@@ -185,6 +185,8 @@ struct eap_sm {
 	struct wpabuf *assoc_wps_ie;
 
 	Boolean start_reauth;
+
+	u8 peer_addr[ETH_ALEN];
 };
 
 int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
diff --git a/contrib/wpa/src/eap_server/eap_methods.h b/contrib/wpa/src/eap_server/eap_methods.h
index 0fd53909ff4b..5d4d92cbf215 100644
--- a/contrib/wpa/src/eap_server/eap_methods.h
+++ b/contrib/wpa/src/eap_server/eap_methods.h
@@ -1,6 +1,6 @@
 /*
- * hostapd / EAP method registration
- * Copyright (c) 2004-2006, Jouni Malinen 
+ * EAP server method registration
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -12,8 +12,10 @@
  * See README and COPYING for more details.
  */
 
-#ifndef EAP_METHODS_H
-#define EAP_METHODS_H
+#ifndef EAP_SERVER_METHODS_H
+#define EAP_SERVER_METHODS_H
+
+#include "eap_common/eap_defs.h"
 
 const struct eap_method * eap_server_get_eap_method(int vendor,
 						    EapType method);
@@ -23,7 +25,29 @@ void eap_server_method_free(struct eap_method *method);
 int eap_server_method_register(struct eap_method *method);
 
 EapType eap_server_get_type(const char *name, int *vendor);
-int eap_server_register_methods(void);
 void eap_server_unregister_methods(void);
+const char * eap_server_get_name(int vendor, EapType type);
 
-#endif /* EAP_METHODS_H */
+/* EAP server method registration calls for statically linked in methods */
+int eap_server_identity_register(void);
+int eap_server_md5_register(void);
+int eap_server_tls_register(void);
+int eap_server_mschapv2_register(void);
+int eap_server_peap_register(void);
+int eap_server_tlv_register(void);
+int eap_server_gtc_register(void);
+int eap_server_ttls_register(void);
+int eap_server_sim_register(void);
+int eap_server_aka_register(void);
+int eap_server_aka_prime_register(void);
+int eap_server_pax_register(void);
+int eap_server_psk_register(void);
+int eap_server_sake_register(void);
+int eap_server_gpsk_register(void);
+int eap_server_vendor_test_register(void);
+int eap_server_fast_register(void);
+int eap_server_wsc_register(void);
+int eap_server_ikev2_register(void);
+int eap_server_tnc_register(void);
+
+#endif /* EAP_SERVER_METHODS_H */
diff --git a/contrib/wpa/src/eap_server/eap.c b/contrib/wpa/src/eap_server/eap_server.c
similarity index 98%
rename from contrib/wpa/src/eap_server/eap.c
rename to contrib/wpa/src/eap_server/eap_server.c
index 897adc3b1a2a..fdc26f9343fb 100644
--- a/contrib/wpa/src/eap_server/eap.c
+++ b/contrib/wpa/src/eap_server/eap_server.c
@@ -23,6 +23,7 @@
 #include "common.h"
 #include "eap_i.h"
 #include "state_machine.h"
+#include "common/wpa_ctrl.h"
 
 #define STATE_MACHINE_DATA struct eap_sm
 #define STATE_MACHINE_DEBUG_PREFIX "EAP"
@@ -167,6 +168,9 @@ SM_STATE(EAP, INITIALIZE)
 	}
 	sm->num_rounds = 0;
 	sm->method_pending = METHOD_PENDING_NONE;
+
+	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
+		MACSTR, MAC2STR(sm->peer_addr));
 }
 
 
@@ -196,6 +200,9 @@ SM_STATE(EAP, PICK_UP_METHOD)
 			sm->currentMethod = EAP_TYPE_NONE;
 		}
 	}
+
+	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
+		"method=%u", sm->currentMethod);
 }
 
 
@@ -350,6 +357,9 @@ SM_STATE(EAP, PROPOSE_METHOD)
 		sm->methodState = METHOD_CONTINUE;
 	else
 		sm->methodState = METHOD_PROPOSED;
+
+	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD
+		"vendor=%u method=%u", vendor, sm->currentMethod);
 }
 
 
@@ -410,6 +420,9 @@ SM_STATE(EAP, FAILURE)
 	wpabuf_free(sm->lastReqData);
 	sm->lastReqData = NULL;
 	sm->eap_if.eapFail = TRUE;
+
+	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
+		MACSTR, MAC2STR(sm->peer_addr));
 }
 
 
@@ -424,6 +437,9 @@ SM_STATE(EAP, SUCCESS)
 	if (sm->eap_if.eapKeyData)
 		sm->eap_if.eapKeyAvailable = TRUE;
 	sm->eap_if.eapSuccess = TRUE;
+
+	wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
+		MACSTR, MAC2STR(sm->peer_addr));
 }
 
 
@@ -1210,6 +1226,7 @@ struct eap_sm * eap_server_sm_init(void *eapol_ctx,
 	sm->eapol_cb = eapol_cb;
 	sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */
 	sm->ssl_ctx = conf->ssl_ctx;
+	sm->msg_ctx = conf->msg_ctx;
 	sm->eap_sim_db_priv = conf->eap_sim_db_priv;
 	sm->backend_auth = conf->backend_auth;
 	sm->eap_server = conf->eap_server;
@@ -1238,6 +1255,8 @@ struct eap_sm * eap_server_sm_init(void *eapol_ctx,
 	sm->wps = conf->wps;
 	if (conf->assoc_wps_ie)
 		sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie);
+	if (conf->peer_addr)
+		os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN);
 
 	wpa_printf(MSG_DEBUG, "EAP: Server state machine created");
 
diff --git a/contrib/wpa/src/eap_server/eap_aka.c b/contrib/wpa/src/eap_server/eap_server_aka.c
similarity index 98%
rename from contrib/wpa/src/eap_server/eap_aka.c
rename to contrib/wpa/src/eap_server/eap_server_aka.c
index aad52fd649a5..4e7db48d0793 100644
--- a/contrib/wpa/src/eap_server/eap_aka.c
+++ b/contrib/wpa/src/eap_server/eap_server_aka.c
@@ -15,12 +15,11 @@
 #include "includes.h"
 
 #include "common.h"
-#include "eap_server/eap_i.h"
+#include "crypto/sha256.h"
+#include "crypto/crypto.h"
 #include "eap_common/eap_sim_common.h"
+#include "eap_server/eap_i.h"
 #include "eap_server/eap_sim_db.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "crypto.h"
 
 
 struct eap_aka_data {
@@ -116,7 +115,7 @@ static void * eap_aka_init(struct eap_sm *sm)
 }
 
 
-#ifdef EAP_AKA_PRIME
+#ifdef EAP_SERVER_AKA_PRIME
 static void * eap_aka_prime_init(struct eap_sm *sm)
 {
 	struct eap_aka_data *data;
@@ -148,7 +147,7 @@ static void * eap_aka_prime_init(struct eap_sm *sm)
 
 	return data;
 }
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_SERVER_AKA_PRIME */
 
 
 static void eap_aka_reset(struct eap_sm *sm, void *priv)
@@ -399,7 +398,7 @@ static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
 		eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
 	}
 
-#ifdef EAP_AKA_PRIME
+#ifdef EAP_SERVER_AKA_PRIME
 	if (data->eap_method == EAP_TYPE_AKA) {
 		u16 flags = 0;
 		int i;
@@ -426,7 +425,7 @@ static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
 			flags |= EAP_AKA_BIDDING_FLAG_D;
 		eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0);
 	}
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_SERVER_AKA_PRIME */
 
 	wpa_printf(MSG_DEBUG, "   AT_MAC");
 	eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
@@ -701,7 +700,7 @@ static void eap_aka_determine_identity(struct eap_sm *sm,
 		return;
 	}
 
-#ifdef EAP_AKA_PRIME
+#ifdef EAP_SERVER_AKA_PRIME
 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
 		/* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
 		 * needed 6-octet SQN ^AK for CK',IK' derivation */
@@ -710,7 +709,7 @@ static void eap_aka_determine_identity(struct eap_sm *sm,
 						 data->network_name,
 						 data->network_name_len);
 	}
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_SERVER_AKA_PRIME */
 
 	data->reauth = NULL;
 	data->counter = 0; /* reset re-auth counter since this is full auth */
@@ -807,7 +806,7 @@ static void eap_aka_process_challenge(struct eap_sm *sm,
 
 	wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
 
-#ifdef EAP_AKA_PRIME
+#ifdef EAP_SERVER_AKA_PRIME
 #if 0
 	/* KDF negotiation; to be enabled only after more than one KDF is
 	 * supported */
@@ -830,7 +829,7 @@ static void eap_aka_process_challenge(struct eap_sm *sm,
 		return;
 	}
 #endif
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_SERVER_AKA_PRIME */
 
 	if (attr->checkcode &&
 	    eap_aka_verify_checkcode(data, attr->checkcode,
@@ -892,7 +891,7 @@ static void eap_aka_process_challenge(struct eap_sm *sm,
 	}
 	if (data->next_reauth_id) {
 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
-#ifdef EAP_AKA_PRIME
+#ifdef EAP_SERVER_AKA_PRIME
 			eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
 						    identity,
 						    identity_len,
@@ -900,7 +899,7 @@ static void eap_aka_process_challenge(struct eap_sm *sm,
 						    data->counter + 1,
 						    data->k_encr, data->k_aut,
 						    data->k_re);
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_SERVER_AKA_PRIME */
 		} else {
 			eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
 					      identity_len,
@@ -1031,7 +1030,7 @@ static void eap_aka_process_reauth(struct eap_sm *sm,
 	}
 	if (data->next_reauth_id) {
 		if (data->eap_method == EAP_TYPE_AKA_PRIME) {
-#ifdef EAP_AKA_PRIME
+#ifdef EAP_SERVER_AKA_PRIME
 			eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
 						    identity,
 						    identity_len,
@@ -1039,7 +1038,7 @@ static void eap_aka_process_reauth(struct eap_sm *sm,
 						    data->counter + 1,
 						    data->k_encr, data->k_aut,
 						    data->k_re);
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_SERVER_AKA_PRIME */
 		} else {
 			eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
 					      identity_len,
@@ -1247,7 +1246,7 @@ int eap_server_aka_register(void)
 }
 
 
-#ifdef EAP_AKA_PRIME
+#ifdef EAP_SERVER_AKA_PRIME
 int eap_server_aka_prime_register(void)
 {
 	struct eap_method *eap;
@@ -1275,4 +1274,4 @@ int eap_server_aka_prime_register(void)
 
 	return ret;
 }
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_SERVER_AKA_PRIME */
diff --git a/contrib/wpa/src/eap_server/eap_fast.c b/contrib/wpa/src/eap_server/eap_server_fast.c
similarity index 95%
rename from contrib/wpa/src/eap_server/eap_fast.c
rename to contrib/wpa/src/eap_server/eap_server_fast.c
index c06f396ffd67..39beb33056fb 100644
--- a/contrib/wpa/src/eap_server/eap_fast.c
+++ b/contrib/wpa/src/eap_server/eap_server_fast.c
@@ -15,13 +15,13 @@
 #include "includes.h"
 
 #include "common.h"
-#include "aes_wrap.h"
-#include "sha1.h"
-#include "eap_i.h"
-#include "eap_tls_common.h"
-#include "tls.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "eap_common/eap_tlv_common.h"
 #include "eap_common/eap_fast_common.h"
+#include "eap_i.h"
+#include "eap_tls_common.h"
 
 
 static void eap_fast_reset(struct eap_sm *sm, void *priv);
@@ -791,6 +791,11 @@ static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm,
 	
 	/* Note: headers may be misaligned after A-ID */
 
+	if (sm->identity) {
+		eap_fast_put_tlv(buf, PAC_TYPE_I_ID, sm->identity,
+				 sm->identity_len);
+	}
+
 	/* A-ID-Info (inside PAC-Info) */
 	eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id_info,
 			 srv_id_info_len);
@@ -816,29 +821,28 @@ static int eap_fast_encrypt_phase2(struct eap_sm *sm,
 
 	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 TLVs",
 			    plain);
-	encr = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_mhead(plain),
-				      wpabuf_len(plain));
+	encr = eap_server_tls_encrypt(sm, &data->ssl, plain);
 	wpabuf_free(plain);
 
-	if (data->ssl.out_buf && piggyback) {
+	if (data->ssl.tls_out && piggyback) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Piggyback Phase 2 data "
 			   "(len=%d) with last Phase 1 Message (len=%d "
 			   "used=%d)",
 			   (int) wpabuf_len(encr),
-			   (int) wpabuf_len(data->ssl.out_buf),
-			   (int) data->ssl.out_used);
-		if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(encr)) < 0) {
+			   (int) wpabuf_len(data->ssl.tls_out),
+			   (int) data->ssl.tls_out_pos);
+		if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(encr)) < 0) {
 			wpa_printf(MSG_WARNING, "EAP-FAST: Failed to resize "
 				   "output buffer");
 			wpabuf_free(encr);
 			return -1;
 		}
-		wpabuf_put_buf(data->ssl.out_buf, encr);
+		wpabuf_put_buf(data->ssl.tls_out, encr);
 		wpabuf_free(encr);
 	} else {
-		wpabuf_free(data->ssl.out_buf);
-		data->ssl.out_used = 0;
-		data->ssl.out_buf = encr;
+		wpabuf_free(data->ssl.tls_out);
+		data->ssl.tls_out_pos = 0;
+		data->ssl.tls_out = encr;
 	}
 
 	return 0;
@@ -987,7 +991,7 @@ static void eap_fast_process_phase2_response(struct eap_sm *sm,
 		left = in_len - sizeof(*hdr);
 		wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 type Nak'ed; "
 			    "allowed types", pos + 1, left - 1);
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
 		if (m && m->vendor == EAP_VENDOR_IETF &&
 		    m->method == EAP_TYPE_TNC) {
 			wpa_printf(MSG_DEBUG, "EAP-FAST: Peer Nak'ed required "
@@ -996,7 +1000,7 @@ static void eap_fast_process_phase2_response(struct eap_sm *sm,
 			eap_fast_phase2_init(sm, data, next_type);
 			return;
 		}
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 		eap_sm_process_nak(sm, pos + 1, left - 1);
 		if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
 		    sm->user->methods[sm->user_eap_method_index].method !=
@@ -1064,13 +1068,13 @@ static void eap_fast_process_phase2_response(struct eap_sm *sm,
 		eap_fast_state(data, CRYPTO_BINDING);
 		data->eap_seq++;
 		next_type = EAP_TYPE_NONE;
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
 		if (sm->tnc && !data->tnc_started) {
 			wpa_printf(MSG_DEBUG, "EAP-FAST: Initialize TNC");
 			next_type = EAP_TYPE_TNC;
 			data->tnc_started = 1;
 		}
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 		break;
 	case FAILURE:
 		break;
@@ -1121,7 +1125,7 @@ static void eap_fast_process_phase2_eap(struct eap_sm *sm,
 }
 
 
-static int eap_fast_parse_tlvs(u8 *data, size_t data_len,
+static int eap_fast_parse_tlvs(struct wpabuf *data,
 			       struct eap_fast_tlv_parse *tlv)
 {
 	int mandatory, tlv_type, len, res;
@@ -1129,8 +1133,8 @@ static int eap_fast_parse_tlvs(u8 *data, size_t data_len,
 
 	os_memset(tlv, 0, sizeof(*tlv));
 
-	pos = data;
-	end = data + data_len;
+	pos = wpabuf_mhead(data);
+	end = pos + wpabuf_len(data);
 	while (pos + 4 < end) {
 		mandatory = pos[0] & 0x80;
 		tlv_type = WPA_GET_BE16(pos) & 0x3fff;
@@ -1241,12 +1245,12 @@ static int eap_fast_pac_type(u8 *pac, size_t len, u16 type)
 
 static void eap_fast_process_phase2_tlvs(struct eap_sm *sm,
 					 struct eap_fast_data *data,
-					 u8 *in_data, size_t in_len)
+					 struct wpabuf *in_data)
 {
 	struct eap_fast_tlv_parse tlv;
 	int check_crypto_binding = data->state == CRYPTO_BINDING;
 
-	if (eap_fast_parse_tlvs(in_data, in_len, &tlv) < 0) {
+	if (eap_fast_parse_tlvs(in_data, &tlv) < 0) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to parse received "
 			   "Phase 2 TLVs");
 		return;
@@ -1373,70 +1377,44 @@ static void eap_fast_process_phase2(struct eap_sm *sm,
 				    struct eap_fast_data *data,
 				    struct wpabuf *in_buf)
 {
-	u8 *in_decrypted;
-	int len_decrypted;
-	size_t buf_len;
-	u8 *in_data;
-	size_t in_len;
-
-	in_data = wpabuf_mhead(in_buf);
-	in_len = wpabuf_len(in_buf);
+	struct wpabuf *in_decrypted;
 
 	wpa_printf(MSG_DEBUG, "EAP-FAST: Received %lu bytes encrypted data for"
-		   " Phase 2", (unsigned long) in_len);
+		   " Phase 2", (unsigned long) wpabuf_len(in_buf));
 
 	if (data->pending_phase2_resp) {
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
 			   "skip decryption and use old data");
-		eap_fast_process_phase2_tlvs(
-			sm, data, wpabuf_mhead(data->pending_phase2_resp),
-			wpabuf_len(data->pending_phase2_resp));
+		eap_fast_process_phase2_tlvs(sm, data,
+					     data->pending_phase2_resp);
 		wpabuf_free(data->pending_phase2_resp);
 		data->pending_phase2_resp = NULL;
 		return;
 	}
 
-	buf_len = in_len;
-	/*
-	 * Even though we try to disable TLS compression, it is possible that
-	 * this cannot be done with all TLS libraries. Add extra buffer space
-	 * to handle the possibility of the decrypted data being longer than
-	 * input data.
-	 */
-	buf_len += 500;
-	buf_len *= 3;
-	in_decrypted = os_malloc(buf_len);
+	in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+					      in_buf);
 	if (in_decrypted == NULL) {
-		wpa_printf(MSG_WARNING, "EAP-FAST: Failed to allocate memory "
-			   "for decryption");
-		return;
-	}
-
-	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
-					       in_data, in_len,
-					       in_decrypted, buf_len);
-	if (len_decrypted < 0) {
 		wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 "
 			   "data");
-		os_free(in_decrypted);
 		eap_fast_state(data, FAILURE);
 		return;
 	}
 
-	wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs",
-			in_decrypted, len_decrypted);
+	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs",
+			    in_decrypted);
 
-	eap_fast_process_phase2_tlvs(sm, data, in_decrypted, len_decrypted);
+	eap_fast_process_phase2_tlvs(sm, data, in_decrypted);
 
 	if (sm->method_pending == METHOD_PENDING_WAIT) {
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method is in "
 			   "pending wait state - save decrypted response");
 		wpabuf_free(data->pending_phase2_resp);
-		data->pending_phase2_resp = wpabuf_alloc_copy(in_decrypted,
-							      len_decrypted);
+		data->pending_phase2_resp = in_decrypted;
+		return;
 	}
 
-	os_free(in_decrypted);
+	wpabuf_free(in_decrypted);
 }
 
 
@@ -1475,7 +1453,7 @@ static int eap_fast_process_phase1(struct eap_sm *sm,
 	}
 
 	if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
-	    wpabuf_len(data->ssl.out_buf) > 0)
+	    wpabuf_len(data->ssl.tls_out) > 0)
 		return 1;
 
 	/*
@@ -1541,7 +1519,7 @@ static void eap_fast_process_msg(struct eap_sm *sm, void *priv,
 	case PHASE2_METHOD:
 	case CRYPTO_BINDING:
 	case REQUEST_PAC:
-		eap_fast_process_phase2(sm, data, data->ssl.in_buf);
+		eap_fast_process_phase2(sm, data, data->ssl.tls_in);
 		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected state %d in %s",
diff --git a/contrib/wpa/src/eap_server/eap_gpsk.c b/contrib/wpa/src/eap_server/eap_server_gpsk.c
similarity index 100%
rename from contrib/wpa/src/eap_server/eap_gpsk.c
rename to contrib/wpa/src/eap_server/eap_server_gpsk.c
diff --git a/contrib/wpa/src/eap_server/eap_gtc.c b/contrib/wpa/src/eap_server/eap_server_gtc.c
similarity index 98%
rename from contrib/wpa/src/eap_server/eap_gtc.c
rename to contrib/wpa/src/eap_server/eap_server_gtc.c
index 97e328b83fa6..79b9696b2c95 100644
--- a/contrib/wpa/src/eap_server/eap_gtc.c
+++ b/contrib/wpa/src/eap_server/eap_server_gtc.c
@@ -33,14 +33,14 @@ static void * eap_gtc_init(struct eap_sm *sm)
 		return NULL;
 	data->state = CONTINUE;
 
-#ifdef EAP_FAST
+#ifdef EAP_SERVER_FAST
 	if (sm->m && sm->m->vendor == EAP_VENDOR_IETF &&
 	    sm->m->method == EAP_TYPE_FAST) {
 		wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
 			   "with challenge/response");
 		data->prefix = 1;
 	}
-#endif /* EAP_FAST */
+#endif /* EAP_SERVER_FAST */
 
 	return data;
 }
@@ -109,7 +109,7 @@ static void eap_gtc_process(struct eap_sm *sm, void *priv,
 
 	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", pos, rlen);
 
-#ifdef EAP_FAST
+#ifdef EAP_SERVER_FAST
 	if (data->prefix) {
 		const u8 *pos2, *end;
 		/* "RESPONSE=\0" */
@@ -170,7 +170,7 @@ static void eap_gtc_process(struct eap_sm *sm, void *priv,
 				      "EAP-GTC: Response password",
 				      pos, rlen);
 	}
-#endif /* EAP_FAST */
+#endif /* EAP_SERVER_FAST */
 
 	if (sm->user == NULL || sm->user->password == NULL ||
 	    sm->user->password_hash) {
diff --git a/contrib/wpa/src/eap_server/eap_identity.c b/contrib/wpa/src/eap_server/eap_server_identity.c
similarity index 100%
rename from contrib/wpa/src/eap_server/eap_identity.c
rename to contrib/wpa/src/eap_server/eap_server_identity.c
diff --git a/contrib/wpa/src/eap_server/eap_ikev2.c b/contrib/wpa/src/eap_server/eap_server_ikev2.c
similarity index 100%
rename from contrib/wpa/src/eap_server/eap_ikev2.c
rename to contrib/wpa/src/eap_server/eap_server_ikev2.c
diff --git a/contrib/wpa/src/eap_server/eap_md5.c b/contrib/wpa/src/eap_server/eap_server_md5.c
similarity index 100%
rename from contrib/wpa/src/eap_server/eap_md5.c
rename to contrib/wpa/src/eap_server/eap_server_md5.c
diff --git a/contrib/wpa/src/eap_server/eap_methods.c b/contrib/wpa/src/eap_server/eap_server_methods.c
similarity index 55%
rename from contrib/wpa/src/eap_server/eap_methods.c
rename to contrib/wpa/src/eap_server/eap_server_methods.c
index 4092d675b34f..900a5dd31810 100644
--- a/contrib/wpa/src/eap_server/eap_methods.c
+++ b/contrib/wpa/src/eap_server/eap_server_methods.c
@@ -1,6 +1,6 @@
 /*
- * hostapd / EAP method registration
- * Copyright (c) 2004-2006, Jouni Malinen 
+ * EAP server method registration
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -133,159 +133,6 @@ int eap_server_method_register(struct eap_method *method)
 }
 
 
-/**
- * eap_server_register_methods - Register statically linked EAP server methods
- * Returns: 0 on success, -1 on failure
- *
- * This function is called at program initialization to register all EAP server
- * methods that were linked in statically.
- */
-int eap_server_register_methods(void)
-{
-	int ret = 0;
-
-	if (ret == 0) {
-		int eap_server_identity_register(void);
-		ret = eap_server_identity_register();
-	}
-
-#ifdef EAP_MD5
-	if (ret == 0) {
-		int eap_server_md5_register(void);
-		ret = eap_server_md5_register();
-	}
-#endif /* EAP_MD5 */
-
-#ifdef EAP_TLS
-	if (ret == 0) {
-		int eap_server_tls_register(void);
-		ret = eap_server_tls_register();
-	}
-#endif /* EAP_TLS */
-
-#ifdef EAP_MSCHAPv2
-	if (ret == 0) {
-		int eap_server_mschapv2_register(void);
-		ret = eap_server_mschapv2_register();
-	}
-#endif /* EAP_MSCHAPv2 */
-
-#ifdef EAP_PEAP
-	if (ret == 0) {
-		int eap_server_peap_register(void);
-		ret = eap_server_peap_register();
-	}
-#endif /* EAP_PEAP */
-
-#ifdef EAP_TLV
-	if (ret == 0) {
-		int eap_server_tlv_register(void);
-		ret = eap_server_tlv_register();
-	}
-#endif /* EAP_TLV */
-
-#ifdef EAP_GTC
-	if (ret == 0) {
-		int eap_server_gtc_register(void);
-		ret = eap_server_gtc_register();
-	}
-#endif /* EAP_GTC */
-
-#ifdef EAP_TTLS
-	if (ret == 0) {
-		int eap_server_ttls_register(void);
-		ret = eap_server_ttls_register();
-	}
-#endif /* EAP_TTLS */
-
-#ifdef EAP_SIM
-	if (ret == 0) {
-		int eap_server_sim_register(void);
-		ret = eap_server_sim_register();
-	}
-#endif /* EAP_SIM */
-
-#ifdef EAP_AKA
-	if (ret == 0) {
-		int eap_server_aka_register(void);
-		ret = eap_server_aka_register();
-	}
-#endif /* EAP_AKA */
-
-#ifdef EAP_AKA_PRIME
-	if (ret == 0) {
-		int eap_server_aka_prime_register(void);
-		ret = eap_server_aka_prime_register();
-	}
-#endif /* EAP_AKA_PRIME */
-
-#ifdef EAP_PAX
-	if (ret == 0) {
-		int eap_server_pax_register(void);
-		ret = eap_server_pax_register();
-	}
-#endif /* EAP_PAX */
-
-#ifdef EAP_PSK
-	if (ret == 0) {
-		int eap_server_psk_register(void);
-		ret = eap_server_psk_register();
-	}
-#endif /* EAP_PSK */
-
-#ifdef EAP_SAKE
-	if (ret == 0) {
-		int eap_server_sake_register(void);
-		ret = eap_server_sake_register();
-	}
-#endif /* EAP_SAKE */
-
-#ifdef EAP_GPSK
-	if (ret == 0) {
-		int eap_server_gpsk_register(void);
-		ret = eap_server_gpsk_register();
-	}
-#endif /* EAP_GPSK */
-
-#ifdef EAP_VENDOR_TEST
-	if (ret == 0) {
-		int eap_server_vendor_test_register(void);
-		ret = eap_server_vendor_test_register();
-	}
-#endif /* EAP_VENDOR_TEST */
-
-#ifdef EAP_FAST
-	if (ret == 0) {
-		int eap_server_fast_register(void);
-		ret = eap_server_fast_register();
-	}
-#endif /* EAP_FAST */
-
-#ifdef EAP_WSC
-	if (ret == 0) {
-		int eap_server_wsc_register(void);
-		ret = eap_server_wsc_register();
-	}
-#endif /* EAP_WSC */
-
-#ifdef EAP_IKEV2
-	if (ret == 0) {
-		int eap_server_ikev2_register(void);
-		ret = eap_server_ikev2_register();
-	}
-#endif /* EAP_IKEV2 */
-
-#ifdef EAP_TNC
-	if (ret == 0) {
-		int eap_server_tnc_register(void);
-		ret = eap_server_tnc_register();
-	}
-#endif /* EAP_TNC */
-
-	return ret;
-}
-
-
 /**
  * eap_server_unregister_methods - Unregister EAP server methods
  *
@@ -306,3 +153,23 @@ void eap_server_unregister_methods(void)
 			eap_server_method_free(m);
 	}
 }
+
+
+/**
+ * eap_server_get_name - Get EAP method name for the given EAP type
+ * @vendor: EAP Vendor-Id (0 = IETF)
+ * @type: EAP method type
+ * Returns: EAP method name, e.g., TLS, or %NULL if not found
+ *
+ * This function maps EAP type numbers into EAP type names based on the list of
+ * EAP methods included in the build.
+ */
+const char * eap_server_get_name(int vendor, EapType type)
+{
+	struct eap_method *m;
+	for (m = eap_methods; m; m = m->next) {
+		if (m->vendor == vendor && m->method == type)
+			return m->name;
+	}
+	return NULL;
+}
diff --git a/contrib/wpa/src/eap_server/eap_mschapv2.c b/contrib/wpa/src/eap_server/eap_server_mschapv2.c
similarity index 97%
rename from contrib/wpa/src/eap_server/eap_mschapv2.c
rename to contrib/wpa/src/eap_server/eap_server_mschapv2.c
index 20e7adee6f95..39d1c6ef2b36 100644
--- a/contrib/wpa/src/eap_server/eap_mschapv2.c
+++ b/contrib/wpa/src/eap_server/eap_server_mschapv2.c
@@ -15,8 +15,8 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/ms_funcs.h"
 #include "eap_i.h"
-#include "ms_funcs.h"
 
 
 struct eap_mschapv2_hdr {
@@ -295,6 +295,7 @@ static void eap_mschapv2_process_response(struct eap_sm *sm,
 	u8 expected[24];
 	const u8 *username, *user;
 	size_t username_len, user_len;
+	int res;
 
 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
 			       &len);
@@ -372,17 +373,22 @@ static void eap_mschapv2_process_response(struct eap_sm *sm,
 			  username, username_len);
 
 	if (sm->user->password_hash) {
-		generate_nt_response_pwhash(data->auth_challenge,
-					    peer_challenge,
-					    username, username_len,
-					    sm->user->password,
-					    expected);
+		res = generate_nt_response_pwhash(data->auth_challenge,
+						  peer_challenge,
+						  username, username_len,
+						  sm->user->password,
+						  expected);
 	} else {
-		generate_nt_response(data->auth_challenge, peer_challenge,
-				     username, username_len,
-				     sm->user->password,
-				     sm->user->password_len,
-				     expected);
+		res = generate_nt_response(data->auth_challenge,
+					   peer_challenge,
+					   username, username_len,
+					   sm->user->password,
+					   sm->user->password_len,
+					   expected);
+	}
+	if (res) {
+		data->state = FAILURE;
+		return;
 	}
 
 	if (os_memcmp(nt_response, expected, 24) == 0) {
diff --git a/contrib/wpa/src/eap_server/eap_pax.c b/contrib/wpa/src/eap_server/eap_server_pax.c
similarity index 100%
rename from contrib/wpa/src/eap_server/eap_pax.c
rename to contrib/wpa/src/eap_server/eap_server_pax.c
diff --git a/contrib/wpa/src/eap_server/eap_peap.c b/contrib/wpa/src/eap_server/eap_server_peap.c
similarity index 92%
rename from contrib/wpa/src/eap_server/eap_peap.c
rename to contrib/wpa/src/eap_server/eap_server_peap.c
index 4b2d5a5c83ff..674ecd2231e2 100644
--- a/contrib/wpa/src/eap_server/eap_peap.c
+++ b/contrib/wpa/src/eap_server/eap_server_peap.c
@@ -15,12 +15,12 @@
 #include "includes.h"
 
 #include "common.h"
-#include "sha1.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
 #include "eap_common/eap_tlv_common.h"
 #include "eap_common/eap_peap_common.h"
-#include "tls.h"
 #include "tncs.h"
 
 
@@ -235,7 +235,7 @@ static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
 						 struct eap_peap_data *data,
 						 u8 id)
 {
-	struct wpabuf *buf, *encr_req;
+	struct wpabuf *buf, *encr_req, msgbuf;
 	const u8 *req;
 	size_t req_len;
 
@@ -260,19 +260,20 @@ static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
 		req_len -= sizeof(struct eap_hdr);
 	}
 
-	encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
+	wpabuf_set(&msgbuf, req, req_len);
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
 	wpabuf_free(buf);
 
 	return encr_req;
 }
 
 
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
 static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
 						 struct eap_peap_data *data,
 						 u8 id)
 {
-	struct wpabuf *buf1, *buf, *encr_req;
+	struct wpabuf *buf1, *buf, *encr_req, msgbuf;
 	const u8 *req;
 	size_t req_len;
 
@@ -297,13 +298,14 @@ static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
 
 	req += sizeof(struct eap_hdr);
 	req_len -= sizeof(struct eap_hdr);
+	wpabuf_set(&msgbuf, req, req_len);
 
-	encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
 	wpabuf_free(buf);
 
 	return encr_req;
 }
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 
 
 static void eap_peap_get_isk(struct eap_peap_data *data,
@@ -370,17 +372,17 @@ static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
 						 u8 id)
 {
 	struct wpabuf *buf, *encr_req;
-	size_t len;
+	size_t mlen;
 
-	len = 6; /* Result TLV */
+	mlen = 6; /* Result TLV */
 	if (data->crypto_binding != NO_BINDING)
-		len += 60; /* Cryptobinding TLV */
-#ifdef EAP_TNC
+		mlen += 60; /* Cryptobinding TLV */
+#ifdef EAP_SERVER_TNC
 	if (data->soh_response)
-		len += wpabuf_len(data->soh_response);
-#endif /* EAP_TNC */
+		mlen += wpabuf_len(data->soh_response);
+#endif /* EAP_SERVER_TNC */
 
-	buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len,
+	buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen,
 			    EAP_CODE_REQUEST, id);
 	if (buf == NULL)
 		return NULL;
@@ -401,7 +403,7 @@ static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
 		size_t len[2];
 		u16 tlv_type;
 
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
 		if (data->soh_response) {
 			wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH "
 				   "Response TLV");
@@ -409,7 +411,7 @@ static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
 			wpabuf_free(data->soh_response);
 			data->soh_response = NULL;
 		}
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 
 		if (eap_peap_derive_cmk(sm, data) < 0 ||
 		    os_get_random(data->binding_nonce, 32)) {
@@ -450,8 +452,7 @@ static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
 	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
 			    buf);
 
-	encr_req = eap_server_tls_encrypt(sm, &data->ssl, wpabuf_head(buf),
-					  wpabuf_len(buf));
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
 	wpabuf_free(buf);
 
 	return encr_req;
@@ -462,7 +463,7 @@ static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
 						  struct eap_peap_data *data,
 						  u8 id, int success)
 {
-	struct wpabuf *encr_req;
+	struct wpabuf *encr_req, msgbuf;
 	size_t req_len;
 	struct eap_hdr *hdr;
 
@@ -478,7 +479,8 @@ static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
 			(u8 *) hdr, req_len);
 
-	encr_req = eap_server_tls_encrypt(sm, &data->ssl, (u8 *) hdr, req_len);
+	wpabuf_set(&msgbuf, hdr, req_len);
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
 	os_free(hdr);
 
 	return encr_req;
@@ -513,32 +515,32 @@ static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
 		break;
 	case PHASE2_ID:
 	case PHASE2_METHOD:
-		wpabuf_free(data->ssl.out_buf);
-		data->ssl.out_used = 0;
-		data->ssl.out_buf = eap_peap_build_phase2_req(sm, data, id);
+		wpabuf_free(data->ssl.tls_out);
+		data->ssl.tls_out_pos = 0;
+		data->ssl.tls_out = eap_peap_build_phase2_req(sm, data, id);
 		break;
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
 	case PHASE2_SOH:
-		wpabuf_free(data->ssl.out_buf);
-		data->ssl.out_used = 0;
-		data->ssl.out_buf = eap_peap_build_phase2_soh(sm, data, id);
+		wpabuf_free(data->ssl.tls_out);
+		data->ssl.tls_out_pos = 0;
+		data->ssl.tls_out = eap_peap_build_phase2_soh(sm, data, id);
 		break;
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 	case PHASE2_TLV:
-		wpabuf_free(data->ssl.out_buf);
-		data->ssl.out_used = 0;
-		data->ssl.out_buf = eap_peap_build_phase2_tlv(sm, data, id);
+		wpabuf_free(data->ssl.tls_out);
+		data->ssl.tls_out_pos = 0;
+		data->ssl.tls_out = eap_peap_build_phase2_tlv(sm, data, id);
 		break;
 	case SUCCESS_REQ:
-		wpabuf_free(data->ssl.out_buf);
-		data->ssl.out_used = 0;
-		data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id,
+		wpabuf_free(data->ssl.tls_out);
+		data->ssl.tls_out_pos = 0;
+		data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id,
 							       1);
 		break;
 	case FAILURE_REQ:
-		wpabuf_free(data->ssl.out_buf);
-		data->ssl.out_used = 0;
-		data->ssl.out_buf = eap_peap_build_phase2_term(sm, data, id,
+		wpabuf_free(data->ssl.tls_out);
+		data->ssl.tls_out_pos = 0;
+		data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id,
 							       0);
 		break;
 	default:
@@ -757,7 +759,7 @@ static void eap_peap_process_phase2_tlv(struct eap_sm *sm,
 }
 
 
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
 static void eap_peap_process_phase2_soh(struct eap_sm *sm,
 					struct eap_peap_data *data,
 					struct wpabuf *in_data)
@@ -885,7 +887,7 @@ static void eap_peap_process_phase2_soh(struct eap_sm *sm,
 	wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type);
 	eap_peap_phase2_init(sm, data, next_type);
 }
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 
 
 static void eap_peap_process_phase2_response(struct eap_sm *sm,
@@ -902,12 +904,12 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
 		return;
 	}
 
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
 	if (data->state == PHASE2_SOH) {
 		eap_peap_process_phase2_soh(sm, data, in_data);
 		return;
 	}
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 
 	if (data->phase2_priv == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not "
@@ -991,7 +993,7 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
 			break;
 		}
 
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
 		if (data->state != PHASE2_SOH && sm->tnc &&
 		    data->peap_version == 0) {
 			eap_peap_state(data, PHASE2_SOH);
@@ -1000,7 +1002,7 @@ static void eap_peap_process_phase2_response(struct eap_sm *sm,
 			next_type = EAP_TYPE_NONE;
 			break;
 		}
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 
 		eap_peap_state(data, PHASE2_METHOD);
 		next_type = sm->user->methods[0].method;
@@ -1029,17 +1031,11 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
 				    struct wpabuf *in_buf)
 {
 	struct wpabuf *in_decrypted;
-	int len_decrypted;
 	const struct eap_hdr *hdr;
-	size_t buf_len, len;
-	u8 *in_data;
-	size_t in_len;
-
-	in_data = wpabuf_mhead(in_buf);
-	in_len = wpabuf_len(in_buf);
+	size_t len;
 
 	wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
-		   " Phase 2", (unsigned long) in_len);
+		   " Phase 2", (unsigned long) wpabuf_len(in_buf));
 
 	if (data->pending_phase2_resp) {
 		wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
@@ -1051,34 +1047,14 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
 		return;
 	}
 
-	buf_len = in_len;
-	/*
-	 * Even though we try to disable TLS compression, it is possible that
-	 * this cannot be done with all TLS libraries. Add extra buffer space
-	 * to handle the possibility of the decrypted data being longer than
-	 * input data.
-	 */
-	buf_len += 500;
-	buf_len *= 3;
-	in_decrypted = wpabuf_alloc(buf_len);
+	in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+					      in_buf);
 	if (in_decrypted == NULL) {
-		wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory "
-			   "for decryption");
-		return;
-	}
-
-	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
-					       in_data, in_len,
-					       wpabuf_mhead(in_decrypted),
-					       buf_len);
-	if (len_decrypted < 0) {
 		wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
 			   "data");
-		wpabuf_free(in_decrypted);
 		eap_peap_state(data, FAILURE);
 		return;
 	}
-	wpabuf_put(in_decrypted, len_decrypted);
 
 	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
 			    in_decrypted);
@@ -1191,7 +1167,7 @@ static void eap_peap_process_phase2(struct eap_sm *sm,
 		break;
 	}
 
-	os_free(in_decrypted);
+	wpabuf_free(in_decrypted);
 }
 
 
@@ -1199,7 +1175,6 @@ static int eap_peapv2_start_phase2(struct eap_sm *sm,
 				   struct eap_peap_data *data)
 {
 	struct wpabuf *buf, *buf2;
-	int res;
 
 	wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
 		   "payload in the same message");
@@ -1218,35 +1193,25 @@ static int eap_peapv2_start_phase2(struct eap_sm *sm,
 
 	wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
 
-	buf = wpabuf_alloc(data->ssl.tls_out_limit);
-	if (buf == NULL) {
-		wpabuf_free(buf2);
-		return -1;
-	}
-
-	res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
-				     wpabuf_head(buf2), wpabuf_len(buf2),
-				     wpabuf_put(buf, 0),
-				     data->ssl.tls_out_limit);
+	buf = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
+				     buf2);
 	wpabuf_free(buf2);
 
-	if (res < 0) {
+	if (buf == NULL) {
 		wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
 			   "data");
-		wpabuf_free(buf);
 		return -1;
 	}
 
-	wpabuf_put(buf, res);
 	wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
 			buf);
 
 	/* Append TLS data into the pending buffer after the Server Finished */
-	if (wpabuf_resize(&data->ssl.out_buf, wpabuf_len(buf)) < 0) {
+	if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(buf)) < 0) {
 		wpabuf_free(buf);
 		return -1;
 	}
-	wpabuf_put_buf(data->ssl.out_buf, buf);
+	wpabuf_put_buf(data->ssl.tls_out, buf);
 	wpabuf_free(buf);
 
 	return 0;
@@ -1305,7 +1270,7 @@ static void eap_peap_process_msg(struct eap_sm *sm, void *priv,
 	case PHASE2_METHOD:
 	case PHASE2_SOH:
 	case PHASE2_TLV:
-		eap_peap_process_phase2(sm, data, respData, data->ssl.in_buf);
+		eap_peap_process_phase2(sm, data, respData, data->ssl.tls_in);
 		break;
 	case SUCCESS_REQ:
 		eap_peap_state(data, SUCCESS);
diff --git a/contrib/wpa/src/eap_server/eap_psk.c b/contrib/wpa/src/eap_server/eap_server_psk.c
similarity index 99%
rename from contrib/wpa/src/eap_server/eap_psk.c
rename to contrib/wpa/src/eap_server/eap_server_psk.c
index c68d4c34d451..4c30346e59ce 100644
--- a/contrib/wpa/src/eap_server/eap_psk.c
+++ b/contrib/wpa/src/eap_server/eap_server_psk.c
@@ -18,9 +18,9 @@
 #include "includes.h"
 
 #include "common.h"
-#include "eap_server/eap_i.h"
-#include "aes_wrap.h"
+#include "crypto/aes_wrap.h"
 #include "eap_common/eap_psk_common.h"
+#include "eap_server/eap_i.h"
 
 
 struct eap_psk_data {
diff --git a/contrib/wpa/src/eap_server/eap_sake.c b/contrib/wpa/src/eap_server/eap_server_sake.c
similarity index 100%
rename from contrib/wpa/src/eap_server/eap_sake.c
rename to contrib/wpa/src/eap_server/eap_server_sake.c
diff --git a/contrib/wpa/src/eap_server/eap_sim.c b/contrib/wpa/src/eap_server/eap_server_sim.c
similarity index 100%
rename from contrib/wpa/src/eap_server/eap_sim.c
rename to contrib/wpa/src/eap_server/eap_server_sim.c
diff --git a/contrib/wpa/src/eap_server/eap_tls.c b/contrib/wpa/src/eap_server/eap_server_tls.c
similarity index 98%
rename from contrib/wpa/src/eap_server/eap_tls.c
rename to contrib/wpa/src/eap_server/eap_server_tls.c
index 5747940f7806..c98fa185bb5d 100644
--- a/contrib/wpa/src/eap_server/eap_tls.c
+++ b/contrib/wpa/src/eap_server/eap_server_tls.c
@@ -17,7 +17,7 @@
 #include "common.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
-#include "tls.h"
+#include "crypto/tls.h"
 
 
 static void eap_tls_reset(struct eap_sm *sm, void *priv);
@@ -169,7 +169,7 @@ static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
 				const struct wpabuf *respData)
 {
 	struct eap_tls_data *data = priv;
-	if (data->state == SUCCESS && wpabuf_len(data->ssl.in_buf) == 0) {
+	if (data->state == SUCCESS && wpabuf_len(data->ssl.tls_in) == 0) {
 		wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS "
 			   "handshake message");
 		return;
diff --git a/contrib/wpa/src/eap_server/eap_tls_common.c b/contrib/wpa/src/eap_server/eap_server_tls_common.c
similarity index 79%
rename from contrib/wpa/src/eap_server/eap_tls_common.c
rename to contrib/wpa/src/eap_server/eap_server_tls_common.c
index bda1184c02bd..25ae683f0668 100644
--- a/contrib/wpa/src/eap_server/eap_tls_common.c
+++ b/contrib/wpa/src/eap_server/eap_server_tls_common.c
@@ -1,6 +1,6 @@
 /*
- * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2008, Jouni Malinen 
+ * EAP-TLS/PEAP/TTLS/FAST server common functions
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -15,10 +15,13 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "eap_i.h"
 #include "eap_tls_common.h"
-#include "sha1.h"
-#include "tls.h"
+
+
+static void eap_server_tls_free_in_buf(struct eap_ssl_data *data);
 
 
 int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
@@ -58,8 +61,9 @@ int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
 {
 	tls_connection_deinit(sm->ssl_ctx, data->conn);
-	os_free(data->in_buf);
-	os_free(data->out_buf);
+	eap_server_tls_free_in_buf(data);
+	wpabuf_free(data->tls_out);
+	data->tls_out = NULL;
 }
 
 
@@ -114,17 +118,17 @@ struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
 	size_t send_len, plen;
 
 	wpa_printf(MSG_DEBUG, "SSL: Generating Request");
-	if (data->out_buf == NULL) {
-		wpa_printf(MSG_ERROR, "SSL: out_buf NULL in %s", __func__);
+	if (data->tls_out == NULL) {
+		wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__);
 		return NULL;
 	}
 
 	flags = version;
-	send_len = wpabuf_len(data->out_buf) - data->out_used;
+	send_len = wpabuf_len(data->tls_out) - data->tls_out_pos;
 	if (1 + send_len > data->tls_out_limit) {
 		send_len = data->tls_out_limit - 1;
 		flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
-		if (data->out_used == 0) {
+		if (data->tls_out_pos == 0) {
 			flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
 			send_len -= 4;
 		}
@@ -141,25 +145,25 @@ struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data,
 
 	wpabuf_put_u8(req, flags); /* Flags */
 	if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)
-		wpabuf_put_be32(req, wpabuf_len(data->out_buf));
+		wpabuf_put_be32(req, wpabuf_len(data->tls_out));
 
-	wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used,
+	wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos,
 			send_len);
-	data->out_used += send_len;
+	data->tls_out_pos += send_len;
 
-	if (data->out_used == wpabuf_len(data->out_buf)) {
+	if (data->tls_out_pos == wpabuf_len(data->tls_out)) {
 		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
 			   "(message sent completely)",
 			   (unsigned long) send_len);
-		wpabuf_free(data->out_buf);
-		data->out_buf = NULL;
-		data->out_used = 0;
+		wpabuf_free(data->tls_out);
+		data->tls_out = NULL;
+		data->tls_out_pos = 0;
 		data->state = MSG;
 	} else {
 		wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes "
 			   "(%lu more to send)", (unsigned long) send_len,
-			   (unsigned long) wpabuf_len(data->out_buf) -
-			   data->out_used);
+			   (unsigned long) wpabuf_len(data->tls_out) -
+			   data->tls_out_pos);
 		data->state = WAIT_FRAG_ACK;
 	}
 
@@ -185,15 +189,15 @@ static int eap_server_tls_process_cont(struct eap_ssl_data *data,
 				       const u8 *buf, size_t len)
 {
 	/* Process continuation of a pending message */
-	if (len > wpabuf_tailroom(data->in_buf)) {
+	if (len > wpabuf_tailroom(data->tls_in)) {
 		wpa_printf(MSG_DEBUG, "SSL: Fragment overflow");
 		return -1;
 	}
 
-	wpabuf_put_data(data->in_buf, buf, len);
+	wpabuf_put_data(data->tls_in, buf, len);
 	wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu "
 		   "bytes more", (unsigned long) len,
-		   (unsigned long) wpabuf_tailroom(data->in_buf));
+		   (unsigned long) wpabuf_tailroom(data->tls_in));
 
 	return 0;
 }
@@ -204,13 +208,13 @@ static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
 					   const u8 *buf, size_t len)
 {
 	/* Process a fragment that is not the last one of the message */
-	if (data->in_buf == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
+	if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) {
 		wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a "
 			   "fragmented packet");
 		return -1;
 	}
 
-	if (data->in_buf == NULL) {
+	if (data->tls_in == NULL) {
 		/* First fragment of the message */
 
 		/* Limit length to avoid rogue peers from causing large
@@ -221,16 +225,16 @@ static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
 			return -1;
 		}
 
-		data->in_buf = wpabuf_alloc(message_length);
-		if (data->in_buf == NULL) {
+		data->tls_in = wpabuf_alloc(message_length);
+		if (data->tls_in == NULL) {
 			wpa_printf(MSG_DEBUG, "SSL: No memory for message");
 			return -1;
 		}
-		wpabuf_put_data(data->in_buf, buf, len);
+		wpabuf_put_data(data->tls_in, buf, len);
 		wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first "
 			   "fragment, waiting for %lu bytes more",
 			   (unsigned long) len,
-			   (unsigned long) wpabuf_tailroom(data->in_buf));
+			   (unsigned long) wpabuf_tailroom(data->tls_in));
 	}
 
 	return 0;
@@ -239,30 +243,28 @@ static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
 
 int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
 {
-	u8 *next;
-	size_t next_len;
-
-	next = tls_connection_server_handshake(
-		sm->ssl_ctx, data->conn,
-		wpabuf_mhead(data->in_buf),
-		wpabuf_len(data->in_buf),
-		&next_len);
-	if (next == NULL) {
-		wpa_printf(MSG_INFO, "SSL: TLS processing failed");
-		return -1;
-	}
-	if (data->out_buf) {
+	if (data->tls_out) {
 		/* This should not happen.. */
 		wpa_printf(MSG_INFO, "SSL: pending tls_out data when "
 			   "processing new message");
-		os_free(data->out_buf);
-		WPA_ASSERT(data->out_buf == NULL);
+		wpabuf_free(data->tls_out);
+		WPA_ASSERT(data->tls_out == NULL);
 	}
-	data->out_buf = wpabuf_alloc_ext_data(next, next_len);
-	if (data->out_buf == NULL) {
-		os_free(next);
+
+	data->tls_out = tls_connection_server_handshake(sm->ssl_ctx,
+							data->conn,
+							data->tls_in, NULL);
+	if (data->tls_out == NULL) {
+		wpa_printf(MSG_INFO, "SSL: TLS processing failed");
 		return -1;
 	}
+	if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
+		/* TLS processing has failed - return error */
+		wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
+			   "report error");
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -299,7 +301,7 @@ static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
 		return 1;
 	}
 
-	if (data->in_buf &&
+	if (data->tls_in &&
 	    eap_server_tls_process_cont(data, *pos, end - *pos) < 0)
 		return -1;
 		
@@ -317,10 +319,10 @@ static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
 		data->state = MSG;
 	}
 
-	if (data->in_buf == NULL) {
+	if (data->tls_in == NULL) {
 		/* Wrap unfragmented messages as wpabuf without extra copy */
 		wpabuf_set(&data->tmpbuf, *pos, end - *pos);
-		data->in_buf = &data->tmpbuf;
+		data->tls_in = &data->tmpbuf;
 	}
 
 	return 0;
@@ -329,36 +331,25 @@ static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags,
 
 static void eap_server_tls_free_in_buf(struct eap_ssl_data *data)
 {
-	if (data->in_buf != &data->tmpbuf)
-		wpabuf_free(data->in_buf);
-	data->in_buf = NULL;
+	if (data->tls_in != &data->tmpbuf)
+		wpabuf_free(data->tls_in);
+	data->tls_in = NULL;
 }
 
 
 struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
 				       struct eap_ssl_data *data,
-				       const u8 *plain, size_t plain_len)
+				       const struct wpabuf *plain)
 {
-	int res;
 	struct wpabuf *buf;
-	size_t buf_len;
 
-	/* reserve some extra room for encryption overhead */
-	buf_len = plain_len + 300;
-	buf = wpabuf_alloc(buf_len);
-	if (buf == NULL)
-		return NULL;
-	res = tls_connection_encrypt(sm->ssl_ctx, data->conn,
-				     plain, plain_len, wpabuf_put(buf, 0),
-				     buf_len);
-	if (res < 0) {
+	buf = tls_connection_encrypt(sm->ssl_ctx, data->conn,
+				     plain);
+	if (buf == NULL) {
 		wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data");
-		wpabuf_free(buf);
 		return NULL;
 	}
 
-	wpabuf_put(buf, res);
-
 	return buf;
 }
 
diff --git a/contrib/wpa/src/eap_server/eap_tnc.c b/contrib/wpa/src/eap_server/eap_server_tnc.c
similarity index 85%
rename from contrib/wpa/src/eap_server/eap_tnc.c
rename to contrib/wpa/src/eap_server/eap_server_tnc.c
index 4cb3ecfb0565..f3b70edabfcd 100644
--- a/contrib/wpa/src/eap_server/eap_tnc.c
+++ b/contrib/wpa/src/eap_server/eap_server_tnc.c
@@ -1,6 +1,6 @@
 /*
  * EAP server method: EAP-TNC (Trusted Network Connect)
- * Copyright (c) 2007-2008, Jouni Malinen 
+ * Copyright (c) 2007-2010, Jouni Malinen 
  *
  * 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
@@ -21,14 +21,18 @@
 
 
 struct eap_tnc_data {
-	enum { START, CONTINUE, RECOMMENDATION, FRAG_ACK, WAIT_FRAG_ACK, DONE,
-	       FAIL } state;
+	enum eap_tnc_state {
+		START, CONTINUE, RECOMMENDATION, FRAG_ACK, WAIT_FRAG_ACK, DONE,
+		FAIL
+	} state;
 	enum { ALLOW, ISOLATE, NO_ACCESS, NO_RECOMMENDATION } recommendation;
 	struct tncs_data *tncs;
 	struct wpabuf *in_buf;
 	struct wpabuf *out_buf;
 	size_t out_used;
 	size_t fragment_size;
+	unsigned int was_done:1;
+	unsigned int was_fail:1;
 };
 
 
@@ -41,6 +45,38 @@ struct eap_tnc_data {
 #define EAP_TNC_VERSION 1
 
 
+static const char * eap_tnc_state_txt(enum eap_tnc_state state)
+{
+	switch (state) {
+	case START:
+		return "START";
+	case CONTINUE:
+		return "CONTINUE";
+	case RECOMMENDATION:
+		return "RECOMMENDATION";
+	case FRAG_ACK:
+		return "FRAG_ACK";
+	case WAIT_FRAG_ACK:
+		return "WAIT_FRAG_ACK";
+	case DONE:
+		return "DONE";
+	case FAIL:
+		return "FAIL";
+	}
+	return "??";
+}
+
+
+static void eap_tnc_set_state(struct eap_tnc_data *data,
+			      enum eap_tnc_state new_state)
+{
+	wpa_printf(MSG_DEBUG, "EAP-TNC: %s -> %s",
+		   eap_tnc_state_txt(data->state),
+		   eap_tnc_state_txt(new_state));
+	data->state = new_state;
+}
+
+
 static void * eap_tnc_init(struct eap_sm *sm)
 {
 	struct eap_tnc_data *data;
@@ -48,7 +84,7 @@ static void * eap_tnc_init(struct eap_sm *sm)
 	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	data->state = START;
+	eap_tnc_set_state(data, START);
 	data->tncs = tncs_init();
 	if (data->tncs == NULL) {
 		os_free(data);
@@ -81,13 +117,13 @@ static struct wpabuf * eap_tnc_build_start(struct eap_sm *sm,
 	if (req == NULL) {
 		wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory for "
 			   "request");
-		data->state = FAIL;
+		eap_tnc_set_state(data, FAIL);
 		return NULL;
 	}
 
 	wpabuf_put_u8(req, EAP_TNC_FLAGS_START | EAP_TNC_VERSION);
 
-	data->state = CONTINUE;
+	eap_tnc_set_state(data, CONTINUE);
 
 	return req;
 }
@@ -146,17 +182,17 @@ static struct wpabuf * eap_tnc_build_recommendation(struct eap_sm *sm,
 {
 	switch (data->recommendation) {
 	case ALLOW:
-		data->state = DONE;
+		eap_tnc_set_state(data, DONE);
 		break;
 	case ISOLATE:
-		data->state = FAIL;
+		eap_tnc_set_state(data, FAIL);
 		/* TODO: support assignment to a different VLAN */
 		break;
 	case NO_ACCESS:
-		data->state = FAIL;
+		eap_tnc_set_state(data, FAIL);
 		break;
 	case NO_RECOMMENDATION:
-		data->state = DONE;
+		eap_tnc_set_state(data, DONE);
 		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-TNC: Unknown recommendation");
@@ -171,12 +207,13 @@ static struct wpabuf * eap_tnc_build_frag_ack(u8 id, u8 code)
 {
 	struct wpabuf *msg;
 
-	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 0, code, id);
+	msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, code, id);
 	if (msg == NULL) {
 		wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory "
 			   "for fragment ack");
 		return NULL;
 	}
+	wpabuf_put_u8(msg, EAP_TNC_VERSION); /* Flags */
 
 	wpa_printf(MSG_DEBUG, "EAP-TNC: Send fragment ack");
 
@@ -226,12 +263,20 @@ static struct wpabuf * eap_tnc_build_msg(struct eap_tnc_data *data, u8 id)
 		wpabuf_free(data->out_buf);
 		data->out_buf = NULL;
 		data->out_used = 0;
+		if (data->was_fail)
+			eap_tnc_set_state(data, FAIL);
+		else if (data->was_done)
+			eap_tnc_set_state(data, DONE);
 	} else {
 		wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes "
 			   "(%lu more to send)", (unsigned long) send_len,
 			   (unsigned long) wpabuf_len(data->out_buf) -
 			   data->out_used);
-		data->state = WAIT_FRAG_ACK;
+		if (data->state == FAIL)
+			data->was_fail = 1;
+		else if (data->state == DONE)
+			data->was_done = 1;
+		eap_tnc_set_state(data, WAIT_FRAG_ACK);
 	}
 
 	return req;
@@ -327,27 +372,27 @@ static void tncs_process(struct eap_tnc_data *data, struct wpabuf *inbuf)
 	switch (res) {
 	case TNCCS_RECOMMENDATION_ALLOW:
 		wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS allowed access");
-		data->state = RECOMMENDATION;
+		eap_tnc_set_state(data, RECOMMENDATION);
 		data->recommendation = ALLOW;
 		break;
 	case TNCCS_RECOMMENDATION_NO_RECOMMENDATION:
 		wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS has no recommendation");
-		data->state = RECOMMENDATION;
+		eap_tnc_set_state(data, RECOMMENDATION);
 		data->recommendation = NO_RECOMMENDATION;
 		break;
 	case TNCCS_RECOMMENDATION_ISOLATE:
 		wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS requested isolation");
-		data->state = RECOMMENDATION;
+		eap_tnc_set_state(data, RECOMMENDATION);
 		data->recommendation = ISOLATE;
 		break;
 	case TNCCS_RECOMMENDATION_NO_ACCESS:
 		wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS rejected access");
-		data->state = RECOMMENDATION;
+		eap_tnc_set_state(data, RECOMMENDATION);
 		data->recommendation = NO_ACCESS;
 		break;
 	case TNCCS_PROCESS_ERROR:
 		wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS processing error");
-		data->state = FAIL;
+		eap_tnc_set_state(data, FAIL);
 		break;
 	default:
 		break;
@@ -361,7 +406,7 @@ static int eap_tnc_process_cont(struct eap_tnc_data *data,
 	/* Process continuation of a pending message */
 	if (len > wpabuf_tailroom(data->in_buf)) {
 		wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment overflow");
-		data->state = FAIL;
+		eap_tnc_set_state(data, FAIL);
 		return -1;
 	}
 
@@ -435,7 +480,7 @@ static void eap_tnc_process(struct eap_sm *sm, void *priv,
 	if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) {
 		if (end - pos < 4) {
 			wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow");
-			data->state = FAIL;
+			eap_tnc_set_state(data, FAIL);
 			return;
 		}
 		message_length = WPA_GET_BE32(pos);
@@ -445,7 +490,7 @@ static void eap_tnc_process(struct eap_sm *sm, void *priv,
 			wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message "
 				   "Length (%d; %ld remaining in this msg)",
 				   message_length, (long) (end - pos));
-			data->state = FAIL;
+			eap_tnc_set_state(data, FAIL);
 			return;
 		}
 	}
@@ -453,32 +498,32 @@ static void eap_tnc_process(struct eap_sm *sm, void *priv,
 		   "Message Length %u", flags, message_length);
 
 	if (data->state == WAIT_FRAG_ACK) {
-		if (len != 0) {
+		if (len > 1) {
 			wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload "
 				   "in WAIT_FRAG_ACK state");
-			data->state = FAIL;
+			eap_tnc_set_state(data, FAIL);
 			return;
 		}
 		wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged");
-		data->state = CONTINUE;
+		eap_tnc_set_state(data, CONTINUE);
 		return;
 	}
 
 	if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) {
-		data->state = FAIL;
+		eap_tnc_set_state(data, FAIL);
 		return;
 	}
 		
 	if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) {
 		if (eap_tnc_process_fragment(data, flags, message_length,
 					     pos, end - pos) < 0)
-			data->state = FAIL;
+			eap_tnc_set_state(data, FAIL);
 		else
-			data->state = FRAG_ACK;
+			eap_tnc_set_state(data, FRAG_ACK);
 		return;
 	} else if (data->state == FRAG_ACK) {
 		wpa_printf(MSG_DEBUG, "EAP-TNC: All fragments received");
-		data->state = CONTINUE;
+		eap_tnc_set_state(data, CONTINUE);
 	}
 
 	if (data->in_buf == NULL) {
diff --git a/contrib/wpa/src/eap_server/eap_ttls.c b/contrib/wpa/src/eap_server/eap_server_ttls.c
similarity index 93%
rename from contrib/wpa/src/eap_server/eap_ttls.c
rename to contrib/wpa/src/eap_server/eap_server_ttls.c
index 21e4b21b15db..702c50c3566e 100644
--- a/contrib/wpa/src/eap_server/eap_ttls.c
+++ b/contrib/wpa/src/eap_server/eap_server_ttls.c
@@ -15,12 +15,12 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/ms_funcs.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "eap_server/eap_i.h"
 #include "eap_server/eap_tls_common.h"
-#include "ms_funcs.h"
-#include "sha1.h"
 #include "eap_common/chap.h"
-#include "tls.h"
 #include "eap_common/eap_ttls.h"
 
 
@@ -163,14 +163,14 @@ struct eap_ttls_avp {
 };
 
 
-static int eap_ttls_avp_parse(u8 *buf, size_t len, struct eap_ttls_avp *parse)
+static int eap_ttls_avp_parse(struct wpabuf *buf, struct eap_ttls_avp *parse)
 {
 	struct ttls_avp *avp;
 	u8 *pos;
 	int left;
 
-	pos = buf;
-	left = len;
+	pos = wpabuf_mhead(buf);
+	left = wpabuf_len(buf);
 	os_memset(parse, 0, sizeof(*parse));
 
 	while (left > 0) {
@@ -449,8 +449,6 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
 	struct eap_sm *sm, struct eap_ttls_data *data, u8 id)
 {
 	struct wpabuf *buf, *encr_req;
-	u8 *req;
-	size_t req_len;
 
 
 	buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
@@ -467,12 +465,10 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
 		return NULL;
 	}
 
-	req = wpabuf_mhead(buf);
-	req_len = wpabuf_len(buf);
-	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase "
-			"2 data", req, req_len);
+	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated "
+			    "Phase 2 data", buf);
 
-	encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
 	wpabuf_free(buf);
 
 	return encr_req;
@@ -482,10 +478,9 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
 static struct wpabuf * eap_ttls_build_phase2_mschapv2(
 	struct eap_sm *sm, struct eap_ttls_data *data)
 {
-	struct wpabuf *encr_req;
+	struct wpabuf *encr_req, msgbuf;
 	u8 *req, *pos, *end;
 	int ret;
-	size_t req_len;
 
 	pos = req = os_malloc(100);
 	if (req == NULL)
@@ -510,11 +505,11 @@ static struct wpabuf * eap_ttls_build_phase2_mschapv2(
 		AVP_PAD(req, pos);
 	}
 
-	req_len = pos - req;
-	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
-			"data", req, req_len);
+	wpabuf_set(&msgbuf, req, pos - req);
+	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
+			    "data", &msgbuf);
 
-	encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
+	encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
 	os_free(req);
 
 	return encr_req;
@@ -524,25 +519,8 @@ static struct wpabuf * eap_ttls_build_phase2_mschapv2(
 static struct wpabuf * eap_ttls_build_phase_finished(
 	struct eap_sm *sm, struct eap_ttls_data *data, int final)
 {
-	int len;
-	struct wpabuf *req;
-	const int max_len = 300;
-
-	req = wpabuf_alloc(max_len);
-	if (req == NULL)
-		return NULL;
-
-	len = tls_connection_ia_send_phase_finished(sm->ssl_ctx,
-						    data->ssl.conn, final,
-						    wpabuf_mhead(req),
-						    max_len);
-	if (len < 0) {
-		wpabuf_free(req);
-		return NULL;
-	}
-	wpabuf_put(req, len);
-
-	return req;
+	return tls_connection_ia_send_phase_finished(sm->ssl_ctx,
+						     data->ssl.conn, final);
 }
 
 
@@ -571,20 +549,20 @@ static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id)
 		}
 		break;
 	case PHASE2_METHOD:
-		wpabuf_free(data->ssl.out_buf);
-		data->ssl.out_used = 0;
-		data->ssl.out_buf = eap_ttls_build_phase2_eap_req(sm, data,
+		wpabuf_free(data->ssl.tls_out);
+		data->ssl.tls_out_pos = 0;
+		data->ssl.tls_out = eap_ttls_build_phase2_eap_req(sm, data,
 								  id);
 		break;
 	case PHASE2_MSCHAPV2_RESP:
-		wpabuf_free(data->ssl.out_buf);
-		data->ssl.out_used = 0;
-		data->ssl.out_buf = eap_ttls_build_phase2_mschapv2(sm, data);
+		wpabuf_free(data->ssl.tls_out);
+		data->ssl.tls_out_pos = 0;
+		data->ssl.tls_out = eap_ttls_build_phase2_mschapv2(sm, data);
 		break;
 	case PHASE_FINISHED:
-		wpabuf_free(data->ssl.out_buf);
-		data->ssl.out_used = 0;
-		data->ssl.out_buf = eap_ttls_build_phase_finished(sm, data, 1);
+		wpabuf_free(data->ssl.tls_out);
+		data->ssl.tls_out_pos = 0;
+		data->ssl.tls_out = eap_ttls_build_phase_finished(sm, data, 1);
 		break;
 	default:
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
@@ -1126,18 +1104,11 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
 				    struct eap_ttls_data *data,
 				    struct wpabuf *in_buf)
 {
-	u8 *in_decrypted;
-	int len_decrypted;
+	struct wpabuf *in_decrypted;
 	struct eap_ttls_avp parse;
-	size_t buf_len;
-	u8 *in_data;
-	size_t in_len;
-
-	in_data = wpabuf_mhead(in_buf);
-	in_len = wpabuf_len(in_buf);
 
 	wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
-		   " Phase 2", (unsigned long) in_len);
+		   " Phase 2", (unsigned long) wpabuf_len(in_buf));
 
 	if (data->pending_phase2_eap_resp) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response "
@@ -1150,35 +1121,17 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
 		return;
 	}
 
-	buf_len = in_len;
-	/*
-	 * Even though we try to disable TLS compression, it is possible that
-	 * this cannot be done with all TLS libraries. Add extra buffer space
-	 * to handle the possibility of the decrypted data being longer than
-	 * input data.
-	 */
-	buf_len += 500;
-	buf_len *= 3;
-	in_decrypted = os_malloc(buf_len);
+	in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
+					      in_buf);
 	if (in_decrypted == NULL) {
-		wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory "
-			   "for decryption");
-		return;
-	}
-
-	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
-					       in_data, in_len,
-					       in_decrypted, buf_len);
-	if (len_decrypted < 0) {
 		wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
 			   "data");
-		os_free(in_decrypted);
 		eap_ttls_state(data, FAILURE);
 		return;
 	}
 
 	if (data->state == PHASE_FINISHED) {
-		if (len_decrypted == 0 &&
+		if (wpabuf_len(in_decrypted) == 0 &&
 		    tls_connection_ia_final_phase_finished(sm->ssl_ctx,
 							   data->ssl.conn)) {
 			wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished "
@@ -1190,16 +1143,16 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
 			eap_ttls_state(data, FAILURE);
 		}
 
-		os_free(in_decrypted);
+		wpabuf_free(in_decrypted);
 		return;
 	}
 
-	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
-			in_decrypted, len_decrypted);
+	wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP",
+			    in_decrypted);
 
-	if (eap_ttls_avp_parse(in_decrypted, len_decrypted, &parse) < 0) {
+	if (eap_ttls_avp_parse(in_decrypted, &parse) < 0) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs");
-		os_free(in_decrypted);
+		wpabuf_free(in_decrypted);
 		eap_ttls_state(data, FAILURE);
 		return;
 	}
@@ -1221,14 +1174,14 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
 		}
 	}
 
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
 	if (data->tnc_started && parse.eap == NULL) {
 		wpa_printf(MSG_DEBUG, "EAP-TTLS: TNC started but no EAP "
 			   "response from peer");
 		eap_ttls_state(data, FAILURE);
 		goto done;
 	}
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 
 	if (parse.eap) {
 		eap_ttls_process_phase2_eap(sm, data, parse.eap,
@@ -1257,14 +1210,14 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
 	}
 
 done:
-	os_free(in_decrypted);
+	wpabuf_free(in_decrypted);
 	os_free(parse.eap);
 }
 
 
 static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data)
 {
-#ifdef EAP_TNC
+#ifdef EAP_SERVER_TNC
 	if (!sm->tnc || data->state != SUCCESS || data->tnc_started)
 		return;
 
@@ -1277,7 +1230,7 @@ static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data)
 
 	data->tnc_started = 1;
 	eap_ttls_state(data, PHASE2_METHOD);
-#endif /* EAP_TNC */
+#endif /* EAP_SERVER_TNC */
 }
 
 
@@ -1318,11 +1271,11 @@ static void eap_ttls_process_msg(struct eap_sm *sm, void *priv,
 	case PHASE2_START:
 	case PHASE2_METHOD:
 	case PHASE_FINISHED:
-		eap_ttls_process_phase2(sm, data, data->ssl.in_buf);
+		eap_ttls_process_phase2(sm, data, data->ssl.tls_in);
 		eap_ttls_start_tnc(sm, data);
 		break;
 	case PHASE2_MSCHAPV2_RESP:
-		if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.in_buf) ==
+		if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.tls_in) ==
 		    0) {
 			wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer "
 				   "acknowledged response");
@@ -1337,7 +1290,7 @@ static void eap_ttls_process_msg(struct eap_sm *sm, void *priv,
 				   "frame from peer (payload len %lu, "
 				   "expected empty frame)",
 				   (unsigned long)
-				   wpabuf_len(data->ssl.in_buf));
+				   wpabuf_len(data->ssl.tls_in));
 			eap_ttls_state(data, FAILURE);
 		}
 		eap_ttls_start_tnc(sm, data);
diff --git a/contrib/wpa/src/eap_server/eap_vendor_test.c b/contrib/wpa/src/eap_server/eap_server_vendor_test.c
similarity index 100%
rename from contrib/wpa/src/eap_server/eap_vendor_test.c
rename to contrib/wpa/src/eap_server/eap_server_vendor_test.c
diff --git a/contrib/wpa/src/eap_server/eap_wsc.c b/contrib/wpa/src/eap_server/eap_server_wsc.c
similarity index 92%
rename from contrib/wpa/src/eap_server/eap_wsc.c
rename to contrib/wpa/src/eap_server/eap_server_wsc.c
index 3c17577889b7..77cf9e2af2b1 100644
--- a/contrib/wpa/src/eap_server/eap_wsc.c
+++ b/contrib/wpa/src/eap_server/eap_server_wsc.c
@@ -22,7 +22,7 @@
 
 
 struct eap_wsc_data {
-	enum { START, MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state;
+	enum { START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state;
 	int registrar;
 	struct wpabuf *in_buf;
 	struct wpabuf *out_buf;
@@ -34,13 +34,14 @@ struct eap_wsc_data {
 };
 
 
+#ifndef CONFIG_NO_STDOUT_DEBUG
 static const char * eap_wsc_state_txt(int state)
 {
 	switch (state) {
 	case START:
 		return "START";
-	case MSG:
-		return "MSG";
+	case MESG:
+		return "MESG";
 	case FRAG_ACK:
 		return "FRAG_ACK";
 	case WAIT_FRAG_ACK:
@@ -53,6 +54,7 @@ static const char * eap_wsc_state_txt(int state)
 		return "?";
 	}
 }
+#endif /* CONFIG_NO_STDOUT_DEBUG */
 
 
 static void eap_wsc_state(struct eap_wsc_data *data, int state)
@@ -102,7 +104,7 @@ static void * eap_wsc_init(struct eap_sm *sm)
 	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
 		return NULL;
-	data->state = registrar ? START : MSG;
+	data->state = registrar ? START : MESG;
 	data->registrar = registrar;
 
 	os_memset(&cfg, 0, sizeof(cfg));
@@ -117,15 +119,24 @@ static void * eap_wsc_init(struct eap_sm *sm)
 		}
 	} else {
 		if (sm->user == NULL || sm->user->password == NULL) {
-			wpa_printf(MSG_INFO, "EAP-WSC: No AP PIN (password) "
-				   "configured for Enrollee functionality");
-			os_free(data);
-			return NULL;
+			/*
+			 * In theory, this should not really be needed, but
+			 * Windows 7 uses Registrar mode to probe AP's WPS
+			 * capabilities before trying to use Enrollee and fails
+			 * if the AP does not allow that probing to happen..
+			 */
+			wpa_printf(MSG_DEBUG, "EAP-WSC: No AP PIN (password) "
+				   "configured for Enrollee functionality - "
+				   "allow for probing capabilities (M1)");
+		} else {
+			cfg.pin = sm->user->password;
+			cfg.pin_len = sm->user->password_len;
 		}
-		cfg.pin = sm->user->password;
-		cfg.pin_len = sm->user->password_len;
 	}
 	cfg.assoc_wps_ie = sm->assoc_wps_ie;
+	cfg.peer_addr = sm->peer_addr;
+	if (0 /* TODO: could provide option for forcing PSK format */)
+		 cfg.use_psk_key = 1;
 	data->wps = wps_init(&cfg);
 	if (data->wps == NULL) {
 		os_free(data);
@@ -212,7 +223,7 @@ static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 id)
 		wpabuf_free(data->out_buf);
 		data->out_buf = NULL;
 		data->out_used = 0;
-		eap_wsc_state(data, MSG);
+		eap_wsc_state(data, MESG);
 	} else {
 		wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes "
 			   "(%lu more to send)", (unsigned long) send_len,
@@ -232,7 +243,7 @@ static struct wpabuf * eap_wsc_buildReq(struct eap_sm *sm, void *priv, u8 id)
 	switch (data->state) {
 	case START:
 		return eap_wsc_build_start(sm, data, id);
-	case MSG:
+	case MESG:
 		if (data->out_buf == NULL) {
 			data->out_buf = wps_get_msg(data->wps,
 						    &data->out_op_code);
@@ -385,7 +396,7 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv,
 			return;
 		}
 		wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged");
-		eap_wsc_state(data, MSG);
+		eap_wsc_state(data, MESG);
 		return;
 	}
 
@@ -427,14 +438,14 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv,
 		eap_wsc_state(data, FAIL);
 		break;
 	case WPS_CONTINUE:
-		eap_wsc_state(data, MSG);
+		eap_wsc_state(data, MESG);
 		break;
 	case WPS_FAILURE:
 		wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed");
 		eap_wsc_state(data, FAIL);
 		break;
 	case WPS_PENDING:
-		eap_wsc_state(data, MSG);
+		eap_wsc_state(data, MESG);
 		sm->method_pending = METHOD_PENDING_WAIT;
 		eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
 		eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout,
diff --git a/contrib/wpa/src/eap_server/eap_sim_db.c b/contrib/wpa/src/eap_server/eap_sim_db.c
index ed0bd3cd1332..aba919aa5512 100644
--- a/contrib/wpa/src/eap_server/eap_sim_db.c
+++ b/contrib/wpa/src/eap_server/eap_sim_db.c
@@ -1023,7 +1023,7 @@ int eap_sim_db_add_reauth(void *priv, const u8 *identity,
 }
 
 
-#ifdef EAP_AKA_PRIME
+#ifdef EAP_SERVER_AKA_PRIME
 /**
  * eap_sim_db_add_reauth_prime - EAP-AKA' DB: Add new re-authentication entry
  * @priv: Private data pointer from eap_sim_db_init()
@@ -1062,7 +1062,7 @@ int eap_sim_db_add_reauth_prime(void *priv, const u8 *identity,
 
 	return 0;
 }
-#endif /* EAP_AKA_PRIME */
+#endif /* EAP_SERVER_AKA_PRIME */
 
 
 /**
diff --git a/contrib/wpa/src/eap_server/eap_sim_db.h b/contrib/wpa/src/eap_server/eap_sim_db.h
index 66221817b220..ab89ae97d5a0 100644
--- a/contrib/wpa/src/eap_server/eap_sim_db.h
+++ b/contrib/wpa/src/eap_server/eap_sim_db.h
@@ -15,8 +15,6 @@
 #ifndef EAP_SIM_DB_H
 #define EAP_SIM_DB_H
 
-#ifdef EAP_SIM
-
 #include "eap_common/eap_sim_common.h"
 
 /* Identity prefixes */
@@ -90,18 +88,4 @@ int eap_sim_db_resynchronize(void *priv, const u8 *identity,
 			     size_t identity_len, const u8 *auts,
 			     const u8 *_rand);
 
-#else /* EAP_SIM */
-static inline void *
-eap_sim_db_init(const char *config,
-		void (*get_complete_cb)(void *ctx, void *session_ctx),
-		void *ctx)
-{
-	return (void *) 1;
-}
-
-static inline void eap_sim_db_deinit(void *priv)
-{
-}
-#endif /* EAP_SIM */
-
 #endif /* EAP_SIM_DB_H */
diff --git a/contrib/wpa/src/eap_server/eap_tls_common.h b/contrib/wpa/src/eap_server/eap_tls_common.h
index ce8dd252bc6d..c34c40108b24 100644
--- a/contrib/wpa/src/eap_server/eap_tls_common.h
+++ b/contrib/wpa/src/eap_server/eap_tls_common.h
@@ -1,6 +1,6 @@
 /*
- * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
- * Copyright (c) 2004-2008, Jouni Malinen 
+ * EAP-TLS/PEAP/TTLS/FAST server common functions
+ * Copyright (c) 2004-2009, Jouni Malinen 
  *
  * 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
@@ -15,19 +15,46 @@
 #ifndef EAP_TLS_COMMON_H
 #define EAP_TLS_COMMON_H
 
+/**
+ * struct eap_ssl_data - TLS data for EAP methods
+ */
 struct eap_ssl_data {
+	/**
+	 * conn - TLS connection context data from tls_connection_init()
+	 */
 	struct tls_connection *conn;
 
+	/**
+	 * tls_out - TLS message to be sent out in fragments
+	 */
+	struct wpabuf *tls_out;
+
+	/**
+	 * tls_out_pos - The current position in the outgoing TLS message
+	 */
+	size_t tls_out_pos;
+
+	/**
+	 * tls_out_limit - Maximum fragment size for outgoing TLS messages
+	 */
 	size_t tls_out_limit;
 
+	/**
+	 * tls_in - Received TLS message buffer for re-assembly
+	 */
+	struct wpabuf *tls_in;
+
+	/**
+	 * phase2 - Whether this TLS connection is used in EAP phase 2 (tunnel)
+	 */
 	int phase2;
 
+	/**
+	 * eap - EAP state machine allocated with eap_server_sm_init()
+	 */
 	struct eap_sm *eap;
 
 	enum { MSG, FRAG_ACK, WAIT_FRAG_ACK } state;
-	struct wpabuf *in_buf;
-	struct wpabuf *out_buf;
-	size_t out_used;
 	struct wpabuf tmpbuf;
 };
 
@@ -53,7 +80,7 @@ struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version);
 int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data);
 struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm,
 				       struct eap_ssl_data *data,
-				       const u8 *plain, size_t plain_len);
+				       const struct wpabuf *plain);
 int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data,
 			   struct wpabuf *respData, void *priv, int eap_type,
 			   int (*proc_version)(struct eap_sm *sm, void *priv,
diff --git a/contrib/wpa/src/eap_server/ikev2.c b/contrib/wpa/src/eap_server/ikev2.c
index 46767c501405..435ba2624933 100644
--- a/contrib/wpa/src/eap_server/ikev2.c
+++ b/contrib/wpa/src/eap_server/ikev2.c
@@ -15,7 +15,7 @@
 #include "includes.h"
 
 #include "common.h"
-#include "dh_groups.h"
+#include "crypto/dh_groups.h"
 #include "ikev2.h"
 
 
diff --git a/contrib/wpa/src/eap_server/tncs.c b/contrib/wpa/src/eap_server/tncs.c
index 21d83b3bd961..497b51a0f3e5 100644
--- a/contrib/wpa/src/eap_server/tncs.c
+++ b/contrib/wpa/src/eap_server/tncs.c
@@ -1231,6 +1231,7 @@ void tncs_global_deinit(void)
 	}
 
 	os_free(tncs_global_data);
+	tncs_global_data = NULL;
 }
 
 
diff --git a/contrib/wpa/src/eapol_auth/Makefile b/contrib/wpa/src/eapol_auth/Makefile
new file mode 100644
index 000000000000..9c41962fd7e1
--- /dev/null
+++ b/contrib/wpa/src/eapol_auth/Makefile
@@ -0,0 +1,8 @@
+all:
+	@echo Nothing to be made.
+
+clean:
+	rm -f *~ *.o *.d
+
+install:
+	@echo Nothing to be made.
diff --git a/contrib/wpa/src/eapol_auth/eapol_auth_dump.c b/contrib/wpa/src/eapol_auth/eapol_auth_dump.c
new file mode 100644
index 000000000000..a0f0e8d61669
--- /dev/null
+++ b/contrib/wpa/src/eapol_auth/eapol_auth_dump.c
@@ -0,0 +1,231 @@
+/*
+ * IEEE 802.1X-2004 Authenticator - State dump
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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.h"
+#include "eapol_auth_sm.h"
+#include "eapol_auth_sm_i.h"
+
+static inline const char * port_type_txt(PortTypes pt)
+{
+	switch (pt) {
+	case ForceUnauthorized: return "ForceUnauthorized";
+	case ForceAuthorized: return "ForceAuthorized";
+	case Auto: return "Auto";
+	default: return "Unknown";
+	}
+}
+
+
+static inline const char * port_state_txt(PortState ps)
+{
+	switch (ps) {
+	case Unauthorized: return "Unauthorized";
+	case Authorized: return "Authorized";
+	default: return "Unknown";
+	}
+}
+
+
+static inline const char * ctrl_dir_txt(ControlledDirection dir)
+{
+	switch (dir) {
+	case Both: return "Both";
+	case In: return "In";
+	default: return "Unknown";
+	}
+}
+
+
+static inline const char * auth_pae_state_txt(int s)
+{
+	switch (s) {
+	case AUTH_PAE_INITIALIZE: return "INITIALIZE";
+	case AUTH_PAE_DISCONNECTED: return "DISCONNECTED";
+	case AUTH_PAE_CONNECTING: return "CONNECTING";
+	case AUTH_PAE_AUTHENTICATING: return "AUTHENTICATING";
+	case AUTH_PAE_AUTHENTICATED: return "AUTHENTICATED";
+	case AUTH_PAE_ABORTING: return "ABORTING";
+	case AUTH_PAE_HELD: return "HELD";
+	case AUTH_PAE_FORCE_AUTH: return "FORCE_AUTH";
+	case AUTH_PAE_FORCE_UNAUTH: return "FORCE_UNAUTH";
+	case AUTH_PAE_RESTART: return "RESTART";
+	default: return "Unknown";
+	}
+}
+
+
+static inline const char * be_auth_state_txt(int s)
+{
+	switch (s) {
+	case BE_AUTH_REQUEST: return "REQUEST";
+	case BE_AUTH_RESPONSE: return "RESPONSE";
+	case BE_AUTH_SUCCESS: return "SUCCESS";
+	case BE_AUTH_FAIL: return "FAIL";
+	case BE_AUTH_TIMEOUT: return "TIMEOUT";
+	case BE_AUTH_IDLE: return "IDLE";
+	case BE_AUTH_INITIALIZE: return "INITIALIZE";
+	case BE_AUTH_IGNORE: return "IGNORE";
+	default: return "Unknown";
+	}
+}
+
+
+static inline const char * reauth_timer_state_txt(int s)
+{
+	switch (s) {
+	case REAUTH_TIMER_INITIALIZE: return "INITIALIZE";
+	case REAUTH_TIMER_REAUTHENTICATE: return "REAUTHENTICATE";
+	default: return "Unknown";
+	}
+}
+
+
+static inline const char * auth_key_tx_state_txt(int s)
+{
+	switch (s) {
+	case AUTH_KEY_TX_NO_KEY_TRANSMIT: return "NO_KEY_TRANSMIT";
+	case AUTH_KEY_TX_KEY_TRANSMIT: return "KEY_TRANSMIT";
+	default: return "Unknown";
+	}
+}
+
+
+static inline const char * key_rx_state_txt(int s)
+{
+	switch (s) {
+	case KEY_RX_NO_KEY_RECEIVE: return "NO_KEY_RECEIVE";
+	case KEY_RX_KEY_RECEIVE: return "KEY_RECEIVE";
+	default: return "Unknown";
+	}
+}
+
+
+static inline const char * ctrl_dir_state_txt(int s)
+{
+	switch (s) {
+	case CTRL_DIR_FORCE_BOTH: return "FORCE_BOTH";
+	case CTRL_DIR_IN_OR_BOTH: return "IN_OR_BOTH";
+	default: return "Unknown";
+	}
+}
+
+
+void eapol_auth_dump_state(FILE *f, const char *prefix,
+			   struct eapol_state_machine *sm)
+{
+	fprintf(f, "%sEAPOL state machine:\n", prefix);
+	fprintf(f, "%s  aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix,
+		sm->aWhile, sm->quietWhile, sm->reAuthWhen);
+#define _SB(b) ((b) ? "TRUE" : "FALSE")
+	fprintf(f,
+		"%s  authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n"
+		"%s  authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n"
+		"%s  eapSuccess=%s eapTimeout=%s initialize=%s "
+		"keyAvailable=%s\n"
+		"%s  keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n"
+		"%s  portEnabled=%s portValid=%s reAuthenticate=%s\n",
+		prefix, _SB(sm->authAbort), _SB(sm->authFail),
+		port_state_txt(sm->authPortStatus), _SB(sm->authStart),
+		prefix, _SB(sm->authTimeout), _SB(sm->authSuccess),
+		_SB(sm->eap_if->eapFail), _SB(sm->eapolEap),
+		prefix, _SB(sm->eap_if->eapSuccess),
+		_SB(sm->eap_if->eapTimeout),
+		_SB(sm->initialize), _SB(sm->eap_if->eapKeyAvailable),
+		prefix, _SB(sm->keyDone), _SB(sm->keyRun),
+		_SB(sm->keyTxEnabled), port_type_txt(sm->portControl),
+		prefix, _SB(sm->eap_if->portEnabled), _SB(sm->portValid),
+		_SB(sm->reAuthenticate));
+
+	fprintf(f, "%s  Authenticator PAE:\n"
+		"%s    state=%s\n"
+		"%s    eapolLogoff=%s eapolStart=%s eapRestart=%s\n"
+		"%s    portMode=%s reAuthCount=%d\n"
+		"%s    quietPeriod=%d reAuthMax=%d\n"
+		"%s    authEntersConnecting=%d\n"
+		"%s    authEapLogoffsWhileConnecting=%d\n"
+		"%s    authEntersAuthenticating=%d\n"
+		"%s    authAuthSuccessesWhileAuthenticating=%d\n"
+		"%s    authAuthTimeoutsWhileAuthenticating=%d\n"
+		"%s    authAuthFailWhileAuthenticating=%d\n"
+		"%s    authAuthEapStartsWhileAuthenticating=%d\n"
+		"%s    authAuthEapLogoffWhileAuthenticating=%d\n"
+		"%s    authAuthReauthsWhileAuthenticated=%d\n"
+		"%s    authAuthEapStartsWhileAuthenticated=%d\n"
+		"%s    authAuthEapLogoffWhileAuthenticated=%d\n",
+		prefix, prefix, auth_pae_state_txt(sm->auth_pae_state), prefix,
+		_SB(sm->eapolLogoff), _SB(sm->eapolStart),
+		_SB(sm->eap_if->eapRestart),
+		prefix, port_type_txt(sm->portMode), sm->reAuthCount,
+		prefix, sm->quietPeriod, sm->reAuthMax,
+		prefix, sm->authEntersConnecting,
+		prefix, sm->authEapLogoffsWhileConnecting,
+		prefix, sm->authEntersAuthenticating,
+		prefix, sm->authAuthSuccessesWhileAuthenticating,
+		prefix, sm->authAuthTimeoutsWhileAuthenticating,
+		prefix, sm->authAuthFailWhileAuthenticating,
+		prefix, sm->authAuthEapStartsWhileAuthenticating,
+		prefix, sm->authAuthEapLogoffWhileAuthenticating,
+		prefix, sm->authAuthReauthsWhileAuthenticated,
+		prefix, sm->authAuthEapStartsWhileAuthenticated,
+		prefix, sm->authAuthEapLogoffWhileAuthenticated);
+
+	fprintf(f, "%s  Backend Authentication:\n"
+		"%s    state=%s\n"
+		"%s    eapNoReq=%s eapReq=%s eapResp=%s\n"
+		"%s    serverTimeout=%d\n"
+		"%s    backendResponses=%d\n"
+		"%s    backendAccessChallenges=%d\n"
+		"%s    backendOtherRequestsToSupplicant=%d\n"
+		"%s    backendAuthSuccesses=%d\n"
+		"%s    backendAuthFails=%d\n",
+		prefix, prefix,
+		be_auth_state_txt(sm->be_auth_state),
+		prefix, _SB(sm->eap_if->eapNoReq), _SB(sm->eap_if->eapReq),
+		_SB(sm->eap_if->eapResp),
+		prefix, sm->serverTimeout,
+		prefix, sm->backendResponses,
+		prefix, sm->backendAccessChallenges,
+		prefix, sm->backendOtherRequestsToSupplicant,
+		prefix, sm->backendAuthSuccesses,
+		prefix, sm->backendAuthFails);
+
+	fprintf(f, "%s  Reauthentication Timer:\n"
+		"%s    state=%s\n"
+		"%s    reAuthPeriod=%d reAuthEnabled=%s\n", prefix, prefix,
+		reauth_timer_state_txt(sm->reauth_timer_state), prefix,
+		sm->reAuthPeriod, _SB(sm->reAuthEnabled));
+
+	fprintf(f, "%s  Authenticator Key Transmit:\n"
+		"%s    state=%s\n", prefix, prefix,
+		auth_key_tx_state_txt(sm->auth_key_tx_state));
+
+	fprintf(f, "%s  Key Receive:\n"
+		"%s    state=%s\n"
+		"%s    rxKey=%s\n", prefix, prefix,
+		key_rx_state_txt(sm->key_rx_state), prefix, _SB(sm->rxKey));
+
+	fprintf(f, "%s  Controlled Directions:\n"
+		"%s    state=%s\n"
+		"%s    adminControlledDirections=%s "
+		"operControlledDirections=%s\n"
+		"%s    operEdge=%s\n", prefix, prefix,
+		ctrl_dir_state_txt(sm->ctrl_dir_state),
+		prefix, ctrl_dir_txt(sm->adminControlledDirections),
+		ctrl_dir_txt(sm->operControlledDirections),
+		prefix, _SB(sm->operEdge));
+#undef _SB
+}
diff --git a/contrib/wpa/hostapd/eapol_sm.c b/contrib/wpa/src/eapol_auth/eapol_auth_sm.c
similarity index 75%
rename from contrib/wpa/hostapd/eapol_sm.c
rename to contrib/wpa/src/eapol_auth/eapol_auth_sm.c
index 8e9d56c7964f..a1976e8f0a29 100644
--- a/contrib/wpa/hostapd/eapol_sm.c
+++ b/contrib/wpa/src/eapol_auth/eapol_auth_sm.c
@@ -1,6 +1,6 @@
 /*
- * hostapd / IEEE 802.1X-2004 Authenticator - EAPOL state machine
- * Copyright (c) 2002-2008, Jouni Malinen 
+ * IEEE 802.1X-2004 Authenticator - EAPOL state machine
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -14,16 +14,15 @@
 
 #include "includes.h"
 
-#include "hostapd.h"
-#include "ieee802_1x.h"
-#include "eapol_sm.h"
+#include "common.h"
 #include "eloop.h"
-#include "wpa.h"
-#include "preauth.h"
-#include "sta_info.h"
-#include "eap_server/eap.h"
 #include "state_machine.h"
+#include "common/eapol_common.h"
+#include "eap_common/eap_defs.h"
 #include "eap_common/eap_common.h"
+#include "eap_server/eap.h"
+#include "eapol_auth_sm.h"
+#include "eapol_auth_sm_i.h"
 
 #define STATE_MACHINE_DATA struct eapol_state_machine
 #define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X"
@@ -34,35 +33,36 @@ static struct eapol_callbacks eapol_cb;
 /* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */
 
 #define setPortAuthorized() \
-sm->eapol->cb.set_port_authorized(sm->hapd, sm->sta, 1)
+sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 1)
 #define setPortUnauthorized() \
-sm->eapol->cb.set_port_authorized(sm->hapd, sm->sta, 0)
+sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 0)
 
 /* procedures */
 #define txCannedFail() eapol_auth_tx_canned_eap(sm, 0)
 #define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1)
 #define txReq() eapol_auth_tx_req(sm)
-#define abortAuth() sm->eapol->cb.abort_auth(sm->hapd, sm->sta)
-#define txKey() sm->eapol->cb.tx_key(sm->hapd, sm->sta)
+#define abortAuth() sm->eapol->cb.abort_auth(sm->eapol->conf.ctx, sm->sta)
+#define txKey() sm->eapol->cb.tx_key(sm->eapol->conf.ctx, sm->sta)
 #define processKey() do { } while (0)
 
 
 static void eapol_sm_step_run(struct eapol_state_machine *sm);
 static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx);
+static void eapol_auth_initialize(struct eapol_state_machine *sm);
 
 
 static void eapol_auth_logger(struct eapol_authenticator *eapol,
-			      const u8 *addr, logger_level level,
+			      const u8 *addr, eapol_logger_level level,
 			      const char *txt)
 {
 	if (eapol->cb.logger == NULL)
 		return;
-	eapol->cb.logger(eapol->conf.hapd, addr, level, txt);
+	eapol->cb.logger(eapol->conf.ctx, addr, level, txt);
 }
 
 
 static void eapol_auth_vlogger(struct eapol_authenticator *eapol,
-			       const u8 *addr, logger_level level,
+			       const u8 *addr, eapol_logger_level level,
 			       const char *fmt, ...)
 {
 	char *format;
@@ -101,7 +101,8 @@ static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm,
 	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
 			   "Sending canned EAP packet %s (identifier %d)",
 			   success ? "SUCCESS" : "FAILURE", eap.identifier);
-	sm->eapol->cb.eapol_send(sm->hapd, sm->sta, IEEE802_1X_TYPE_EAP_PACKET,
+	sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta,
+				 IEEE802_1X_TYPE_EAP_PACKET,
 				 (u8 *) &eap, sizeof(eap));
 	sm->dot1xAuthEapolFramesTx++;
 }
@@ -129,7 +130,8 @@ static void eapol_auth_tx_req(struct eapol_state_machine *sm)
 	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG,
 			   "Sending EAP Packet (identifier %d)",
 			   sm->last_eap_id);
-	sm->eapol->cb.eapol_send(sm->hapd, sm->sta, IEEE802_1X_TYPE_EAP_PACKET,
+	sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta,
+				 IEEE802_1X_TYPE_EAP_PACKET,
 				 wpabuf_head(sm->eap_if->eapReqData),
 				 wpabuf_len(sm->eap_if->eapReqData));
 	sm->dot1xAuthEapolFramesTx++;
@@ -222,7 +224,7 @@ SM_STATE(AUTH_PAE, DISCONNECTED)
 	sm->reAuthCount = 0;
 	sm->eapolLogoff = FALSE;
 	if (!from_initialize) {
-		sm->eapol->cb.finished(sm->hapd, sm->sta, 0,
+		sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
 				       sm->flags & EAPOL_SM_PREAUTH);
 	}
 }
@@ -272,14 +274,14 @@ SM_STATE(AUTH_PAE, HELD)
 	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING,
 			   "authentication failed - EAP type: %d (%s)",
 			   sm->eap_type_authsrv,
-			   eap_type_text(sm->eap_type_authsrv));
+			   eap_server_get_name(0, sm->eap_type_authsrv));
 	if (sm->eap_type_authsrv != sm->eap_type_supp) {
 		eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
 				   "Supplicant used different EAP type: "
 				   "%d (%s)", sm->eap_type_supp,
-				   eap_type_text(sm->eap_type_supp));
+				   eap_server_get_name(0, sm->eap_type_supp));
 	}
-	sm->eapol->cb.finished(sm->hapd, sm->sta, 0,
+	sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0,
 			       sm->flags & EAPOL_SM_PREAUTH);
 }
 
@@ -298,13 +300,14 @@ SM_STATE(AUTH_PAE, AUTHENTICATED)
 	sm->reAuthCount = 0;
 	if (sm->flags & EAPOL_SM_PREAUTH)
 		extra = " (pre-authentication)";
-	else if (wpa_auth_sta_get_pmksa(sm->sta->wpa_sm))
+	else if (sm->flags & EAPOL_SM_FROM_PMKSA_CACHE)
 		extra = " (PMKSA cache)";
 	eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO,
 			   "authenticated - EAP type: %d (%s)%s",
 			   sm->eap_type_authsrv,
-			   eap_type_text(sm->eap_type_authsrv), extra);
-	sm->eapol->cb.finished(sm->hapd, sm->sta, 1,
+			   eap_server_get_name(0, sm->eap_type_authsrv),
+			   extra);
+	sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1,
 			       sm->flags & EAPOL_SM_PREAUTH);
 }
 
@@ -611,7 +614,8 @@ SM_STATE(REAUTH_TIMER, REAUTHENTICATE)
 	SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer);
 
 	sm->reAuthenticate = TRUE;
-	wpa_auth_sm_event(sm->sta->wpa_sm, WPA_REAUTH_EAPOL);
+	sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta,
+				  EAPOL_AUTH_REAUTHENTICATE);
 }
 
 
@@ -664,7 +668,7 @@ SM_STEP(AUTH_KEY_TX)
 	switch (sm->auth_key_tx_state) {
 	case AUTH_KEY_TX_NO_KEY_TRANSMIT:
 		if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable &&
-		    sm->keyRun && !wpa_auth_sta_wpa_version(sm->sta->wpa_sm))
+		    sm->keyRun && !(sm->flags & EAPOL_SM_USES_WPA))
 			SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT);
 		break;
 	case AUTH_KEY_TX_KEY_TRANSMIT:
@@ -758,15 +762,13 @@ SM_STEP(CTRL_DIR)
 
 struct eapol_state_machine *
 eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
-		 int preauth, struct sta_info *sta)
+		 int flags, const struct wpabuf *assoc_wps_ie, void *sta_ctx)
 {
 	struct eapol_state_machine *sm;
-	struct hostapd_data *hapd; /* TODO: to be removed */
 	struct eap_config eap_conf;
 
 	if (eapol == NULL)
 		return NULL;
-	hapd = eapol->conf.hapd;
 
 	sm = os_zalloc(sizeof(*sm));
 	if (sm == NULL) {
@@ -776,12 +778,10 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
 	}
 	sm->radius_identifier = -1;
 	os_memcpy(sm->addr, addr, ETH_ALEN);
-	if (preauth)
-		sm->flags |= EAPOL_SM_PREAUTH;
+	sm->flags = flags;
 
-	sm->hapd = hapd;
 	sm->eapol = eapol;
-	sm->sta = sta;
+	sm->sta = sta_ctx;
 
 	/* Set default values for state machine constants */
 	sm->auth_pae_state = AUTH_PAE_INITIALIZE;
@@ -804,7 +804,7 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
 	sm->portControl = Auto;
 
 	if (!eapol->conf.wpa &&
-	    (hapd->default_wep_key || eapol->conf.individual_wep_key_len > 0))
+	    (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0))
 		sm->keyTxEnabled = TRUE;
 	else
 		sm->keyTxEnabled = FALSE;
@@ -816,6 +816,7 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
 	os_memset(&eap_conf, 0, sizeof(eap_conf));
 	eap_conf.eap_server = eapol->conf.eap_server;
 	eap_conf.ssl_ctx = eapol->conf.ssl_ctx;
+	eap_conf.msg_ctx = eapol->conf.msg_ctx;
 	eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv;
 	eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key;
 	eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id;
@@ -827,7 +828,8 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
 	eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind;
 	eap_conf.tnc = eapol->conf.tnc;
 	eap_conf.wps = eapol->conf.wps;
-	eap_conf.assoc_wps_ie = sta->wps_ie;
+	eap_conf.assoc_wps_ie = assoc_wps_ie;
+	eap_conf.peer_addr = addr;
 	sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf);
 	if (sm->eap == NULL) {
 		eapol_auth_free(sm);
@@ -857,7 +859,7 @@ void eapol_auth_free(struct eapol_state_machine *sm)
 static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol,
 				    const u8 *addr)
 {
-	return eapol->cb.sta_entry_alive(eapol->conf.hapd, addr);
+	return eapol->cb.sta_entry_alive(eapol->conf.ctx, addr);
 }
 
 
@@ -928,14 +930,15 @@ static void eapol_sm_step_run(struct eapol_state_machine *sm)
 				return;
 			}
 			sm->eapol->cb.aaa_send(
-				sm->hapd, sm->sta,
+				sm->eapol->conf.ctx, sm->sta,
 				wpabuf_head(sm->eap_if->aaaEapRespData),
 				wpabuf_len(sm->eap_if->aaaEapRespData));
 		}
 	}
 
 	if (eapol_sm_sta_entry_alive(eapol, addr))
-		wpa_auth_sm_notify(sm->sta->wpa_sm);
+		sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta,
+					  EAPOL_AUTH_SM_CHANGE);
 }
 
 
@@ -965,7 +968,7 @@ void eapol_auth_step(struct eapol_state_machine *sm)
 }
 
 
-void eapol_auth_initialize(struct eapol_state_machine *sm)
+static void eapol_auth_initialize(struct eapol_state_machine *sm)
 {
 	sm->initializing = TRUE;
 	/* Initialize the state machines by asserting initialize and then
@@ -982,227 +985,13 @@ void eapol_auth_initialize(struct eapol_state_machine *sm)
 }
 
 
-#ifdef HOSTAPD_DUMP_STATE
-static inline const char * port_type_txt(PortTypes pt)
-{
-	switch (pt) {
-	case ForceUnauthorized: return "ForceUnauthorized";
-	case ForceAuthorized: return "ForceAuthorized";
-	case Auto: return "Auto";
-	default: return "Unknown";
-	}
-}
-
-
-static inline const char * port_state_txt(PortState ps)
-{
-	switch (ps) {
-	case Unauthorized: return "Unauthorized";
-	case Authorized: return "Authorized";
-	default: return "Unknown";
-	}
-}
-
-
-static inline const char * ctrl_dir_txt(ControlledDirection dir)
-{
-	switch (dir) {
-	case Both: return "Both";
-	case In: return "In";
-	default: return "Unknown";
-	}
-}
-
-
-static inline const char * auth_pae_state_txt(int s)
-{
-	switch (s) {
-	case AUTH_PAE_INITIALIZE: return "INITIALIZE";
-	case AUTH_PAE_DISCONNECTED: return "DISCONNECTED";
-	case AUTH_PAE_CONNECTING: return "CONNECTING";
-	case AUTH_PAE_AUTHENTICATING: return "AUTHENTICATING";
-	case AUTH_PAE_AUTHENTICATED: return "AUTHENTICATED";
-	case AUTH_PAE_ABORTING: return "ABORTING";
-	case AUTH_PAE_HELD: return "HELD";
-	case AUTH_PAE_FORCE_AUTH: return "FORCE_AUTH";
-	case AUTH_PAE_FORCE_UNAUTH: return "FORCE_UNAUTH";
-	case AUTH_PAE_RESTART: return "RESTART";
-	default: return "Unknown";
-	}
-}
-
-
-static inline const char * be_auth_state_txt(int s)
-{
-	switch (s) {
-	case BE_AUTH_REQUEST: return "REQUEST";
-	case BE_AUTH_RESPONSE: return "RESPONSE";
-	case BE_AUTH_SUCCESS: return "SUCCESS";
-	case BE_AUTH_FAIL: return "FAIL";
-	case BE_AUTH_TIMEOUT: return "TIMEOUT";
-	case BE_AUTH_IDLE: return "IDLE";
-	case BE_AUTH_INITIALIZE: return "INITIALIZE";
-	case BE_AUTH_IGNORE: return "IGNORE";
-	default: return "Unknown";
-	}
-}
-
-
-static inline const char * reauth_timer_state_txt(int s)
-{
-	switch (s) {
-	case REAUTH_TIMER_INITIALIZE: return "INITIALIZE";
-	case REAUTH_TIMER_REAUTHENTICATE: return "REAUTHENTICATE";
-	default: return "Unknown";
-	}
-}
-
-
-static inline const char * auth_key_tx_state_txt(int s)
-{
-	switch (s) {
-	case AUTH_KEY_TX_NO_KEY_TRANSMIT: return "NO_KEY_TRANSMIT";
-	case AUTH_KEY_TX_KEY_TRANSMIT: return "KEY_TRANSMIT";
-	default: return "Unknown";
-	}
-}
-
-
-static inline const char * key_rx_state_txt(int s)
-{
-	switch (s) {
-	case KEY_RX_NO_KEY_RECEIVE: return "NO_KEY_RECEIVE";
-	case KEY_RX_KEY_RECEIVE: return "KEY_RECEIVE";
-	default: return "Unknown";
-	}
-}
-
-
-static inline const char * ctrl_dir_state_txt(int s)
-{
-	switch (s) {
-	case CTRL_DIR_FORCE_BOTH: return "FORCE_BOTH";
-	case CTRL_DIR_IN_OR_BOTH: return "IN_OR_BOTH";
-	default: return "Unknown";
-	}
-}
-
-
-void eapol_auth_dump_state(FILE *f, const char *prefix,
-			   struct eapol_state_machine *sm)
-{
-	fprintf(f, "%sEAPOL state machine:\n", prefix);
-	fprintf(f, "%s  aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix,
-		sm->aWhile, sm->quietWhile, sm->reAuthWhen);
-#define _SB(b) ((b) ? "TRUE" : "FALSE")
-	fprintf(f,
-		"%s  authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n"
-		"%s  authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n"
-		"%s  eapSuccess=%s eapTimeout=%s initialize=%s "
-		"keyAvailable=%s\n"
-		"%s  keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n"
-		"%s  portEnabled=%s portValid=%s reAuthenticate=%s\n",
-		prefix, _SB(sm->authAbort), _SB(sm->authFail),
-		port_state_txt(sm->authPortStatus), _SB(sm->authStart),
-		prefix, _SB(sm->authTimeout), _SB(sm->authSuccess),
-		_SB(sm->eap_if->eapFail), _SB(sm->eapolEap),
-		prefix, _SB(sm->eap_if->eapSuccess),
-		_SB(sm->eap_if->eapTimeout),
-		_SB(sm->initialize), _SB(sm->eap_if->eapKeyAvailable),
-		prefix, _SB(sm->keyDone), _SB(sm->keyRun),
-		_SB(sm->keyTxEnabled), port_type_txt(sm->portControl),
-		prefix, _SB(sm->eap_if->portEnabled), _SB(sm->portValid),
-		_SB(sm->reAuthenticate));
-
-	fprintf(f, "%s  Authenticator PAE:\n"
-		"%s    state=%s\n"
-		"%s    eapolLogoff=%s eapolStart=%s eapRestart=%s\n"
-		"%s    portMode=%s reAuthCount=%d\n"
-		"%s    quietPeriod=%d reAuthMax=%d\n"
-		"%s    authEntersConnecting=%d\n"
-		"%s    authEapLogoffsWhileConnecting=%d\n"
-		"%s    authEntersAuthenticating=%d\n"
-		"%s    authAuthSuccessesWhileAuthenticating=%d\n"
-		"%s    authAuthTimeoutsWhileAuthenticating=%d\n"
-		"%s    authAuthFailWhileAuthenticating=%d\n"
-		"%s    authAuthEapStartsWhileAuthenticating=%d\n"
-		"%s    authAuthEapLogoffWhileAuthenticating=%d\n"
-		"%s    authAuthReauthsWhileAuthenticated=%d\n"
-		"%s    authAuthEapStartsWhileAuthenticated=%d\n"
-		"%s    authAuthEapLogoffWhileAuthenticated=%d\n",
-		prefix, prefix, auth_pae_state_txt(sm->auth_pae_state), prefix,
-		_SB(sm->eapolLogoff), _SB(sm->eapolStart),
-		_SB(sm->eap_if->eapRestart),
-		prefix, port_type_txt(sm->portMode), sm->reAuthCount,
-		prefix, sm->quietPeriod, sm->reAuthMax,
-		prefix, sm->authEntersConnecting,
-		prefix, sm->authEapLogoffsWhileConnecting,
-		prefix, sm->authEntersAuthenticating,
-		prefix, sm->authAuthSuccessesWhileAuthenticating,
-		prefix, sm->authAuthTimeoutsWhileAuthenticating,
-		prefix, sm->authAuthFailWhileAuthenticating,
-		prefix, sm->authAuthEapStartsWhileAuthenticating,
-		prefix, sm->authAuthEapLogoffWhileAuthenticating,
-		prefix, sm->authAuthReauthsWhileAuthenticated,
-		prefix, sm->authAuthEapStartsWhileAuthenticated,
-		prefix, sm->authAuthEapLogoffWhileAuthenticated);
-
-	fprintf(f, "%s  Backend Authentication:\n"
-		"%s    state=%s\n"
-		"%s    eapNoReq=%s eapReq=%s eapResp=%s\n"
-		"%s    serverTimeout=%d\n"
-		"%s    backendResponses=%d\n"
-		"%s    backendAccessChallenges=%d\n"
-		"%s    backendOtherRequestsToSupplicant=%d\n"
-		"%s    backendAuthSuccesses=%d\n"
-		"%s    backendAuthFails=%d\n",
-		prefix, prefix,
-		be_auth_state_txt(sm->be_auth_state),
-		prefix, _SB(sm->eap_if->eapNoReq), _SB(sm->eap_if->eapReq),
-		_SB(sm->eap_if->eapResp),
-		prefix, sm->serverTimeout,
-		prefix, sm->backendResponses,
-		prefix, sm->backendAccessChallenges,
-		prefix, sm->backendOtherRequestsToSupplicant,
-		prefix, sm->backendAuthSuccesses,
-		prefix, sm->backendAuthFails);
-
-	fprintf(f, "%s  Reauthentication Timer:\n"
-		"%s    state=%s\n"
-		"%s    reAuthPeriod=%d reAuthEnabled=%s\n", prefix, prefix,
-		reauth_timer_state_txt(sm->reauth_timer_state), prefix,
-		sm->reAuthPeriod, _SB(sm->reAuthEnabled));
-
-	fprintf(f, "%s  Authenticator Key Transmit:\n"
-		"%s    state=%s\n", prefix, prefix,
-		auth_key_tx_state_txt(sm->auth_key_tx_state));
-
-	fprintf(f, "%s  Key Receive:\n"
-		"%s    state=%s\n"
-		"%s    rxKey=%s\n", prefix, prefix,
-		key_rx_state_txt(sm->key_rx_state), prefix, _SB(sm->rxKey));
-
-	fprintf(f, "%s  Controlled Directions:\n"
-		"%s    state=%s\n"
-		"%s    adminControlledDirections=%s "
-		"operControlledDirections=%s\n"
-		"%s    operEdge=%s\n", prefix, prefix,
-		ctrl_dir_state_txt(sm->ctrl_dir_state),
-		prefix, ctrl_dir_txt(sm->adminControlledDirections),
-		ctrl_dir_txt(sm->operControlledDirections),
-		prefix, _SB(sm->operEdge));
-#undef _SB
-}
-#endif /* HOSTAPD_DUMP_STATE */
-
-
 static int eapol_sm_get_eap_user(void *ctx, const u8 *identity,
 				 size_t identity_len, int phase2,
 				 struct eap_user *user)
 {
 	struct eapol_state_machine *sm = ctx;
-	return sm->eapol->cb.get_eap_user(sm->hapd, identity, identity_len,
-					  phase2, user);
+	return sm->eapol->cb.get_eap_user(sm->eapol->conf.ctx, identity,
+					  identity_len, phase2, user);
 }
 
 
@@ -1216,8 +1005,8 @@ static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len)
 
 static struct eapol_callbacks eapol_cb =
 {
-	.get_eap_user = eapol_sm_get_eap_user,
-	.get_eap_req_id_text = eapol_sm_get_eap_req_id_text,
+	eapol_sm_get_eap_user,
+	eapol_sm_get_eap_req_id_text
 };
 
 
@@ -1236,12 +1025,13 @@ int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx)
 static int eapol_auth_conf_clone(struct eapol_auth_config *dst,
 				 struct eapol_auth_config *src)
 {
-	dst->hapd = src->hapd;
+	dst->ctx = src->ctx;
 	dst->eap_reauth_period = src->eap_reauth_period;
 	dst->wpa = src->wpa;
 	dst->individual_wep_key_len = src->individual_wep_key_len;
 	dst->eap_server = src->eap_server;
 	dst->ssl_ctx = src->ssl_ctx;
+	dst->msg_ctx = src->msg_ctx;
 	dst->eap_sim_db_priv = src->eap_sim_db_priv;
 	os_free(dst->eap_req_id_text);
 	if (src->eap_req_id_text) {
@@ -1318,6 +1108,11 @@ struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
 		return NULL;
 	}
 
+	if (conf->individual_wep_key_len > 0) {
+		/* use key0 in individual key and key1 in broadcast key */
+		eapol->default_wep_key_idx = 1;
+	}
+
 	eapol->cb.eapol_send = cb->eapol_send;
 	eapol->cb.aaa_send = cb->aaa_send;
 	eapol->cb.finished = cb->finished;
@@ -1327,6 +1122,7 @@ struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
 	eapol->cb.set_port_authorized = cb->set_port_authorized;
 	eapol->cb.abort_auth = cb->abort_auth;
 	eapol->cb.tx_key = cb->tx_key;
+	eapol->cb.eapol_event = cb->eapol_event;
 
 	return eapol;
 }
@@ -1338,5 +1134,6 @@ void eapol_auth_deinit(struct eapol_authenticator *eapol)
 		return;
 
 	eapol_auth_conf_free(&eapol->conf);
+	os_free(eapol->default_wep_key);
 	os_free(eapol);
 }
diff --git a/contrib/wpa/src/eapol_auth/eapol_auth_sm.h b/contrib/wpa/src/eapol_auth/eapol_auth_sm.h
new file mode 100644
index 000000000000..ef943ad47813
--- /dev/null
+++ b/contrib/wpa/src/eapol_auth/eapol_auth_sm.h
@@ -0,0 +1,89 @@
+/*
+ * IEEE 802.1X-2004 Authenticator - EAPOL state machine
+ * Copyright (c) 2002-2009, Jouni Malinen 
+ *
+ * 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 EAPOL_AUTH_SM_H
+#define EAPOL_AUTH_SM_H
+
+#define EAPOL_SM_PREAUTH BIT(0)
+#define EAPOL_SM_WAIT_START BIT(1)
+#define EAPOL_SM_USES_WPA BIT(2)
+#define EAPOL_SM_FROM_PMKSA_CACHE BIT(3)
+
+struct eapol_auth_config {
+	int eap_reauth_period;
+	int wpa;
+	int individual_wep_key_len;
+	int eap_server;
+	void *ssl_ctx;
+	void *msg_ctx;
+	void *eap_sim_db_priv;
+	char *eap_req_id_text; /* a copy of this will be allocated */
+	size_t eap_req_id_text_len;
+	u8 *pac_opaque_encr_key;
+	u8 *eap_fast_a_id;
+	size_t eap_fast_a_id_len;
+	char *eap_fast_a_id_info;
+	int eap_fast_prov;
+	int pac_key_lifetime;
+	int pac_key_refresh_time;
+	int eap_sim_aka_result_ind;
+	int tnc;
+	struct wps_context *wps;
+
+	/* Opaque context pointer to owner data for callback functions */
+	void *ctx;
+};
+
+struct eap_user;
+
+typedef enum {
+	EAPOL_LOGGER_DEBUG, EAPOL_LOGGER_INFO, EAPOL_LOGGER_WARNING
+} eapol_logger_level;
+
+enum eapol_event {
+	EAPOL_AUTH_SM_CHANGE,
+	EAPOL_AUTH_REAUTHENTICATE
+};
+
+struct eapol_auth_cb {
+	void (*eapol_send)(void *ctx, void *sta_ctx, u8 type, const u8 *data,
+			   size_t datalen);
+	void (*aaa_send)(void *ctx, void *sta_ctx, const u8 *data,
+			 size_t datalen);
+	void (*finished)(void *ctx, void *sta_ctx, int success, int preauth);
+	int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
+			    int phase2, struct eap_user *user);
+	int (*sta_entry_alive)(void *ctx, const u8 *addr);
+	void (*logger)(void *ctx, const u8 *addr, eapol_logger_level level,
+		       const char *txt);
+	void (*set_port_authorized)(void *ctx, void *sta_ctx, int authorized);
+	void (*abort_auth)(void *ctx, void *sta_ctx);
+	void (*tx_key)(void *ctx, void *sta_ctx);
+	void (*eapol_event)(void *ctx, void *sta_ctx, enum eapol_event type);
+};
+
+
+struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
+					     struct eapol_auth_cb *cb);
+void eapol_auth_deinit(struct eapol_authenticator *eapol);
+struct eapol_state_machine *
+eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
+		 int flags, const struct wpabuf *assoc_wps_ie, void *sta_ctx);
+void eapol_auth_free(struct eapol_state_machine *sm);
+void eapol_auth_step(struct eapol_state_machine *sm);
+void eapol_auth_dump_state(FILE *f, const char *prefix,
+			   struct eapol_state_machine *sm);
+int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx);
+
+#endif /* EAPOL_AUTH_SM_H */
diff --git a/contrib/wpa/hostapd/eapol_sm.h b/contrib/wpa/src/eapol_auth/eapol_auth_sm_i.h
similarity index 65%
rename from contrib/wpa/hostapd/eapol_sm.h
rename to contrib/wpa/src/eapol_auth/eapol_auth_sm_i.h
index 7a13e8e7c003..1000da4df148 100644
--- a/contrib/wpa/hostapd/eapol_sm.h
+++ b/contrib/wpa/src/eapol_auth/eapol_auth_sm_i.h
@@ -1,6 +1,6 @@
 /*
- * hostapd / IEEE 802.1X-2004 Authenticator - EAPOL state machine
- * Copyright (c) 2002-2007, Jouni Malinen 
+ * IEEE 802.1X-2004 Authenticator - EAPOL state machine (internal definitions)
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -12,10 +12,11 @@
  * See README and COPYING for more details.
  */
 
-#ifndef EAPOL_SM_H
-#define EAPOL_SM_H
+#ifndef EAPOL_AUTH_SM_I_H
+#define EAPOL_AUTH_SM_I_H
 
-#include "defs.h"
+#include "common/defs.h"
+#include "radius/radius.h"
 
 /* IEEE Std 802.1X-2004, Ch. 8.2 */
 
@@ -25,68 +26,6 @@ typedef enum { Unauthorized = 2, Authorized = 1 } PortState;
 typedef enum { Both = 0, In = 1 } ControlledDirection;
 typedef unsigned int Counter;
 
-struct eap_sm;
-
-struct radius_attr_data {
-	u8 *data;
-	size_t len;
-};
-
-struct radius_class_data {
-	struct radius_attr_data *attr;
-	size_t count;
-};
-
-
-struct eapol_auth_config {
-	int eap_reauth_period;
-	int wpa;
-	int individual_wep_key_len;
-	int eap_server;
-	void *ssl_ctx;
-	void *eap_sim_db_priv;
-	char *eap_req_id_text; /* a copy of this will be allocated */
-	size_t eap_req_id_text_len;
-	u8 *pac_opaque_encr_key;
-	u8 *eap_fast_a_id;
-	size_t eap_fast_a_id_len;
-	char *eap_fast_a_id_info;
-	int eap_fast_prov;
-	int pac_key_lifetime;
-	int pac_key_refresh_time;
-	int eap_sim_aka_result_ind;
-	int tnc;
-	struct wps_context *wps;
-
-	/*
-	 * Pointer to hostapd data. This is a temporary workaround for
-	 * transition phase and will be removed once IEEE 802.1X/EAPOL code is
-	 * separated more cleanly from rest of hostapd.
-	 */
-	struct hostapd_data *hapd;
-};
-
-struct eap_user;
-
-typedef enum {
-	EAPOL_LOGGER_DEBUG, EAPOL_LOGGER_INFO, EAPOL_LOGGER_WARNING
-} eapol_logger_level;
-
-struct eapol_auth_cb {
-	void (*eapol_send)(void *ctx, void *sta_ctx, u8 type, const u8 *data,
-			   size_t datalen);
-	void (*aaa_send)(void *ctx, void *sta_ctx, const u8 *data,
-			 size_t datalen);
-	void (*finished)(void *ctx, void *sta_ctx, int success, int preauth);
-	int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
-			    int phase2, struct eap_user *user);
-	int (*sta_entry_alive)(void *ctx, const u8 *addr);
-	void (*logger)(void *ctx, const u8 *addr, eapol_logger_level level,
-		       const char *txt);
-	void (*set_port_authorized)(void *ctx, void *sta_ctx, int authorized);
-	void (*abort_auth)(void *ctx, void *sta_ctx);
-	void (*tx_key)(void *ctx, void *sta_ctx);
-};
 
 /**
  * struct eapol_authenticator - Global EAPOL authenticator data
@@ -94,6 +33,9 @@ struct eapol_auth_cb {
 struct eapol_authenticator {
 	struct eapol_auth_config conf;
 	struct eapol_auth_cb cb;
+
+	u8 *default_wep_key;
+	u8 default_wep_key_idx;
 };
 
 
@@ -206,8 +148,6 @@ struct eapol_state_machine {
 
 	/* Other variables - not defined in IEEE 802.1X */
 	u8 addr[ETH_ALEN]; /* Supplicant address */
-#define EAPOL_SM_PREAUTH BIT(0)
-#define EAPOL_SM_WAIT_START BIT(1)
 	int flags; /* EAPOL_SM_* */
 
 	/* EAPOL/AAA <-> EAP full authenticator interface */
@@ -237,24 +177,7 @@ struct eapol_state_machine {
 
 	struct eapol_authenticator *eapol;
 
-	/* Somewhat nasty pointers to global hostapd and STA data to avoid
-	 * passing these to every function */
-	struct hostapd_data *hapd;
-	struct sta_info *sta;
+	void *sta; /* station context pointer to use in callbacks */
 };
 
-
-struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf,
-					     struct eapol_auth_cb *cb);
-void eapol_auth_deinit(struct eapol_authenticator *eapol);
-struct eapol_state_machine *
-eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
-		 int preauth, struct sta_info *sta);
-void eapol_auth_free(struct eapol_state_machine *sm);
-void eapol_auth_step(struct eapol_state_machine *sm);
-void eapol_auth_initialize(struct eapol_state_machine *sm);
-void eapol_auth_dump_state(FILE *f, const char *prefix,
-			   struct eapol_state_machine *sm);
-int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx);
-
-#endif /* EAPOL_SM_H */
+#endif /* EAPOL_AUTH_SM_I_H */
diff --git a/contrib/wpa/src/eapol_supp/Makefile b/contrib/wpa/src/eapol_supp/Makefile
index cffba620da04..9c41962fd7e1 100644
--- a/contrib/wpa/src/eapol_supp/Makefile
+++ b/contrib/wpa/src/eapol_supp/Makefile
@@ -2,7 +2,6 @@ all:
 	@echo Nothing to be made.
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
 	rm -f *~ *.o *.d
 
 install:
diff --git a/contrib/wpa/src/eapol_supp/eapol_supp_sm.c b/contrib/wpa/src/eapol_supp/eapol_supp_sm.c
index d163049ccef0..77cd564b0d43 100644
--- a/contrib/wpa/src/eapol_supp/eapol_supp_sm.c
+++ b/contrib/wpa/src/eapol_supp/eapol_supp_sm.c
@@ -15,14 +15,14 @@
 #include "includes.h"
 
 #include "common.h"
-#include "eapol_supp_sm.h"
-#include "eap_peer/eap.h"
-#include "eloop.h"
-#include "eapol_common.h"
-#include "md5.h"
-#include "rc4.h"
 #include "state_machine.h"
 #include "wpabuf.h"
+#include "eloop.h"
+#include "crypto/crypto.h"
+#include "crypto/md5.h"
+#include "common/eapol_common.h"
+#include "eap_peer/eap.h"
+#include "eapol_supp_sm.h"
 
 #define STATE_MACHINE_DATA struct eapol_sm
 #define STATE_MACHINE_DEBUG_PREFIX "EAPOL"
@@ -193,6 +193,8 @@ static void eapol_sm_txSuppRsp(struct eapol_sm *sm);
 static void eapol_sm_abortSupp(struct eapol_sm *sm);
 static void eapol_sm_abort_cached(struct eapol_sm *sm);
 static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx);
+static void eapol_sm_set_port_authorized(struct eapol_sm *sm);
+static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm);
 
 
 /* Port Timers state machine - implemented as a function that will be called
@@ -250,6 +252,7 @@ SM_STATE(SUPP_PAE, LOGOFF)
 	eapol_sm_txLogoff(sm);
 	sm->logoffSent = TRUE;
 	sm->suppPortStatus = Unauthorized;
+	eapol_sm_set_port_unauthorized(sm);
 }
 
 
@@ -260,6 +263,7 @@ SM_STATE(SUPP_PAE, DISCONNECTED)
 	sm->startCount = 0;
 	sm->logoffSent = FALSE;
 	sm->suppPortStatus = Unauthorized;
+	eapol_sm_set_port_unauthorized(sm);
 	sm->suppAbort = TRUE;
 
 	sm->unicast_key_received = FALSE;
@@ -315,6 +319,7 @@ SM_STATE(SUPP_PAE, HELD)
 	sm->heldWhile = sm->heldPeriod;
 	eapol_enable_timer_tick(sm);
 	sm->suppPortStatus = Unauthorized;
+	eapol_sm_set_port_unauthorized(sm);
 	sm->cb_status = EAPOL_CB_FAILURE;
 }
 
@@ -323,6 +328,7 @@ SM_STATE(SUPP_PAE, AUTHENTICATED)
 {
 	SM_ENTRY(SUPP_PAE, AUTHENTICATED);
 	sm->suppPortStatus = Authorized;
+	eapol_sm_set_port_authorized(sm);
 	sm->cb_status = EAPOL_CB_SUCCESS;
 }
 
@@ -338,6 +344,7 @@ SM_STATE(SUPP_PAE, S_FORCE_AUTH)
 {
 	SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
 	sm->suppPortStatus = Authorized;
+	eapol_sm_set_port_authorized(sm);
 	sm->sPortMode = ForceAuthorized;
 }
 
@@ -346,6 +353,7 @@ SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
 {
 	SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
 	sm->suppPortStatus = Unauthorized;
+	eapol_sm_set_port_unauthorized(sm);
 	sm->sPortMode = ForceUnauthorized;
 	eapol_sm_txLogoff(sm);
 }
@@ -862,6 +870,20 @@ static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx)
 }
 
 
+static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
+{
+	if (sm->ctx->port_cb)
+		sm->ctx->port_cb(sm->ctx->ctx, 1);
+}
+
+
+static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
+{
+	if (sm->ctx->port_cb)
+		sm->ctx->port_cb(sm->ctx->ctx, 0);
+}
+
+
 /**
  * eapol_sm_step - EAPOL state machine step function
  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
@@ -1456,6 +1478,7 @@ void eapol_sm_notify_cached(struct eapol_sm *sm)
 	wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL");
 	sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED;
 	sm->suppPortStatus = Authorized;
+	eapol_sm_set_port_authorized(sm);
 	sm->portValid = TRUE;
 	eap_notify_success(sm->eap);
 	eapol_sm_step(sm);
@@ -1492,6 +1515,7 @@ static void eapol_sm_abort_cached(struct eapol_sm *sm)
 	sm->cached_pmk = FALSE;
 	sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
 	sm->suppPortStatus = Unauthorized;
+	eapol_sm_set_port_unauthorized(sm);
 
 	/* Make sure we do not start sending EAPOL-Start frames first, but
 	 * instead move to RESTART state to start EAPOL authentication. */
@@ -1830,11 +1854,9 @@ struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
 	sm->authPeriod = 30;
 
 	os_memset(&conf, 0, sizeof(conf));
-#ifdef EAP_TLS_OPENSSL
 	conf.opensc_engine_path = ctx->opensc_engine_path;
 	conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
 	conf.pkcs11_module_path = ctx->pkcs11_module_path;
-#endif /* EAP_TLS_OPENSSL */
 	conf.wps = ctx->wps;
 
 	sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
diff --git a/contrib/wpa/src/eapol_supp/eapol_supp_sm.h b/contrib/wpa/src/eapol_supp/eapol_supp_sm.h
index 57d7bc1ab12e..1d2a32bb7cbf 100644
--- a/contrib/wpa/src/eapol_supp/eapol_supp_sm.h
+++ b/contrib/wpa/src/eapol_supp/eapol_supp_sm.h
@@ -15,7 +15,7 @@
 #ifndef EAPOL_SUPP_SM_H
 #define EAPOL_SUPP_SM_H
 
-#include "defs.h"
+#include "common/defs.h"
 
 typedef enum { Unauthorized, Authorized } PortStatus;
 typedef enum { Auto, ForceUnauthorized, ForceAuthorized } PortControl;
@@ -173,7 +173,6 @@ struct eapol_ctx {
 	 */
 	void (*aborted_cached)(void *ctx);
 
-#ifdef EAP_TLS_OPENSSL
 	/**
 	 * opensc_engine_path - Path to the OpenSSL engine for opensc
 	 *
@@ -198,7 +197,6 @@ struct eapol_ctx {
 	 * module is not loaded.
 	 */
 	const char *pkcs11_module_path;
-#endif /* EAP_TLS_OPENSSL */
 
 	/**
 	 * wps - WPS context data
@@ -215,6 +213,13 @@ struct eapol_ctx {
 	 */
 	void (*eap_param_needed)(void *ctx, const char *field,
 				 const char *txt);
+
+	/**
+	 * port_cb - Set port authorized/unauthorized callback (optional)
+	 * @ctx: Callback context (ctx)
+	 * @authorized: Whether the supplicant port is now in authorized state
+	 */
+	void (*port_cb)(void *ctx, int authorized);
 };
 
 
diff --git a/contrib/wpa/src/hlr_auc_gw/milenage.c b/contrib/wpa/src/hlr_auc_gw/milenage.c
deleted file mode 100644
index 0ce5ef3ff671..000000000000
--- a/contrib/wpa/src/hlr_auc_gw/milenage.c
+++ /dev/null
@@ -1,1142 +0,0 @@
-/*
- * 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
- * Copyright (c) 2006-2007 
- *
- * 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 file implements an example authentication algorithm defined for 3GPP
- * AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow
- * EAP-AKA to be tested properly with real USIM cards.
- *
- * This implementations assumes that the r1..r5 and c1..c5 constants defined in
- * TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00,
- * c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to
- * be AES (Rijndael).
- */
-
-#include "includes.h"
-
-#include "common.h"
-#include "milenage.h"
-#include "aes_wrap.h"
-
-
-/**
- * milenage_f1 - Milenage f1 and f1* algorithms
- * @opc: OPc = 128-bit value derived from OP and K
- * @k: K = 128-bit subscriber key
- * @_rand: RAND = 128-bit random challenge
- * @sqn: SQN = 48-bit sequence number
- * @amf: AMF = 16-bit authentication management field
- * @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL
- * @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL
- * Returns: 0 on success, -1 on failure
- */
-static int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
-		       const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s)
-{
-	u8 tmp1[16], tmp2[16], tmp3[16];
-	int i;
-
-	/* tmp1 = TEMP = E_K(RAND XOR OP_C) */
-	for (i = 0; i < 16; i++)
-		tmp1[i] = _rand[i] ^ opc[i];
-	if (aes_128_encrypt_block(k, tmp1, tmp1))
-		return -1;
-
-	/* tmp2 = IN1 = SQN || AMF || SQN || AMF */
-	os_memcpy(tmp2, sqn, 6);
-	os_memcpy(tmp2 + 6, amf, 2);
-	os_memcpy(tmp2 + 8, tmp2, 8);
-
-	/* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */
-
-	/* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */
-	for (i = 0; i < 16; i++)
-		tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i];
-	/* XOR with TEMP = E_K(RAND XOR OP_C) */
-	for (i = 0; i < 16; i++)
-		tmp3[i] ^= tmp1[i];
-	/* XOR with c1 (= ..00, i.e., NOP) */
-
-	/* f1 || f1* = E_K(tmp3) XOR OP_c */
-	if (aes_128_encrypt_block(k, tmp3, tmp1))
-		return -1;
-	for (i = 0; i < 16; i++)
-		tmp1[i] ^= opc[i];
-	if (mac_a)
-		os_memcpy(mac_a, tmp1, 8); /* f1 */
-	if (mac_s)
-		os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */
-	return 0;
-}
-
-
-/**
- * milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
- * @opc: OPc = 128-bit value derived from OP and K
- * @k: K = 128-bit subscriber key
- * @_rand: RAND = 128-bit random challenge
- * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
- * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
- * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
- * @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL
- * @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL
- * Returns: 0 on success, -1 on failure
- */
-static int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
-			  u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar)
-{
-	u8 tmp1[16], tmp2[16], tmp3[16];
-	int i;
-
-	/* tmp2 = TEMP = E_K(RAND XOR OP_C) */
-	for (i = 0; i < 16; i++)
-		tmp1[i] = _rand[i] ^ opc[i];
-	if (aes_128_encrypt_block(k, tmp1, tmp2))
-		return -1;
-
-	/* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */
-	/* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */
-	/* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */
-	/* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */
-
-	/* f2 and f5 */
-	/* rotate by r2 (= 0, i.e., NOP) */
-	for (i = 0; i < 16; i++)
-		tmp1[i] = tmp2[i] ^ opc[i];
-	tmp1[15] ^= 1; /* XOR c2 (= ..01) */
-	/* f5 || f2 = E_K(tmp1) XOR OP_c */
-	if (aes_128_encrypt_block(k, tmp1, tmp3))
-		return -1;
-	for (i = 0; i < 16; i++)
-		tmp3[i] ^= opc[i];
-	if (res)
-		os_memcpy(res, tmp3 + 8, 8); /* f2 */
-	if (ak)
-		os_memcpy(ak, tmp3, 6); /* f5 */
-
-	/* f3 */
-	if (ck) {
-		/* rotate by r3 = 0x20 = 4 bytes */
-		for (i = 0; i < 16; i++)
-			tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i];
-		tmp1[15] ^= 2; /* XOR c3 (= ..02) */
-		if (aes_128_encrypt_block(k, tmp1, ck))
-			return -1;
-		for (i = 0; i < 16; i++)
-			ck[i] ^= opc[i];
-	}
-
-	/* f4 */
-	if (ik) {
-		/* rotate by r4 = 0x40 = 8 bytes */
-		for (i = 0; i < 16; i++)
-			tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i];
-		tmp1[15] ^= 4; /* XOR c4 (= ..04) */
-		if (aes_128_encrypt_block(k, tmp1, ik))
-			return -1;
-		for (i = 0; i < 16; i++)
-			ik[i] ^= opc[i];
-	}
-
-	/* f5* */
-	if (akstar) {
-		/* rotate by r5 = 0x60 = 12 bytes */
-		for (i = 0; i < 16; i++)
-			tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i];
-		tmp1[15] ^= 8; /* XOR c5 (= ..08) */
-		if (aes_128_encrypt_block(k, tmp1, tmp1))
-			return -1;
-		for (i = 0; i < 6; i++)
-			akstar[i] = tmp1[i] ^ opc[i];
-	}
-
-	return 0;
-}
-
-
-/**
- * milenage_generate - Generate AKA AUTN,IK,CK,RES
- * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
- * @amf: AMF = 16-bit authentication management field
- * @k: K = 128-bit subscriber key
- * @sqn: SQN = 48-bit sequence number
- * @_rand: RAND = 128-bit random challenge
- * @autn: Buffer for AUTN = 128-bit authentication token
- * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
- * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
- * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
- * @res_len: Max length for res; set to used length or 0 on failure
- */
-void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
-		       const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik,
-		       u8 *ck, u8 *res, size_t *res_len)
-{
-	int i;
-	u8 mac_a[8], ak[6];
-
-	if (*res_len < 8) {
-		*res_len = 0;
-		return;
-	}
-	if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) ||
-	    milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) {
-		*res_len = 0;
-		return;
-	}
-	*res_len = 8;
-
-	/* AUTN = (SQN ^ AK) || AMF || MAC */
-	for (i = 0; i < 6; i++)
-		autn[i] = sqn[i] ^ ak[i];
-	os_memcpy(autn + 6, amf, 2);
-	os_memcpy(autn + 8, mac_a, 8);
-}
-
-
-/**
- * milenage_auts - Milenage AUTS validation
- * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
- * @k: K = 128-bit subscriber key
- * @_rand: RAND = 128-bit random challenge
- * @auts: AUTS = 112-bit authentication token from client
- * @sqn: Buffer for SQN = 48-bit sequence number
- * Returns: 0 = success (sqn filled), -1 on failure
- */
-int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
-		  u8 *sqn)
-{
-	u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
-	u8 ak[6], mac_s[8];
-	int i;
-
-	if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
-		return -1;
-	for (i = 0; i < 6; i++)
-		sqn[i] = auts[i] ^ ak[i];
-	if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) ||
-	    memcmp(mac_s, auts + 6, 8) != 0)
-		return -1;
-	return 0;
-}
-
-
-/**
- * gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet
- * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
- * @k: K = 128-bit subscriber key
- * @_rand: RAND = 128-bit random challenge
- * @sres: Buffer for SRES = 32-bit SRES
- * @kc: Buffer for Kc = 64-bit Kc
- * Returns: 0 on success, -1 on failure
- */
-int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc)
-{
-	u8 res[8], ck[16], ik[16];
-	int i;
-
-	if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL))
-		return -1;
-
-	for (i = 0; i < 8; i++)
-		kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8];
-
-#ifdef GSM_MILENAGE_ALT_SRES
-	os_memcpy(sres, res, 4);
-#else /* GSM_MILENAGE_ALT_SRES */
-	for (i = 0; i < 4; i++)
-		sres[i] = res[i] ^ res[i + 4];
-#endif /* GSM_MILENAGE_ALT_SRES */
-	return 0;
-}
-
-
-/**
- * milenage_generate - Generate AKA AUTN,IK,CK,RES
- * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
- * @k: K = 128-bit subscriber key
- * @sqn: SQN = 48-bit sequence number
- * @_rand: RAND = 128-bit random challenge
- * @autn: AUTN = 128-bit authentication token
- * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
- * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
- * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
- * @res_len: Variable that will be set to RES length
- * @auts: 112-bit buffer for AUTS
- * Returns: 0 on success, -1 on failure, or -2 on synchronization failure
- */
-int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
-		   const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
-		   u8 *auts)
-{
-	int i;
-	u8 mac_a[8], ak[6], rx_sqn[6];
-	const u8 *amf;
-
-	wpa_hexdump(MSG_DEBUG, "Milenage: AUTN", autn, 16);
-	wpa_hexdump(MSG_DEBUG, "Milenage: RAND", _rand, 16);
-
-	if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
-		return -1;
-
-	*res_len = 8;
-	wpa_hexdump_key(MSG_DEBUG, "Milenage: RES", res, *res_len);
-	wpa_hexdump_key(MSG_DEBUG, "Milenage: CK", ck, 16);
-	wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 16);
-	wpa_hexdump_key(MSG_DEBUG, "Milenage: AK", ak, 6);
-
-	/* AUTN = (SQN ^ AK) || AMF || MAC */
-	for (i = 0; i < 6; i++)
-		rx_sqn[i] = autn[i] ^ ak[i];
-	wpa_hexdump(MSG_DEBUG, "Milenage: SQN", rx_sqn, 6);
-
-	if (os_memcmp(rx_sqn, sqn, 6) <= 0) {
-		u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
-		if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
-			return -1;
-		wpa_hexdump_key(MSG_DEBUG, "Milenage: AK*", ak, 6);
-		for (i = 0; i < 6; i++)
-			auts[i] = sqn[i] ^ ak[i];
-		if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6))
-			return -1;
-		wpa_hexdump(MSG_DEBUG, "Milenage: AUTS", auts, 14);
-		return -2;
-	}
-
-	amf = autn + 6;
-	wpa_hexdump(MSG_DEBUG, "Milenage: AMF", amf, 2);
-	if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL))
-		return -1;
-
-	wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8);
-
-	if (os_memcmp(mac_a, autn + 8, 8) != 0) {
-		wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch");
-		wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A",
-			    autn + 8, 8);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-#ifdef TEST_MAIN_MILENAGE
-
-extern int wpa_debug_level;
-
-
-/**
- * milenage_opc - Determine OPc from OP and K
- * @op: OP = 128-bit operator variant algorithm configuration field
- * @k: K = 128-bit subscriber key
- * @opc: Buffer for OPc = 128-bit value derived from OP and K
- */
-static void milenage_opc(const u8 *op, const u8 *k, u8 *opc)
-{
-	int i;
-	/* OP_C = OP XOR E_K(OP) */
-	aes_128_encrypt_block(k, op, opc);
-	for (i = 0; i < 16; i++)
-		opc[i] ^= op[i];
-}
-
-
-struct gsm_milenage_test_set {
-	u8 ki[16];
-	u8 rand[16];
-	u8 opc[16];
-	u8 sres1[4];
-	u8 sres2[4];
-	u8 kc[8];
-};
-
-static const struct gsm_milenage_test_set gsm_test_sets[] =
-{
-	{
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 1 */
-		{ 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f,
-		  0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc },
-		{ 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d,
-		  0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 },
-		{ 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e,
-		  0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf },
-		{ 0x46, 0xf8, 0x41, 0x6a },
-		{ 0xa5, 0x42, 0x11, 0xd5 },
-		{ 0xea, 0xe4, 0xbe, 0x82, 0x3a, 0xf9, 0xa0, 0x8b }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 2 */
-		{ 0xfe, 0xc8, 0x6b, 0xa6, 0xeb, 0x70, 0x7e, 0xd0,
-		  0x89, 0x05, 0x75, 0x7b, 0x1b, 0xb4, 0x4b, 0x8f },
-		{ 0x9f, 0x7c, 0x8d, 0x02, 0x1a, 0xcc, 0xf4, 0xdb,
-		  0x21, 0x3c, 0xcf, 0xf0, 0xc7, 0xf7, 0x1a, 0x6a },
-		{ 0x10, 0x06, 0x02, 0x0f, 0x0a, 0x47, 0x8b, 0xf6,
-		  0xb6, 0x99, 0xf1, 0x5c, 0x06, 0x2e, 0x42, 0xb3 },
-		{ 0x8c, 0x30, 0x8a, 0x5e },
-		{ 0x80, 0x11, 0xc4, 0x8c },
-		{ 0xaa, 0x01, 0x73, 0x9b, 0x8c, 0xaa, 0x97, 0x6d }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 3 */
-		{ 0x9e, 0x59, 0x44, 0xae, 0xa9, 0x4b, 0x81, 0x16,
-		  0x5c, 0x82, 0xfb, 0xf9, 0xf3, 0x2d, 0xb7, 0x51 },
-		{ 0xce, 0x83, 0xdb, 0xc5, 0x4a, 0xc0, 0x27, 0x4a,
-		  0x15, 0x7c, 0x17, 0xf8, 0x0d, 0x01, 0x7b, 0xd6 },
-		{ 0xa6, 0x4a, 0x50, 0x7a, 0xe1, 0xa2, 0xa9, 0x8b,
-		  0xb8, 0x8e, 0xb4, 0x21, 0x01, 0x35, 0xdc, 0x87 },
-		{ 0xcf, 0xbc, 0xe3, 0xfe },
-		{ 0xf3, 0x65, 0xcd, 0x68 },
-		{ 0x9a, 0x8e, 0xc9, 0x5f, 0x40, 0x8c, 0xc5, 0x07 }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 4 */
-		{ 0x4a, 0xb1, 0xde, 0xb0, 0x5c, 0xa6, 0xce, 0xb0,
-		  0x51, 0xfc, 0x98, 0xe7, 0x7d, 0x02, 0x6a, 0x84 },
-		{ 0x74, 0xb0, 0xcd, 0x60, 0x31, 0xa1, 0xc8, 0x33,
-		  0x9b, 0x2b, 0x6c, 0xe2, 0xb8, 0xc4, 0xa1, 0x86 },
-		{ 0xdc, 0xf0, 0x7c, 0xbd, 0x51, 0x85, 0x52, 0x90,
-		  0xb9, 0x2a, 0x07, 0xa9, 0x89, 0x1e, 0x52, 0x3e },
-		{ 0x96, 0x55, 0xe2, 0x65 },
-		{ 0x58, 0x60, 0xfc, 0x1b },
-		{ 0xcd, 0xc1, 0xdc, 0x08, 0x41, 0xb8, 0x1a, 0x22 }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 5 */
-		{ 0x6c, 0x38, 0xa1, 0x16, 0xac, 0x28, 0x0c, 0x45,
-		  0x4f, 0x59, 0x33, 0x2e, 0xe3, 0x5c, 0x8c, 0x4f },
-		{ 0xee, 0x64, 0x66, 0xbc, 0x96, 0x20, 0x2c, 0x5a,
-		  0x55, 0x7a, 0xbb, 0xef, 0xf8, 0xba, 0xbf, 0x63 },
-		{ 0x38, 0x03, 0xef, 0x53, 0x63, 0xb9, 0x47, 0xc6,
-		  0xaa, 0xa2, 0x25, 0xe5, 0x8f, 0xae, 0x39, 0x34 },
-		{ 0x13, 0x68, 0x8f, 0x17 },
-		{ 0x16, 0xc8, 0x23, 0x3f },
-		{ 0xdf, 0x75, 0xbc, 0x5e, 0xa8, 0x99, 0x87, 0x9f }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 6 */
-		{ 0x2d, 0x60, 0x9d, 0x4d, 0xb0, 0xac, 0x5b, 0xf0,
-		  0xd2, 0xc0, 0xde, 0x26, 0x70, 0x14, 0xde, 0x0d },
-		{ 0x19, 0x4a, 0xa7, 0x56, 0x01, 0x38, 0x96, 0xb7,
-		  0x4b, 0x4a, 0x2a, 0x3b, 0x0a, 0xf4, 0x53, 0x9e },
-		{ 0xc3, 0x5a, 0x0a, 0xb0, 0xbc, 0xbf, 0xc9, 0x25,
-		  0x2c, 0xaf, 0xf1, 0x5f, 0x24, 0xef, 0xbd, 0xe0 },
-		{ 0x55, 0x3d, 0x00, 0xb3 },
-		{ 0x8c, 0x25, 0xa1, 0x6c },
-		{ 0x84, 0xb4, 0x17, 0xae, 0x3a, 0xea, 0xb4, 0xf3 }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 7 */
-		{ 0xa5, 0x30, 0xa7, 0xfe, 0x42, 0x8f, 0xad, 0x10,
-		  0x82, 0xc4, 0x5e, 0xdd, 0xfc, 0xe1, 0x38, 0x84 },
-		{ 0x3a, 0x4c, 0x2b, 0x32, 0x45, 0xc5, 0x0e, 0xb5,
-		  0xc7, 0x1d, 0x08, 0x63, 0x93, 0x95, 0x76, 0x4d },
-		{ 0x27, 0x95, 0x3e, 0x49, 0xbc, 0x8a, 0xf6, 0xdc,
-		  0xc6, 0xe7, 0x30, 0xeb, 0x80, 0x28, 0x6b, 0xe3 },
-		{ 0x59, 0xf1, 0xa4, 0x4a },
-		{ 0xa6, 0x32, 0x41, 0xe1 },
-		{ 0x3b, 0x4e, 0x24, 0x4c, 0xdc, 0x60, 0xce, 0x03 }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 8 */
-		{ 0xd9, 0x15, 0x1c, 0xf0, 0x48, 0x96, 0xe2, 0x58,
-		  0x30, 0xbf, 0x2e, 0x08, 0x26, 0x7b, 0x83, 0x60 },
-		{ 0xf7, 0x61, 0xe5, 0xe9, 0x3d, 0x60, 0x3f, 0xeb,
-		  0x73, 0x0e, 0x27, 0x55, 0x6c, 0xb8, 0xa2, 0xca },
-		{ 0xc4, 0xc9, 0x3e, 0xff, 0xe8, 0xa0, 0x81, 0x38,
-		  0xc2, 0x03, 0xd4, 0xc2, 0x7c, 0xe4, 0xe3, 0xd9 },
-		{ 0x50, 0x58, 0x88, 0x61 },
-		{ 0x4a, 0x90, 0xb2, 0x17 },
-		{ 0x8d, 0x4e, 0xc0, 0x1d, 0xe5, 0x97, 0xac, 0xfe }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 9 */
-		{ 0xa0, 0xe2, 0x97, 0x1b, 0x68, 0x22, 0xe8, 0xd3,
-		  0x54, 0xa1, 0x8c, 0xc2, 0x35, 0x62, 0x4e, 0xcb },
-		{ 0x08, 0xef, 0xf8, 0x28, 0xb1, 0x3f, 0xdb, 0x56,
-		  0x27, 0x22, 0xc6, 0x5c, 0x7f, 0x30, 0xa9, 0xb2 },
-		{ 0x82, 0xa2, 0x6f, 0x22, 0xbb, 0xa9, 0xe9, 0x48,
-		  0x8f, 0x94, 0x9a, 0x10, 0xd9, 0x8e, 0x9c, 0xc4 },
-		{ 0xcd, 0xe6, 0xb0, 0x27 },
-		{ 0x4b, 0xc2, 0x21, 0x2d },
-		{ 0xd8, 0xde, 0xbc, 0x4f, 0xfb, 0xcd, 0x60, 0xaa }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 10 */
-		{ 0x0d, 0xa6, 0xf7, 0xba, 0x86, 0xd5, 0xea, 0xc8,
-		  0xa1, 0x9c, 0xf5, 0x63, 0xac, 0x58, 0x64, 0x2d },
-		{ 0x67, 0x9a, 0xc4, 0xdb, 0xac, 0xd7, 0xd2, 0x33,
-		  0xff, 0x9d, 0x68, 0x06, 0xf4, 0x14, 0x9c, 0xe3 },
-		{ 0x0d, 0xb1, 0x07, 0x1f, 0x87, 0x67, 0x56, 0x2c,
-		  0xa4, 0x3a, 0x0a, 0x64, 0xc4, 0x1e, 0x8d, 0x08 },
-		{ 0x02, 0xd1, 0x3a, 0xcd },
-		{ 0x6f, 0xc3, 0x0f, 0xee },
-		{ 0xf0, 0xea, 0xa5, 0x0a, 0x1e, 0xdc, 0xeb, 0xb7 }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 11 */
-		{ 0x77, 0xb4, 0x58, 0x43, 0xc8, 0x8e, 0x58, 0xc1,
-		  0x0d, 0x20, 0x26, 0x84, 0x51, 0x5e, 0xd4, 0x30 },
-		{ 0x4c, 0x47, 0xeb, 0x30, 0x76, 0xdc, 0x55, 0xfe,
-		  0x51, 0x06, 0xcb, 0x20, 0x34, 0xb8, 0xcd, 0x78 },
-		{ 0xd4, 0x83, 0xaf, 0xae, 0x56, 0x24, 0x09, 0xa3,
-		  0x26, 0xb5, 0xbb, 0x0b, 0x20, 0xc4, 0xd7, 0x62 },
-		{ 0x44, 0x38, 0x9d, 0x01 },
-		{ 0xae, 0xfa, 0x35, 0x7b },
-		{ 0x82, 0xdb, 0xab, 0x7f, 0x83, 0xf0, 0x63, 0xda }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 12 */
-		{ 0x72, 0x9b, 0x17, 0x72, 0x92, 0x70, 0xdd, 0x87,
-		  0xcc, 0xdf, 0x1b, 0xfe, 0x29, 0xb4, 0xe9, 0xbb },
-		{ 0x31, 0x1c, 0x4c, 0x92, 0x97, 0x44, 0xd6, 0x75,
-		  0xb7, 0x20, 0xf3, 0xb7, 0xe9, 0xb1, 0xcb, 0xd0 },
-		{ 0x22, 0x8c, 0x2f, 0x2f, 0x06, 0xac, 0x32, 0x68,
-		  0xa9, 0xe6, 0x16, 0xee, 0x16, 0xdb, 0x4b, 0xa1 },
-		{ 0x03, 0xe0, 0xfd, 0x84 },
-		{ 0x98, 0xdb, 0xbd, 0x09 },
-		{ 0x3c, 0x66, 0xcb, 0x98, 0xca, 0xb2, 0xd3, 0x3d }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 13 */
-		{ 0xd3, 0x2d, 0xd2, 0x3e, 0x89, 0xdc, 0x66, 0x23,
-		  0x54, 0xca, 0x12, 0xeb, 0x79, 0xdd, 0x32, 0xfa },
-		{ 0xcf, 0x7d, 0x0a, 0xb1, 0xd9, 0x43, 0x06, 0x95,
-		  0x0b, 0xf1, 0x20, 0x18, 0xfb, 0xd4, 0x68, 0x87 },
-		{ 0xd2, 0x2a, 0x4b, 0x41, 0x80, 0xa5, 0x32, 0x57,
-		  0x08, 0xa5, 0xff, 0x70, 0xd9, 0xf6, 0x7e, 0xc7 },
-		{ 0xbe, 0x73, 0xb3, 0xdc },
-		{ 0xaf, 0x4a, 0x41, 0x1e },
-		{ 0x96, 0x12, 0xb5, 0xd8, 0x8a, 0x41, 0x30, 0xbb }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 14 */
-		{ 0xaf, 0x7c, 0x65, 0xe1, 0x92, 0x72, 0x21, 0xde,
-		  0x59, 0x11, 0x87, 0xa2, 0xc5, 0x98, 0x7a, 0x53 },
-		{ 0x1f, 0x0f, 0x85, 0x78, 0x46, 0x4f, 0xd5, 0x9b,
-		  0x64, 0xbe, 0xd2, 0xd0, 0x94, 0x36, 0xb5, 0x7a },
-		{ 0xa4, 0xcf, 0x5c, 0x81, 0x55, 0xc0, 0x8a, 0x7e,
-		  0xff, 0x41, 0x8e, 0x54, 0x43, 0xb9, 0x8e, 0x55 },
-		{ 0x8f, 0xe0, 0x19, 0xc7 },
-		{ 0x7b, 0xff, 0xa5, 0xc2 },
-		{ 0x75, 0xa1, 0x50, 0xdf, 0x3c, 0x6a, 0xed, 0x08 }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 15 */
-		{ 0x5b, 0xd7, 0xec, 0xd3, 0xd3, 0x12, 0x7a, 0x41,
-		  0xd1, 0x25, 0x39, 0xbe, 0xd4, 0xe7, 0xcf, 0x71 },
-		{ 0x59, 0xb7, 0x5f, 0x14, 0x25, 0x1c, 0x75, 0x03,
-		  0x1d, 0x0b, 0xcb, 0xac, 0x1c, 0x2c, 0x04, 0xc7 },
-		{ 0x76, 0x08, 0x9d, 0x3c, 0x0f, 0xf3, 0xef, 0xdc,
-		  0x6e, 0x36, 0x72, 0x1d, 0x4f, 0xce, 0xb7, 0x47 },
-		{ 0x27, 0x20, 0x2b, 0x82 },
-		{ 0x7e, 0x3f, 0x44, 0xc7 },
-		{ 0xb7, 0xf9, 0x2e, 0x42, 0x6a, 0x36, 0xfe, 0xc5 }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 16 */
-		{ 0x6c, 0xd1, 0xc6, 0xce, 0xb1, 0xe0, 0x1e, 0x14,
-		  0xf1, 0xb8, 0x23, 0x16, 0xa9, 0x0b, 0x7f, 0x3d },
-		{ 0xf6, 0x9b, 0x78, 0xf3, 0x00, 0xa0, 0x56, 0x8b,
-		  0xce, 0x9f, 0x0c, 0xb9, 0x3c, 0x4b, 0xe4, 0xc9 },
-		{ 0xa2, 0x19, 0xdc, 0x37, 0xf1, 0xdc, 0x7d, 0x66,
-		  0x73, 0x8b, 0x58, 0x43, 0xc7, 0x99, 0xf2, 0x06 },
-		{ 0xdd, 0xd7, 0xef, 0xe6 },
-		{ 0x70, 0xf6, 0xbd, 0xb9 },
-		{ 0x88, 0xd9, 0xde, 0x10, 0xa2, 0x20, 0x04, 0xc5 }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 17 */
-		{ 0xb7, 0x3a, 0x90, 0xcb, 0xcf, 0x3a, 0xfb, 0x62,
-		  0x2d, 0xba, 0x83, 0xc5, 0x8a, 0x84, 0x15, 0xdf },
-		{ 0xb1, 0x20, 0xf1, 0xc1, 0xa0, 0x10, 0x2a, 0x2f,
-		  0x50, 0x7d, 0xd5, 0x43, 0xde, 0x68, 0x28, 0x1f },
-		{ 0xdf, 0x0c, 0x67, 0x86, 0x8f, 0xa2, 0x5f, 0x74,
-		  0x8b, 0x70, 0x44, 0xc6, 0xe7, 0xc2, 0x45, 0xb8 },
-		{ 0x67, 0xe4, 0xff, 0x3f },
-		{ 0x47, 0x9d, 0xd2, 0x5c },
-		{ 0xa8, 0x19, 0xe5, 0x77, 0xa8, 0xd6, 0x17, 0x5b }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 18 */
-		{ 0x51, 0x22, 0x25, 0x02, 0x14, 0xc3, 0x3e, 0x72,
-		  0x3a, 0x5d, 0xd5, 0x23, 0xfc, 0x14, 0x5f, 0xc0 },
-		{ 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
-		  0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
-		{ 0x98, 0x1d, 0x46, 0x4c, 0x7c, 0x52, 0xeb, 0x6e,
-		  0x50, 0x36, 0x23, 0x49, 0x84, 0xad, 0x0b, 0xcf },
-		{ 0x8a, 0x3b, 0x8d, 0x17 },
-		{ 0x28, 0xd7, 0xb0, 0xf2 },
-		{ 0x9a, 0x8d, 0x0e, 0x88, 0x3f, 0xf0, 0x88, 0x7a }
-	}, {
-		/* 3GPP TS 55.205 v6.0.0 - Test Set 19 */
-		{ 0x90, 0xdc, 0xa4, 0xed, 0xa4, 0x5b, 0x53, 0xcf,
-		  0x0f, 0x12, 0xd7, 0xc9, 0xc3, 0xbc, 0x6a, 0x89 },
-		{ 0x9f, 0xdd, 0xc7, 0x20, 0x92, 0xc6, 0xad, 0x03,
-		  0x6b, 0x6e, 0x46, 0x47, 0x89, 0x31, 0x5b, 0x78 },
-		{ 0xcb, 0x9c, 0xcc, 0xc4, 0xb9, 0x25, 0x8e, 0x6d,
-		  0xca, 0x47, 0x60, 0x37, 0x9f, 0xb8, 0x25, 0x81 },
-		{ 0xdf, 0x58, 0x52, 0x2f },
-		{ 0xa9, 0x51, 0x00, 0xe2 },
-		{ 0xed, 0x29, 0xb2, 0xf1, 0xc2, 0x7f, 0x9f, 0x34 }
-	}
-};
-
-#define NUM_GSM_TESTS (sizeof(gsm_test_sets) / sizeof(gsm_test_sets[0]))
-
-
-struct milenage_test_set {
-	u8 k[16];
-	u8 rand[16];
-	u8 sqn[6];
-	u8 amf[2];
-	u8 op[16];
-	u8 opc[16];
-	u8 f1[8];
-	u8 f1star[8];
-	u8 f2[8];
-	u8 f3[16];
-	u8 f4[16];
-	u8 f5[6];
-	u8 f5star[6];
-};
-
-static const struct milenage_test_set test_sets[] =
-{
-	{
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.1 Test Set 1 */
-		{ 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f,
-		  0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc },
-		{ 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d,
-		  0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 },
-		{ 0xff, 0x9b, 0xb4, 0xd0, 0xb6, 0x07 },
-		{ 0xb9, 0xb9 },
-		{ 0xcd, 0xc2, 0x02, 0xd5, 0x12, 0x3e, 0x20, 0xf6,
-		  0x2b, 0x6d, 0x67, 0x6a, 0xc7, 0x2c, 0xb3, 0x18 },
-		{ 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e,
-		  0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf },
-		{ 0x4a, 0x9f, 0xfa, 0xc3, 0x54, 0xdf, 0xaf, 0xb3 },
-		{ 0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9 },
-		{ 0xa5, 0x42, 0x11, 0xd5, 0xe3, 0xba, 0x50, 0xbf },
-		{ 0xb4, 0x0b, 0xa9, 0xa3, 0xc5, 0x8b, 0x2a, 0x05,
-		  0xbb, 0xf0, 0xd9, 0x87, 0xb2, 0x1b, 0xf8, 0xcb },
-		{ 0xf7, 0x69, 0xbc, 0xd7, 0x51, 0x04, 0x46, 0x04,
-		  0x12, 0x76, 0x72, 0x71, 0x1c, 0x6d, 0x34, 0x41 },
-		{ 0xaa, 0x68, 0x9c, 0x64, 0x83, 0x70 },
-		{ 0x45, 0x1e, 0x8b, 0xec, 0xa4, 0x3b }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.2 Test Set 2 */
-		{ 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f,
-		  0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc },
-		{ 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d,
-		  0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 },
-		{ 0xff, 0x9b, 0xb4, 0xd0, 0xb6, 0x07 },
-		{ 0xb9, 0xb9 },
-		{ 0xcd, 0xc2, 0x02, 0xd5, 0x12, 0x3e, 0x20, 0xf6,
-		  0x2b, 0x6d, 0x67, 0x6a, 0xc7, 0x2c, 0xb3, 0x18 },
-		{ 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e,
-		  0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf },
-		{ 0x4a, 0x9f, 0xfa, 0xc3, 0x54, 0xdf, 0xaf, 0xb3 },
-		{ 0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9 },
-		{ 0xa5, 0x42, 0x11, 0xd5, 0xe3, 0xba, 0x50, 0xbf },
-		{ 0xb4, 0x0b, 0xa9, 0xa3, 0xc5, 0x8b, 0x2a, 0x05,
-		  0xbb, 0xf0, 0xd9, 0x87, 0xb2, 0x1b, 0xf8, 0xcb },
-		{ 0xf7, 0x69, 0xbc, 0xd7, 0x51, 0x04, 0x46, 0x04,
-		  0x12, 0x76, 0x72, 0x71, 0x1c, 0x6d, 0x34, 0x41 },
-		{ 0xaa, 0x68, 0x9c, 0x64, 0x83, 0x70 },
-		{ 0x45, 0x1e, 0x8b, 0xec, 0xa4, 0x3b }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.3 Test Set 3 */
-		{ 0xfe, 0xc8, 0x6b, 0xa6, 0xeb, 0x70, 0x7e, 0xd0,
-		  0x89, 0x05, 0x75, 0x7b, 0x1b, 0xb4, 0x4b, 0x8f },
-		{ 0x9f, 0x7c, 0x8d, 0x02, 0x1a, 0xcc, 0xf4, 0xdb,
-		  0x21, 0x3c, 0xcf, 0xf0, 0xc7, 0xf7, 0x1a, 0x6a },
-		{ 0x9d, 0x02, 0x77, 0x59, 0x5f, 0xfc },
-		{ 0x72, 0x5c },
-		{ 0xdb, 0xc5, 0x9a, 0xdc, 0xb6, 0xf9, 0xa0, 0xef,
-		  0x73, 0x54, 0x77, 0xb7, 0xfa, 0xdf, 0x83, 0x74 },
-		{ 0x10, 0x06, 0x02, 0x0f, 0x0a, 0x47, 0x8b, 0xf6,
-		  0xb6, 0x99, 0xf1, 0x5c, 0x06, 0x2e, 0x42, 0xb3 },
-		{ 0x9c, 0xab, 0xc3, 0xe9, 0x9b, 0xaf, 0x72, 0x81 },
-		{ 0x95, 0x81, 0x4b, 0xa2, 0xb3, 0x04, 0x43, 0x24 },
-		{ 0x80, 0x11, 0xc4, 0x8c, 0x0c, 0x21, 0x4e, 0xd2 },
-		{ 0x5d, 0xbd, 0xbb, 0x29, 0x54, 0xe8, 0xf3, 0xcd,
-		  0xe6, 0x65, 0xb0, 0x46, 0x17, 0x9a, 0x50, 0x98 },
-		{ 0x59, 0xa9, 0x2d, 0x3b, 0x47, 0x6a, 0x04, 0x43,
-		  0x48, 0x70, 0x55, 0xcf, 0x88, 0xb2, 0x30, 0x7b },
-		{ 0x33, 0x48, 0x4d, 0xc2, 0x13, 0x6b },
-		{ 0xde, 0xac, 0xdd, 0x84, 0x8c, 0xc6 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.4 Test Set 4 */
-		{ 0x9e, 0x59, 0x44, 0xae, 0xa9, 0x4b, 0x81, 0x16,
-		  0x5c, 0x82, 0xfb, 0xf9, 0xf3, 0x2d, 0xb7, 0x51 },
-		{ 0xce, 0x83, 0xdb, 0xc5, 0x4a, 0xc0, 0x27, 0x4a,
-		  0x15, 0x7c, 0x17, 0xf8, 0x0d, 0x01, 0x7b, 0xd6 },
-		{ 0x0b, 0x60, 0x4a, 0x81, 0xec, 0xa8 },
-		{ 0x9e, 0x09 },
-		{ 0x22, 0x30, 0x14, 0xc5, 0x80, 0x66, 0x94, 0xc0,
-		  0x07, 0xca, 0x1e, 0xee, 0xf5, 0x7f, 0x00, 0x4f },
-		{ 0xa6, 0x4a, 0x50, 0x7a, 0xe1, 0xa2, 0xa9, 0x8b,
-		  0xb8, 0x8e, 0xb4, 0x21, 0x01, 0x35, 0xdc, 0x87 },
-		{ 0x74, 0xa5, 0x82, 0x20, 0xcb, 0xa8, 0x4c, 0x49 },
-		{ 0xac, 0x2c, 0xc7, 0x4a, 0x96, 0x87, 0x18, 0x37 },
-		{ 0xf3, 0x65, 0xcd, 0x68, 0x3c, 0xd9, 0x2e, 0x96 },
-		{ 0xe2, 0x03, 0xed, 0xb3, 0x97, 0x15, 0x74, 0xf5,
-		  0xa9, 0x4b, 0x0d, 0x61, 0xb8, 0x16, 0x34, 0x5d },
-		{ 0x0c, 0x45, 0x24, 0xad, 0xea, 0xc0, 0x41, 0xc4,
-		  0xdd, 0x83, 0x0d, 0x20, 0x85, 0x4f, 0xc4, 0x6b },
-		{ 0xf0, 0xb9, 0xc0, 0x8a, 0xd0, 0x2e },
-		{ 0x60, 0x85, 0xa8, 0x6c, 0x6f, 0x63 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.5 Test Set 5 */
-		{ 0x4a, 0xb1, 0xde, 0xb0, 0x5c, 0xa6, 0xce, 0xb0,
-		  0x51, 0xfc, 0x98, 0xe7, 0x7d, 0x02, 0x6a, 0x84 },
-		{ 0x74, 0xb0, 0xcd, 0x60, 0x31, 0xa1, 0xc8, 0x33,
-		  0x9b, 0x2b, 0x6c, 0xe2, 0xb8, 0xc4, 0xa1, 0x86 },
-		{ 0xe8, 0x80, 0xa1, 0xb5, 0x80, 0xb6 },
-		{ 0x9f, 0x07 },
-		{ 0x2d, 0x16, 0xc5, 0xcd, 0x1f, 0xdf, 0x6b, 0x22,
-		  0x38, 0x35, 0x84, 0xe3, 0xbe, 0xf2, 0xa8, 0xd8 },
-		{ 0xdc, 0xf0, 0x7c, 0xbd, 0x51, 0x85, 0x52, 0x90,
-		  0xb9, 0x2a, 0x07, 0xa9, 0x89, 0x1e, 0x52, 0x3e },
-		{ 0x49, 0xe7, 0x85, 0xdd, 0x12, 0x62, 0x6e, 0xf2 },
-		{ 0x9e, 0x85, 0x79, 0x03, 0x36, 0xbb, 0x3f, 0xa2 },
-		{ 0x58, 0x60, 0xfc, 0x1b, 0xce, 0x35, 0x1e, 0x7e },
-		{ 0x76, 0x57, 0x76, 0x6b, 0x37, 0x3d, 0x1c, 0x21,
-		  0x38, 0xf3, 0x07, 0xe3, 0xde, 0x92, 0x42, 0xf9 },
-		{ 0x1c, 0x42, 0xe9, 0x60, 0xd8, 0x9b, 0x8f, 0xa9,
-		  0x9f, 0x27, 0x44, 0xe0, 0x70, 0x8c, 0xcb, 0x53 },
-		{ 0x31, 0xe1, 0x1a, 0x60, 0x91, 0x18 },
-		{ 0xfe, 0x25, 0x55, 0xe5, 0x4a, 0xa9 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.6 Test Set 6 */
-		{ 0x6c, 0x38, 0xa1, 0x16, 0xac, 0x28, 0x0c, 0x45,
-		  0x4f, 0x59, 0x33, 0x2e, 0xe3, 0x5c, 0x8c, 0x4f },
-		{ 0xee, 0x64, 0x66, 0xbc, 0x96, 0x20, 0x2c, 0x5a,
-		  0x55, 0x7a, 0xbb, 0xef, 0xf8, 0xba, 0xbf, 0x63 },
-		{ 0x41, 0x4b, 0x98, 0x22, 0x21, 0x81 },
-		{ 0x44, 0x64 },
-		{ 0x1b, 0xa0, 0x0a, 0x1a, 0x7c, 0x67, 0x00, 0xac,
-		  0x8c, 0x3f, 0xf3, 0xe9, 0x6a, 0xd0, 0x87, 0x25 },
-		{ 0x38, 0x03, 0xef, 0x53, 0x63, 0xb9, 0x47, 0xc6,
-		  0xaa, 0xa2, 0x25, 0xe5, 0x8f, 0xae, 0x39, 0x34 },
-		{ 0x07, 0x8a, 0xdf, 0xb4, 0x88, 0x24, 0x1a, 0x57 },
-		{ 0x80, 0x24, 0x6b, 0x8d, 0x01, 0x86, 0xbc, 0xf1 },
-		{ 0x16, 0xc8, 0x23, 0x3f, 0x05, 0xa0, 0xac, 0x28 },
-		{ 0x3f, 0x8c, 0x75, 0x87, 0xfe, 0x8e, 0x4b, 0x23,
-		  0x3a, 0xf6, 0x76, 0xae, 0xde, 0x30, 0xba, 0x3b },
-		{ 0xa7, 0x46, 0x6c, 0xc1, 0xe6, 0xb2, 0xa1, 0x33,
-		  0x7d, 0x49, 0xd3, 0xb6, 0x6e, 0x95, 0xd7, 0xb4 },
-		{ 0x45, 0xb0, 0xf6, 0x9a, 0xb0, 0x6c },
-		{ 0x1f, 0x53, 0xcd, 0x2b, 0x11, 0x13 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.7 Test Set 7 */
-		{ 0x2d, 0x60, 0x9d, 0x4d, 0xb0, 0xac, 0x5b, 0xf0,
-		  0xd2, 0xc0, 0xde, 0x26, 0x70, 0x14, 0xde, 0x0d },
-		{ 0x19, 0x4a, 0xa7, 0x56, 0x01, 0x38, 0x96, 0xb7,
-		  0x4b, 0x4a, 0x2a, 0x3b, 0x0a, 0xf4, 0x53, 0x9e },
-		{ 0x6b, 0xf6, 0x94, 0x38, 0xc2, 0xe4 },
-		{ 0x5f, 0x67 },
-		{ 0x46, 0x0a, 0x48, 0x38, 0x54, 0x27, 0xaa, 0x39,
-		  0x26, 0x4a, 0xac, 0x8e, 0xfc, 0x9e, 0x73, 0xe8 },
-		{ 0xc3, 0x5a, 0x0a, 0xb0, 0xbc, 0xbf, 0xc9, 0x25,
-		  0x2c, 0xaf, 0xf1, 0x5f, 0x24, 0xef, 0xbd, 0xe0 },
-		{ 0xbd, 0x07, 0xd3, 0x00, 0x3b, 0x9e, 0x5c, 0xc3 },
-		{ 0xbc, 0xb6, 0xc2, 0xfc, 0xad, 0x15, 0x22, 0x50 },
-		{ 0x8c, 0x25, 0xa1, 0x6c, 0xd9, 0x18, 0xa1, 0xdf },
-		{ 0x4c, 0xd0, 0x84, 0x60, 0x20, 0xf8, 0xfa, 0x07,
-		  0x31, 0xdd, 0x47, 0xcb, 0xdc, 0x6b, 0xe4, 0x11 },
-		{ 0x88, 0xab, 0x80, 0xa4, 0x15, 0xf1, 0x5c, 0x73,
-		  0x71, 0x12, 0x54, 0xa1, 0xd3, 0x88, 0xf6, 0x96 },
-		{ 0x7e, 0x64, 0x55, 0xf3, 0x4c, 0xf3 },
-		{ 0xdc, 0x6d, 0xd0, 0x1e, 0x8f, 0x15 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.8 Test Set 8 */
-		{ 0xa5, 0x30, 0xa7, 0xfe, 0x42, 0x8f, 0xad, 0x10,
-		  0x82, 0xc4, 0x5e, 0xdd, 0xfc, 0xe1, 0x38, 0x84 },
-		{ 0x3a, 0x4c, 0x2b, 0x32, 0x45, 0xc5, 0x0e, 0xb5,
-		  0xc7, 0x1d, 0x08, 0x63, 0x93, 0x95, 0x76, 0x4d },
-		{ 0xf6, 0x3f, 0x5d, 0x76, 0x87, 0x84 },
-		{ 0xb9, 0x0e },
-		{ 0x51, 0x1c, 0x6c, 0x4e, 0x83, 0xe3, 0x8c, 0x89,
-		  0xb1, 0xc5, 0xd8, 0xdd, 0xe6, 0x24, 0x26, 0xfa },
-		{ 0x27, 0x95, 0x3e, 0x49, 0xbc, 0x8a, 0xf6, 0xdc,
-		  0xc6, 0xe7, 0x30, 0xeb, 0x80, 0x28, 0x6b, 0xe3 },
-		{ 0x53, 0x76, 0x1f, 0xbd, 0x67, 0x9b, 0x0b, 0xad },
-		{ 0x21, 0xad, 0xfd, 0x33, 0x4a, 0x10, 0xe7, 0xce },
-		{ 0xa6, 0x32, 0x41, 0xe1, 0xff, 0xc3, 0xe5, 0xab },
-		{ 0x10, 0xf0, 0x5b, 0xab, 0x75, 0xa9, 0x9a, 0x5f,
-		  0xbb, 0x98, 0xa9, 0xc2, 0x87, 0x67, 0x9c, 0x3b },
-		{ 0xf9, 0xec, 0x08, 0x65, 0xeb, 0x32, 0xf2, 0x23,
-		  0x69, 0xca, 0xde, 0x40, 0xc5, 0x9c, 0x3a, 0x44 },
-		{ 0x88, 0x19, 0x6c, 0x47, 0x98, 0x6f },
-		{ 0xc9, 0x87, 0xa3, 0xd2, 0x31, 0x15 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.9 Test Set 9 */
-		{ 0xd9, 0x15, 0x1c, 0xf0, 0x48, 0x96, 0xe2, 0x58,
-		  0x30, 0xbf, 0x2e, 0x08, 0x26, 0x7b, 0x83, 0x60 },
-		{ 0xf7, 0x61, 0xe5, 0xe9, 0x3d, 0x60, 0x3f, 0xeb,
-		  0x73, 0x0e, 0x27, 0x55, 0x6c, 0xb8, 0xa2, 0xca },
-		{ 0x47, 0xee, 0x01, 0x99, 0x82, 0x0a },
-		{ 0x91, 0x13 },
-		{ 0x75, 0xfc, 0x22, 0x33, 0xa4, 0x42, 0x94, 0xee,
-		  0x8e, 0x6d, 0xe2, 0x5c, 0x43, 0x53, 0xd2, 0x6b },
-		{ 0xc4, 0xc9, 0x3e, 0xff, 0xe8, 0xa0, 0x81, 0x38,
-		  0xc2, 0x03, 0xd4, 0xc2, 0x7c, 0xe4, 0xe3, 0xd9 },
-		{ 0x66, 0xcc, 0x4b, 0xe4, 0x48, 0x62, 0xaf, 0x1f },
-		{ 0x7a, 0x4b, 0x8d, 0x7a, 0x87, 0x53, 0xf2, 0x46 },
-		{ 0x4a, 0x90, 0xb2, 0x17, 0x1a, 0xc8, 0x3a, 0x76 },
-		{ 0x71, 0x23, 0x6b, 0x71, 0x29, 0xf9, 0xb2, 0x2a,
-		  0xb7, 0x7e, 0xa7, 0xa5, 0x4c, 0x96, 0xda, 0x22 },
-		{ 0x90, 0x52, 0x7e, 0xba, 0xa5, 0x58, 0x89, 0x68,
-		  0xdb, 0x41, 0x72, 0x73, 0x25, 0xa0, 0x4d, 0x9e },
-		{ 0x82, 0xa0, 0xf5, 0x28, 0x7a, 0x71 },
-		{ 0x52, 0x7d, 0xbf, 0x41, 0xf3, 0x5f }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.10 Test Set 10 */
-		{ 0xa0, 0xe2, 0x97, 0x1b, 0x68, 0x22, 0xe8, 0xd3,
-		  0x54, 0xa1, 0x8c, 0xc2, 0x35, 0x62, 0x4e, 0xcb },
-		{ 0x08, 0xef, 0xf8, 0x28, 0xb1, 0x3f, 0xdb, 0x56,
-		  0x27, 0x22, 0xc6, 0x5c, 0x7f, 0x30, 0xa9, 0xb2 },
-		{ 0xdb, 0x5c, 0x06, 0x64, 0x81, 0xe0 },
-		{ 0x71, 0x6b },
-		{ 0x32, 0x37, 0x92, 0xfa, 0xca, 0x21, 0xfb, 0x4d,
-		  0x5d, 0x6f, 0x13, 0xc1, 0x45, 0xa9, 0xd2, 0xc1 },
-		{ 0x82, 0xa2, 0x6f, 0x22, 0xbb, 0xa9, 0xe9, 0x48,
-		  0x8f, 0x94, 0x9a, 0x10, 0xd9, 0x8e, 0x9c, 0xc4 },
-		{ 0x94, 0x85, 0xfe, 0x24, 0x62, 0x1c, 0xb9, 0xf6 },
-		{ 0xbc, 0xe3, 0x25, 0xce, 0x03, 0xe2, 0xe9, 0xb9 },
-		{ 0x4b, 0xc2, 0x21, 0x2d, 0x86, 0x24, 0x91, 0x0a },
-		{ 0x08, 0xce, 0xf6, 0xd0, 0x04, 0xec, 0x61, 0x47,
-		  0x1a, 0x3c, 0x3c, 0xda, 0x04, 0x81, 0x37, 0xfa },
-		{ 0xed, 0x03, 0x18, 0xca, 0x5d, 0xeb, 0x92, 0x06,
-		  0x27, 0x2f, 0x6e, 0x8f, 0xa6, 0x4b, 0xa4, 0x11 },
-		{ 0xa2, 0xf8, 0x58, 0xaa, 0x9e, 0x5d },
-		{ 0x74, 0xe7, 0x6f, 0xbb, 0xec, 0x38 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.11 Test Set 11 */
-		{ 0x0d, 0xa6, 0xf7, 0xba, 0x86, 0xd5, 0xea, 0xc8,
-		  0xa1, 0x9c, 0xf5, 0x63, 0xac, 0x58, 0x64, 0x2d },
-		{ 0x67, 0x9a, 0xc4, 0xdb, 0xac, 0xd7, 0xd2, 0x33,
-		  0xff, 0x9d, 0x68, 0x06, 0xf4, 0x14, 0x9c, 0xe3 },
-		{ 0x6e, 0x23, 0x31, 0xd6, 0x92, 0xad },
-		{ 0x22, 0x4a },
-		{ 0x4b, 0x9a, 0x26, 0xfa, 0x45, 0x9e, 0x3a, 0xcb,
-		  0xff, 0x36, 0xf4, 0x01, 0x5d, 0xe3, 0xbd, 0xc1 },
-		{ 0x0d, 0xb1, 0x07, 0x1f, 0x87, 0x67, 0x56, 0x2c,
-		  0xa4, 0x3a, 0x0a, 0x64, 0xc4, 0x1e, 0x8d, 0x08 },
-		{ 0x28, 0x31, 0xd7, 0xae, 0x90, 0x88, 0xe4, 0x92 },
-		{ 0x9b, 0x2e, 0x16, 0x95, 0x11, 0x35, 0xd5, 0x23 },
-		{ 0x6f, 0xc3, 0x0f, 0xee, 0x6d, 0x12, 0x35, 0x23 },
-		{ 0x69, 0xb1, 0xca, 0xe7, 0xc7, 0x42, 0x9d, 0x97,
-		  0x5e, 0x24, 0x5c, 0xac, 0xb0, 0x5a, 0x51, 0x7c },
-		{ 0x74, 0xf2, 0x4e, 0x8c, 0x26, 0xdf, 0x58, 0xe1,
-		  0xb3, 0x8d, 0x7d, 0xcd, 0x4f, 0x1b, 0x7f, 0xbd },
-		{ 0x4c, 0x53, 0x9a, 0x26, 0xe1, 0xfa },
-		{ 0x07, 0x86, 0x1e, 0x12, 0x69, 0x28 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.12 Test Set 12 */
-		{ 0x77, 0xb4, 0x58, 0x43, 0xc8, 0x8e, 0x58, 0xc1,
-		  0x0d, 0x20, 0x26, 0x84, 0x51, 0x5e, 0xd4, 0x30 },
-		{ 0x4c, 0x47, 0xeb, 0x30, 0x76, 0xdc, 0x55, 0xfe,
-		  0x51, 0x06, 0xcb, 0x20, 0x34, 0xb8, 0xcd, 0x78 },
-		{ 0xfe, 0x1a, 0x87, 0x31, 0x00, 0x5d },
-		{ 0xad, 0x25 },
-		{ 0xbf, 0x32, 0x86, 0xc7, 0xa5, 0x14, 0x09, 0xce,
-		  0x95, 0x72, 0x4d, 0x50, 0x3b, 0xfe, 0x6e, 0x70 },
-		{ 0xd4, 0x83, 0xaf, 0xae, 0x56, 0x24, 0x09, 0xa3,
-		  0x26, 0xb5, 0xbb, 0x0b, 0x20, 0xc4, 0xd7, 0x62 },
-		{ 0x08, 0x33, 0x2d, 0x7e, 0x9f, 0x48, 0x45, 0x70 },
-		{ 0xed, 0x41, 0xb7, 0x34, 0x48, 0x9d, 0x52, 0x07 },
-		{ 0xae, 0xfa, 0x35, 0x7b, 0xea, 0xc2, 0xa8, 0x7a },
-		{ 0x90, 0x8c, 0x43, 0xf0, 0x56, 0x9c, 0xb8, 0xf7,
-		  0x4b, 0xc9, 0x71, 0xe7, 0x06, 0xc3, 0x6c, 0x5f },
-		{ 0xc2, 0x51, 0xdf, 0x0d, 0x88, 0x8d, 0xd9, 0x32,
-		  0x9b, 0xcf, 0x46, 0x65, 0x5b, 0x22, 0x6e, 0x40 },
-		{ 0x30, 0xff, 0x25, 0xcd, 0xad, 0xf6 },
-		{ 0xe8, 0x4e, 0xd0, 0xd4, 0x67, 0x7e }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.13 Test Set 13 */
-		{ 0x72, 0x9b, 0x17, 0x72, 0x92, 0x70, 0xdd, 0x87,
-		  0xcc, 0xdf, 0x1b, 0xfe, 0x29, 0xb4, 0xe9, 0xbb },
-		{ 0x31, 0x1c, 0x4c, 0x92, 0x97, 0x44, 0xd6, 0x75,
-		  0xb7, 0x20, 0xf3, 0xb7, 0xe9, 0xb1, 0xcb, 0xd0 },
-		{ 0xc8, 0x5c, 0x4c, 0xf6, 0x59, 0x16 },
-		{ 0x5b, 0xb2 },
-		{ 0xd0, 0x4c, 0x9c, 0x35, 0xbd, 0x22, 0x62, 0xfa,
-		  0x81, 0x0d, 0x29, 0x24, 0xd0, 0x36, 0xfd, 0x13 },
-		{ 0x22, 0x8c, 0x2f, 0x2f, 0x06, 0xac, 0x32, 0x68,
-		  0xa9, 0xe6, 0x16, 0xee, 0x16, 0xdb, 0x4b, 0xa1 },
-		{ 0xff, 0x79, 0x4f, 0xe2, 0xf8, 0x27, 0xeb, 0xf8 },
-		{ 0x24, 0xfe, 0x4d, 0xc6, 0x1e, 0x87, 0x4b, 0x52 },
-		{ 0x98, 0xdb, 0xbd, 0x09, 0x9b, 0x3b, 0x40, 0x8d },
-		{ 0x44, 0xc0, 0xf2, 0x3c, 0x54, 0x93, 0xcf, 0xd2,
-		  0x41, 0xe4, 0x8f, 0x19, 0x7e, 0x1d, 0x10, 0x12 },
-		{ 0x0c, 0x9f, 0xb8, 0x16, 0x13, 0x88, 0x4c, 0x25,
-		  0x35, 0xdd, 0x0e, 0xab, 0xf3, 0xb4, 0x40, 0xd8 },
-		{ 0x53, 0x80, 0xd1, 0x58, 0xcf, 0xe3 },
-		{ 0x87, 0xac, 0x3b, 0x55, 0x9f, 0xb6 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.14 Test Set 14 */
-		{ 0xd3, 0x2d, 0xd2, 0x3e, 0x89, 0xdc, 0x66, 0x23,
-		  0x54, 0xca, 0x12, 0xeb, 0x79, 0xdd, 0x32, 0xfa },
-		{ 0xcf, 0x7d, 0x0a, 0xb1, 0xd9, 0x43, 0x06, 0x95,
-		  0x0b, 0xf1, 0x20, 0x18, 0xfb, 0xd4, 0x68, 0x87 },
-		{ 0x48, 0x41, 0x07, 0xe5, 0x6a, 0x43 },
-		{ 0xb5, 0xe6 },
-		{ 0xfe, 0x75, 0x90, 0x5b, 0x9d, 0xa4, 0x7d, 0x35,
-		  0x62, 0x36, 0xd0, 0x31, 0x4e, 0x09, 0xc3, 0x2e },
-		{ 0xd2, 0x2a, 0x4b, 0x41, 0x80, 0xa5, 0x32, 0x57,
-		  0x08, 0xa5, 0xff, 0x70, 0xd9, 0xf6, 0x7e, 0xc7 },
-		{ 0xcf, 0x19, 0xd6, 0x2b, 0x6a, 0x80, 0x98, 0x66 },
-		{ 0x5d, 0x26, 0x95, 0x37, 0xe4, 0x5e, 0x2c, 0xe6 },
-		{ 0xaf, 0x4a, 0x41, 0x1e, 0x11, 0x39, 0xf2, 0xc2 },
-		{ 0x5a, 0xf8, 0x6b, 0x80, 0xed, 0xb7, 0x0d, 0xf5,
-		  0x29, 0x2c, 0xc1, 0x12, 0x1c, 0xba, 0xd5, 0x0c },
-		{ 0x7f, 0x4d, 0x6a, 0xe7, 0x44, 0x0e, 0x18, 0x78,
-		  0x9a, 0x8b, 0x75, 0xad, 0x3f, 0x42, 0xf0, 0x3a },
-		{ 0x21, 0x7a, 0xf4, 0x92, 0x72, 0xad },
-		{ 0x90, 0x0e, 0x10, 0x1c, 0x67, 0x7e }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.15 Test Set 15 */
-		{ 0xaf, 0x7c, 0x65, 0xe1, 0x92, 0x72, 0x21, 0xde,
-		  0x59, 0x11, 0x87, 0xa2, 0xc5, 0x98, 0x7a, 0x53 },
-		{ 0x1f, 0x0f, 0x85, 0x78, 0x46, 0x4f, 0xd5, 0x9b,
-		  0x64, 0xbe, 0xd2, 0xd0, 0x94, 0x36, 0xb5, 0x7a },
-		{ 0x3d, 0x62, 0x7b, 0x01, 0x41, 0x8d },
-		{ 0x84, 0xf6 },
-		{ 0x0c, 0x7a, 0xcb, 0x8d, 0x95, 0xb7, 0xd4, 0xa3,
-		  0x1c, 0x5a, 0xca, 0x6d, 0x26, 0x34, 0x5a, 0x88 },
-		{ 0xa4, 0xcf, 0x5c, 0x81, 0x55, 0xc0, 0x8a, 0x7e,
-		  0xff, 0x41, 0x8e, 0x54, 0x43, 0xb9, 0x8e, 0x55 },
-		{ 0xc3, 0x7c, 0xae, 0x78, 0x05, 0x64, 0x20, 0x32 },
-		{ 0x68, 0xcd, 0x09, 0xa4, 0x52, 0xd8, 0xdb, 0x7c },
-		{ 0x7b, 0xff, 0xa5, 0xc2, 0xf4, 0x1f, 0xbc, 0x05 },
-		{ 0x3f, 0x8c, 0x3f, 0x3c, 0xcf, 0x76, 0x25, 0xbf,
-		  0x77, 0xfc, 0x94, 0xbc, 0xfd, 0x22, 0xfd, 0x26 },
-		{ 0xab, 0xcb, 0xae, 0x8f, 0xd4, 0x61, 0x15, 0xe9,
-		  0x96, 0x1a, 0x55, 0xd0, 0xda, 0x5f, 0x20, 0x78 },
-		{ 0x83, 0x7f, 0xd7, 0xb7, 0x44, 0x19 },
-		{ 0x56, 0xe9, 0x7a, 0x60, 0x90, 0xb1 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.16 Test Set 16 */
-		{ 0x5b, 0xd7, 0xec, 0xd3, 0xd3, 0x12, 0x7a, 0x41,
-		  0xd1, 0x25, 0x39, 0xbe, 0xd4, 0xe7, 0xcf, 0x71 },
-		{ 0x59, 0xb7, 0x5f, 0x14, 0x25, 0x1c, 0x75, 0x03,
-		  0x1d, 0x0b, 0xcb, 0xac, 0x1c, 0x2c, 0x04, 0xc7 },
-		{ 0xa2, 0x98, 0xae, 0x89, 0x29, 0xdc },
-		{ 0xd0, 0x56 },
-		{ 0xf9, 0x67, 0xf7, 0x60, 0x38, 0xb9, 0x20, 0xa9,
-		  0xcd, 0x25, 0xe1, 0x0c, 0x08, 0xb4, 0x99, 0x24 },
-		{ 0x76, 0x08, 0x9d, 0x3c, 0x0f, 0xf3, 0xef, 0xdc,
-		  0x6e, 0x36, 0x72, 0x1d, 0x4f, 0xce, 0xb7, 0x47 },
-		{ 0xc3, 0xf2, 0x5c, 0xd9, 0x43, 0x09, 0x10, 0x7e },
-		{ 0xb0, 0xc8, 0xba, 0x34, 0x36, 0x65, 0xaf, 0xcc },
-		{ 0x7e, 0x3f, 0x44, 0xc7, 0x59, 0x1f, 0x6f, 0x45 },
-		{ 0xd4, 0x2b, 0x2d, 0x61, 0x5e, 0x49, 0xa0, 0x3a,
-		  0xc2, 0x75, 0xa5, 0xae, 0xf9, 0x7a, 0xf8, 0x92 },
-		{ 0x0b, 0x3f, 0x8d, 0x02, 0x4f, 0xe6, 0xbf, 0xaf,
-		  0xaa, 0x98, 0x2b, 0x8f, 0x82, 0xe3, 0x19, 0xc2 },
-		{ 0x5b, 0xe1, 0x14, 0x95, 0x52, 0x5d },
-		{ 0x4d, 0x6a, 0x34, 0xa1, 0xe4, 0xeb }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.17 Test Set 17 */
-		{ 0x6c, 0xd1, 0xc6, 0xce, 0xb1, 0xe0, 0x1e, 0x14,
-		  0xf1, 0xb8, 0x23, 0x16, 0xa9, 0x0b, 0x7f, 0x3d },
-		{ 0xf6, 0x9b, 0x78, 0xf3, 0x00, 0xa0, 0x56, 0x8b,
-		  0xce, 0x9f, 0x0c, 0xb9, 0x3c, 0x4b, 0xe4, 0xc9 },
-		{ 0xb4, 0xfc, 0xe5, 0xfe, 0xb0, 0x59 },
-		{ 0xe4, 0xbb },
-		{ 0x07, 0x8b, 0xfc, 0xa9, 0x56, 0x46, 0x59, 0xec,
-		  0xd8, 0x85, 0x1e, 0x84, 0xe6, 0xc5, 0x9b, 0x48 },
-		{ 0xa2, 0x19, 0xdc, 0x37, 0xf1, 0xdc, 0x7d, 0x66,
-		  0x73, 0x8b, 0x58, 0x43, 0xc7, 0x99, 0xf2, 0x06 },
-		{ 0x69, 0xa9, 0x08, 0x69, 0xc2, 0x68, 0xcb, 0x7b },
-		{ 0x2e, 0x0f, 0xdc, 0xf9, 0xfd, 0x1c, 0xfa, 0x6a },
-		{ 0x70, 0xf6, 0xbd, 0xb9, 0xad, 0x21, 0x52, 0x5f },
-		{ 0x6e, 0xda, 0xf9, 0x9e, 0x5b, 0xd9, 0xf8, 0x5d,
-		  0x5f, 0x36, 0xd9, 0x1c, 0x12, 0x72, 0xfb, 0x4b },
-		{ 0xd6, 0x1c, 0x85, 0x3c, 0x28, 0x0d, 0xd9, 0xc4,
-		  0x6f, 0x29, 0x7b, 0xae, 0xc3, 0x86, 0xde, 0x17 },
-		{ 0x1c, 0x40, 0x8a, 0x85, 0x8b, 0x3e },
-		{ 0xaa, 0x4a, 0xe5, 0x2d, 0xaa, 0x30 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.18 Test Set 18 */
-		{ 0xb7, 0x3a, 0x90, 0xcb, 0xcf, 0x3a, 0xfb, 0x62,
-		  0x2d, 0xba, 0x83, 0xc5, 0x8a, 0x84, 0x15, 0xdf },
-		{ 0xb1, 0x20, 0xf1, 0xc1, 0xa0, 0x10, 0x2a, 0x2f,
-		  0x50, 0x7d, 0xd5, 0x43, 0xde, 0x68, 0x28, 0x1f },
-		{ 0xf1, 0xe8, 0xa5, 0x23, 0xa3, 0x6d },
-		{ 0x47, 0x1b },
-		{ 0xb6, 0x72, 0x04, 0x7e, 0x00, 0x3b, 0xb9, 0x52,
-		  0xdc, 0xa6, 0xcb, 0x8a, 0xf0, 0xe5, 0xb7, 0x79 },
-		{ 0xdf, 0x0c, 0x67, 0x86, 0x8f, 0xa2, 0x5f, 0x74,
-		  0x8b, 0x70, 0x44, 0xc6, 0xe7, 0xc2, 0x45, 0xb8 },
-		{ 0xeb, 0xd7, 0x03, 0x41, 0xbc, 0xd4, 0x15, 0xb0 },
-		{ 0x12, 0x35, 0x9f, 0x5d, 0x82, 0x22, 0x0c, 0x14 },
-		{ 0x47, 0x9d, 0xd2, 0x5c, 0x20, 0x79, 0x2d, 0x63 },
-		{ 0x66, 0x19, 0x5d, 0xbe, 0xd0, 0x31, 0x32, 0x74,
-		  0xc5, 0xca, 0x77, 0x66, 0x61, 0x5f, 0xa2, 0x5e },
-		{ 0x66, 0xbe, 0xc7, 0x07, 0xeb, 0x2a, 0xfc, 0x47,
-		  0x6d, 0x74, 0x08, 0xa8, 0xf2, 0x92, 0x7b, 0x36 },
-		{ 0xae, 0xfd, 0xaa, 0x5d, 0xdd, 0x99 },
-		{ 0x12, 0xec, 0x2b, 0x87, 0xfb, 0xb1 }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.19 Test Set 19 */
-		{ 0x51, 0x22, 0x25, 0x02, 0x14, 0xc3, 0x3e, 0x72,
-		  0x3a, 0x5d, 0xd5, 0x23, 0xfc, 0x14, 0x5f, 0xc0 },
-		{ 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
-		  0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
-		{ 0x16, 0xf3, 0xb3, 0xf7, 0x0f, 0xc2 },
-		{ 0xc3, 0xab },
-		{ 0xc9, 0xe8, 0x76, 0x32, 0x86, 0xb5, 0xb9, 0xff,
-		  0xbd, 0xf5, 0x6e, 0x12, 0x97, 0xd0, 0x88, 0x7b },
-		{ 0x98, 0x1d, 0x46, 0x4c, 0x7c, 0x52, 0xeb, 0x6e,
-		  0x50, 0x36, 0x23, 0x49, 0x84, 0xad, 0x0b, 0xcf },
-		{ 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
-		{ 0x62, 0xda, 0xe3, 0x85, 0x3f, 0x3a, 0xf9, 0xd2 },
-		{ 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
-		{ 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
-		  0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
-		{ 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
-		  0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
-		{ 0xad, 0xa1, 0x5a, 0xeb, 0x7b, 0xb8 },
-		{ 0xd4, 0x61, 0xbc, 0x15, 0x47, 0x5d }
-	}, {
-		/* 3GPP TS 35.208 v6.0.0 - 4.3.20 Test Set 20 */
-		{ 0x90, 0xdc, 0xa4, 0xed, 0xa4, 0x5b, 0x53, 0xcf,
-		  0x0f, 0x12, 0xd7, 0xc9, 0xc3, 0xbc, 0x6a, 0x89 },
-		{ 0x9f, 0xdd, 0xc7, 0x20, 0x92, 0xc6, 0xad, 0x03,
-		  0x6b, 0x6e, 0x46, 0x47, 0x89, 0x31, 0x5b, 0x78 },
-		{ 0x20, 0xf8, 0x13, 0xbd, 0x41, 0x41 },
-		{ 0x61, 0xdf },
-		{ 0x3f, 0xfc, 0xfe, 0x5b, 0x7b, 0x11, 0x11, 0x58,
-		  0x99, 0x20, 0xd3, 0x52, 0x8e, 0x84, 0xe6, 0x55 },
-		{ 0xcb, 0x9c, 0xcc, 0xc4, 0xb9, 0x25, 0x8e, 0x6d,
-		  0xca, 0x47, 0x60, 0x37, 0x9f, 0xb8, 0x25, 0x81 },
-		{ 0x09, 0xdb, 0x94, 0xea, 0xb4, 0xf8, 0x14, 0x9e },
-		{ 0xa2, 0x94, 0x68, 0xaa, 0x97, 0x75, 0xb5, 0x27 },
-		{ 0xa9, 0x51, 0x00, 0xe2, 0x76, 0x09, 0x52, 0xcd },
-		{ 0xb5, 0xf2, 0xda, 0x03, 0x88, 0x3b, 0x69, 0xf9,
-		  0x6b, 0xf5, 0x2e, 0x02, 0x9e, 0xd9, 0xac, 0x45 },
-		{ 0xb4, 0x72, 0x13, 0x68, 0xbc, 0x16, 0xea, 0x67,
-		  0x87, 0x5c, 0x55, 0x98, 0x68, 0x8b, 0xb0, 0xef },
-		{ 0x83, 0xcf, 0xd5, 0x4d, 0xb9, 0x13 },
-		{ 0x4f, 0x20, 0x39, 0x39, 0x2d, 0xdc }
-	}
-};
-
-#define NUM_TESTS (sizeof(test_sets) / sizeof(test_sets[0]))
-
-
-int main(int argc, char *argv[])
-{
-	u8 buf[16], buf2[16], buf3[16], buf4[16], buf5[16], opc[16];
-	u8 auts[14], sqn[6], _rand[16];
-	int ret = 0, res, i;
-	const struct milenage_test_set *t;
-	size_t res_len;
-
-	wpa_debug_level = 0;
-
-	printf("Milenage test sets\n");
-	for (i = 0; i < NUM_TESTS; i++) {
-		t = &test_sets[i];
-		printf("Test Set %d\n", i + 1);
-
-		milenage_opc(t->op, t->k, opc);
-		if (memcmp(opc, t->opc, 16) != 0) {
-			printf("- milenage_opc failed\n");
-			ret++;
-		}
-
-		if (milenage_f1(opc, t->k, t->rand, t->sqn, t->amf, buf, buf2)
-		    ||  memcmp(buf, t->f1, 8) != 0) {
-			printf("- milenage_f1 failed\n");
-			ret++;
-		}
-		if (memcmp(buf2, t->f1star, 8) != 0) {
-			printf("- milenage_f1* failed\n");
-			ret++;
-		}
-
-		if (milenage_f2345(opc, t->k, t->rand, buf, buf2, buf3, buf4,
-				   buf5) ||
-		    memcmp(buf, t->f2, 8) != 0) {
-			printf("- milenage_f2 failed\n");
-			ret++;
-		}
-		if (memcmp(buf2, t->f3, 16) != 0) {
-			printf("- milenage_f3 failed\n");
-			ret++;
-		}
-		if (memcmp(buf3, t->f4, 16) != 0) {
-			printf("- milenage_f4 failed\n");
-			ret++;
-		}
-		if (memcmp(buf4, t->f5, 6) != 0) {
-			printf("- milenage_f5 failed\n");
-			ret++;
-		}
-		if (memcmp(buf5, t->f5star, 6) != 0) {
-			printf("- milenage_f5* failed\n");
-			ret++;
-		}
-	}
-
-	printf("milenage_auts test:\n");
-	os_memcpy(auts, "\x4f\x20\x39\x39\x2d\xdd", 6);
-	os_memcpy(auts + 6, "\x4b\xb4\x31\x6e\xd4\xa1\x46\x88", 8);
-	res = milenage_auts(t->opc, t->k, t->rand, auts, buf);
-	printf("AUTS for test set %d: %d / SQN=%02x%02x%02x%02x%02x%02x\n",
-	       i, res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
-	if (res)
-		ret++;
-
-	os_memset(_rand, 0xaa, sizeof(_rand));
-	os_memcpy(auts,
-		  "\x43\x68\x1a\xd3\xda\xf0\x06\xbc\xde\x40\x5a\x20\x72\x67",
-		  14);
-	res = milenage_auts(t->opc, t->k, _rand, auts, buf);
-	printf("AUTS from a test USIM: %d / SQN=%02x%02x%02x%02x%02x%02x\n",
-	       res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
-	if (res)
-		ret++;
-
-	printf("milenage_generate test:\n");
-	os_memcpy(sqn, "\x00\x00\x00\x00\x40\x44", 6);
-	os_memcpy(_rand, "\x12\x69\xb8\x23\x41\x39\x35\x66\xfb\x99\x41\xe9\x84"
-		  "\x4f\xe6\x2f", 16);
-	res_len = 8;
-	milenage_generate(t->opc, t->amf, t->k, sqn, _rand, buf, buf2, buf3,
-			  buf4, &res_len);
-	wpa_hexdump(MSG_DEBUG, "SQN", sqn, 6);
-	wpa_hexdump(MSG_DEBUG, "RAND", _rand, 16);
-	wpa_hexdump(MSG_DEBUG, "AUTN", buf, 16);
-	wpa_hexdump(MSG_DEBUG, "IK", buf2, 16);
-	wpa_hexdump(MSG_DEBUG, "CK", buf3, 16);
-	wpa_hexdump(MSG_DEBUG, "RES", buf4, res_len);
-
-	printf("GSM-Milenage test sets\n");
-	for (i = 0; i < NUM_GSM_TESTS; i++) {
-		const struct gsm_milenage_test_set *g;
-		u8 sres[4], kc[8];
-		g = &gsm_test_sets[i];
-		printf("Test Set %d\n", i + 1);
-		gsm_milenage(g->opc, g->ki, g->rand, sres, kc);
-		if (memcmp(g->kc, kc, 8) != 0) {
-			printf("- gsm_milenage Kc failed\n");
-			ret++;
-		}
-#ifdef GSM_MILENAGE_ALT_SRES
-		if (memcmp(g->sres2, sres, 4) != 0) {
-			printf("- gsm_milenage SRES#2 failed\n");
-			ret++;
-		}
-#else /* GSM_MILENAGE_ALT_SRES */
-		if (memcmp(g->sres1, sres, 4) != 0) {
-			printf("- gsm_milenage SRES#1 failed\n");
-			ret++;
-		}
-#endif /* GSM_MILENAGE_ALT_SRES */
-	}
-
-	if (ret)
-		printf("Something failed\n");
-	else
-		printf("OK\n");
-
-	return ret;
-}
-#endif /* TEST_MAIN_MILENAGE */
diff --git a/contrib/wpa/src/l2_packet/Makefile b/contrib/wpa/src/l2_packet/Makefile
index cffba620da04..9c41962fd7e1 100644
--- a/contrib/wpa/src/l2_packet/Makefile
+++ b/contrib/wpa/src/l2_packet/Makefile
@@ -2,7 +2,6 @@ all:
 	@echo Nothing to be made.
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
 	rm -f *~ *.o *.d
 
 install:
diff --git a/contrib/wpa/src/l2_packet/l2_packet_freebsd.c b/contrib/wpa/src/l2_packet/l2_packet_freebsd.c
index d1034aa76271..009e02c79c66 100644
--- a/contrib/wpa/src/l2_packet/l2_packet_freebsd.c
+++ b/contrib/wpa/src/l2_packet/l2_packet_freebsd.c
@@ -14,7 +14,7 @@
  */
 
 #include "includes.h"
-#ifdef __APPLE__
+#if defined(__APPLE__) || defined(__GLIBC__)
 #include 
 #endif /* __APPLE__ */
 #include 
diff --git a/contrib/wpa/src/l2_packet/l2_packet_ndis.c b/contrib/wpa/src/l2_packet/l2_packet_ndis.c
index 7de58808d63c..6ce29aa20ec9 100644
--- a/contrib/wpa/src/l2_packet/l2_packet_ndis.c
+++ b/contrib/wpa/src/l2_packet/l2_packet_ndis.c
@@ -137,11 +137,17 @@ int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
 		DWORD err = GetLastError();
 #ifndef _WIN32_WCE
 		if (err == ERROR_IO_PENDING) {
-			/* For now, just assume that the packet will be sent in
-			 * time before the next write happens. This could be
-			 * cleaned up at some point to actually wait for
-			 * completion before starting new writes.
-			 */
+			wpa_printf(MSG_DEBUG, "L2(NDISUIO): Wait for pending "
+				   "write to complete");
+			res = GetOverlappedResult(
+				driver_ndis_get_ndisuio_handle(), &overlapped,
+				&written, TRUE);
+			if (!res) {
+				wpa_printf(MSG_DEBUG, "L2(NDISUIO): "
+					   "GetOverlappedResult failed: %d",
+					   (int) GetLastError());
+				return -1;
+			}
 			return 0;
 		}
 #endif /* _WIN32_WCE */
diff --git a/contrib/wpa/src/lib.rules b/contrib/wpa/src/lib.rules
new file mode 100644
index 000000000000..b260d25a050c
--- /dev/null
+++ b/contrib/wpa/src/lib.rules
@@ -0,0 +1,21 @@
+ifndef CC
+CC=gcc
+endif
+
+ifndef CFLAGS
+CFLAGS = -MMD -O2 -Wall -g
+endif
+
+CFLAGS += -I.. -I../utils
+
+
+Q=@
+E=echo
+ifeq ($(V), 1)
+Q=
+E=true
+endif
+
+%.o: %.c
+	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
+	@$(E) "  CC " $<
diff --git a/contrib/wpa/src/radius/.gitignore b/contrib/wpa/src/radius/.gitignore
new file mode 100644
index 000000000000..a89a1f92753d
--- /dev/null
+++ b/contrib/wpa/src/radius/.gitignore
@@ -0,0 +1 @@
+libradius.a
diff --git a/contrib/wpa/src/radius/Makefile b/contrib/wpa/src/radius/Makefile
index cffba620da04..b199be8b1970 100644
--- a/contrib/wpa/src/radius/Makefile
+++ b/contrib/wpa/src/radius/Makefile
@@ -1,9 +1,22 @@
-all:
-	@echo Nothing to be made.
+all: libradius.a
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
-	rm -f *~ *.o *.d
+	rm -f *~ *.o *.d libradius.a
 
 install:
 	@echo Nothing to be made.
+
+
+include ../lib.rules
+
+CFLAGS += -DCONFIG_IPV6
+
+LIB_OBJS= \
+	radius.o \
+	radius_client.o \
+	radius_server.o
+
+libradius.a: $(LIB_OBJS)
+	$(AR) crT $@ $?
+
+-include $(OBJS:%.o=%.d)
diff --git a/contrib/wpa/src/radius/radius.c b/contrib/wpa/src/radius/radius.c
index 71bbfb52ee7c..70754ef5dd72 100644
--- a/contrib/wpa/src/radius/radius.c
+++ b/contrib/wpa/src/radius/radius.c
@@ -1,6 +1,6 @@
 /*
- * hostapd / RADIUS message processing
- * Copyright (c) 2002-2008, Jouni Malinen 
+ * RADIUS message processing
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -12,62 +12,82 @@
  * See README and COPYING for more details.
  */
 
-#include "includes.h"
+#include "utils/includes.h"
 
-#include "common.h"
+#include "utils/common.h"
+#include "utils/wpabuf.h"
+#include "crypto/md5.h"
+#include "crypto/crypto.h"
 #include "radius.h"
-#include "md5.h"
-#include "crypto.h"
+
+
+/**
+ * struct radius_msg - RADIUS message structure for new and parsed messages
+ */
+struct radius_msg {
+	/**
+	 * buf - Allocated buffer for RADIUS message
+	 */
+	struct wpabuf *buf;
+
+	/**
+	 * hdr - Pointer to the RADIUS header in buf
+	 */
+	struct radius_hdr *hdr;
+
+	/**
+	 * attr_pos - Array of indexes to attributes
+	 *
+	 * The values are number of bytes from buf to the beginning of
+	 * struct radius_attr_hdr.
+	 */
+	size_t *attr_pos;
+
+	/**
+	 * attr_size - Total size of the attribute pointer array
+	 */
+	size_t attr_size;
+
+	/**
+	 * attr_used - Total number of attributes in the array
+	 */
+	size_t attr_used;
+};
+
+
+struct radius_hdr * radius_msg_get_hdr(struct radius_msg *msg)
+{
+	return msg->hdr;
+}
+
+
+struct wpabuf * radius_msg_get_buf(struct radius_msg *msg)
+{
+	return msg->buf;
+}
 
 
 static struct radius_attr_hdr *
 radius_get_attr_hdr(struct radius_msg *msg, int idx)
 {
-	return (struct radius_attr_hdr *) (msg->buf + msg->attr_pos[idx]);
+	return (struct radius_attr_hdr *)
+		(wpabuf_mhead_u8(msg->buf) + msg->attr_pos[idx]);
 }
 
 
-struct radius_msg *radius_msg_new(u8 code, u8 identifier)
+static void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier)
 {
-	struct radius_msg *msg;
-
-	msg = os_malloc(sizeof(*msg));
-	if (msg == NULL)
-		return NULL;
-
-	if (radius_msg_initialize(msg, RADIUS_DEFAULT_MSG_SIZE)) {
-		os_free(msg);
-		return NULL;
-	}
-
-	radius_msg_set_hdr(msg, code, identifier);
-
-	return msg;
+	msg->hdr->code = code;
+	msg->hdr->identifier = identifier;
 }
 
 
-int radius_msg_initialize(struct radius_msg *msg, size_t init_len)
+static int radius_msg_initialize(struct radius_msg *msg)
 {
-	if (msg == NULL || init_len < sizeof(struct radius_hdr))
-		return -1;
-
-	os_memset(msg, 0, sizeof(*msg));
-	msg->buf = os_zalloc(init_len);
-	if (msg->buf == NULL)
-		return -1;
-
-	msg->buf_size = init_len;
-	msg->hdr = (struct radius_hdr *) msg->buf;
-	msg->buf_used = sizeof(*msg->hdr);
-
 	msg->attr_pos =
 		os_zalloc(RADIUS_DEFAULT_ATTR_COUNT * sizeof(*msg->attr_pos));
-	if (msg->attr_pos == NULL) {
-		os_free(msg->buf);
-		msg->buf = NULL;
-		msg->hdr = NULL;
+	if (msg->attr_pos == NULL)
 		return -1;
-	}
 
 	msg->attr_size = RADIUS_DEFAULT_ATTR_COUNT;
 	msg->attr_used = 0;
@@ -76,23 +96,48 @@ int radius_msg_initialize(struct radius_msg *msg, size_t init_len)
 }
 
 
-void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier)
+/**
+ * radius_msg_new - Create a new RADIUS message
+ * @code: Code for RADIUS header
+ * @identifier: Identifier for RADIUS header
+ * Returns: Context for RADIUS message or %NULL on failure
+ *
+ * The caller is responsible for freeing the returned data with
+ * radius_msg_free().
+ */
+struct radius_msg * radius_msg_new(u8 code, u8 identifier)
 {
-	msg->hdr->code = code;
-	msg->hdr->identifier = identifier;
+	struct radius_msg *msg;
+
+	msg = os_zalloc(sizeof(*msg));
+	if (msg == NULL)
+		return NULL;
+
+	msg->buf = wpabuf_alloc(RADIUS_DEFAULT_MSG_SIZE);
+	if (msg->buf == NULL || radius_msg_initialize(msg)) {
+		radius_msg_free(msg);
+		return NULL;
+	}
+	msg->hdr = wpabuf_put(msg->buf, sizeof(struct radius_hdr));
+
+	radius_msg_set_hdr(msg, code, identifier);
+
+	return msg;
 }
 
 
+/**
+ * radius_msg_free - Free a RADIUS message
+ * @msg: RADIUS message from radius_msg_new() or radius_msg_parse()
+ */
 void radius_msg_free(struct radius_msg *msg)
 {
-	os_free(msg->buf);
-	msg->buf = NULL;
-	msg->hdr = NULL;
-	msg->buf_size = msg->buf_used = 0;
+	if (msg == NULL)
+		return;
 
+	wpabuf_free(msg->buf);
 	os_free(msg->attr_pos);
-	msg->attr_pos = NULL;
-	msg->attr_size = msg->attr_used = 0;
+	os_free(msg);
 }
 
 
@@ -305,19 +350,19 @@ int radius_msg_finish(struct radius_msg *msg, const u8 *secret,
 					   RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
 					   auth, MD5_MAC_LEN);
 		if (attr == NULL) {
-			printf("WARNING: Could not add "
-			       "Message-Authenticator\n");
+			wpa_printf(MSG_WARNING, "RADIUS: Could not add "
+				   "Message-Authenticator");
 			return -1;
 		}
-		msg->hdr->length = htons(msg->buf_used);
-		hmac_md5(secret, secret_len, msg->buf, msg->buf_used,
-			 (u8 *) (attr + 1));
+		msg->hdr->length = htons(wpabuf_len(msg->buf));
+		hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
+			 wpabuf_len(msg->buf), (u8 *) (attr + 1));
 	} else
-		msg->hdr->length = htons(msg->buf_used);
+		msg->hdr->length = htons(wpabuf_len(msg->buf));
 
-	if (msg->buf_used > 0xffff) {
-		printf("WARNING: too long RADIUS message (%lu)\n",
-		       (unsigned long) msg->buf_used);
+	if (wpabuf_len(msg->buf) > 0xffff) {
+		wpa_printf(MSG_WARNING, "RADIUS: Too long message (%lu)",
+			   (unsigned long) wpabuf_len(msg->buf));
 		return -1;
 	}
 	return 0;
@@ -339,26 +384,26 @@ int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
 		printf("WARNING: Could not add Message-Authenticator\n");
 		return -1;
 	}
-	msg->hdr->length = htons(msg->buf_used);
+	msg->hdr->length = htons(wpabuf_len(msg->buf));
 	os_memcpy(msg->hdr->authenticator, req_authenticator,
 		  sizeof(msg->hdr->authenticator));
-	hmac_md5(secret, secret_len, msg->buf, msg->buf_used,
-		 (u8 *) (attr + 1));
+	hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
+		 wpabuf_len(msg->buf), (u8 *) (attr + 1));
 
 	/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
 	addr[0] = (u8 *) msg->hdr;
 	len[0] = 1 + 1 + 2;
 	addr[1] = req_authenticator;
 	len[1] = MD5_MAC_LEN;
-	addr[2] = (u8 *) (msg->hdr + 1);
-	len[2] = msg->buf_used - sizeof(*msg->hdr);
+	addr[2] = wpabuf_head_u8(msg->buf) + sizeof(struct radius_hdr);
+	len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr);
 	addr[3] = secret;
 	len[3] = secret_len;
 	md5_vector(4, addr, len, msg->hdr->authenticator);
 
-	if (msg->buf_used > 0xffff) {
-		printf("WARNING: too long RADIUS message (%lu)\n",
-		       (unsigned long) msg->buf_used);
+	if (wpabuf_len(msg->buf) > 0xffff) {
+		wpa_printf(MSG_WARNING, "RADIUS: Too long message (%lu)",
+			   (unsigned long) wpabuf_len(msg->buf));
 		return -1;
 	}
 	return 0;
@@ -371,17 +416,17 @@ void radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret,
 	const u8 *addr[2];
 	size_t len[2];
 
-	msg->hdr->length = htons(msg->buf_used);
+	msg->hdr->length = htons(wpabuf_len(msg->buf));
 	os_memset(msg->hdr->authenticator, 0, MD5_MAC_LEN);
-	addr[0] = msg->buf;
-	len[0] = msg->buf_used;
+	addr[0] = wpabuf_head(msg->buf);
+	len[0] = wpabuf_len(msg->buf);
 	addr[1] = secret;
 	len[1] = secret_len;
 	md5_vector(2, addr, len, msg->hdr->authenticator);
 
-	if (msg->buf_used > 0xffff) {
-		printf("WARNING: too long RADIUS messages (%lu)\n",
-		       (unsigned long) msg->buf_used);
+	if (wpabuf_len(msg->buf) > 0xffff) {
+		wpa_printf(MSG_WARNING, "RADIUS: Too long messages (%lu)",
+			   (unsigned long) wpabuf_len(msg->buf));
 	}
 }
 
@@ -402,7 +447,8 @@ static int radius_msg_add_attr_to_array(struct radius_msg *msg,
 		msg->attr_size = nlen;
 	}
 
-	msg->attr_pos[msg->attr_used++] = (unsigned char *) attr - msg->buf;
+	msg->attr_pos[msg->attr_used++] =
+		(unsigned char *) attr - wpabuf_head_u8(msg->buf);
 
 	return 0;
 }
@@ -420,31 +466,19 @@ struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
 		return NULL;
 	}
 
-	buf_needed = msg->buf_used + sizeof(*attr) + data_len;
+	buf_needed = sizeof(*attr) + data_len;
 
-	if (msg->buf_size < buf_needed) {
+	if (wpabuf_tailroom(msg->buf) < buf_needed) {
 		/* allocate more space for message buffer */
-		unsigned char *nbuf;
-		size_t nlen = msg->buf_size;
-
-		while (nlen < buf_needed)
-			nlen *= 2;
-		nbuf = os_realloc(msg->buf, nlen);
-		if (nbuf == NULL)
+		if (wpabuf_resize(&msg->buf, buf_needed) < 0)
 			return NULL;
-		msg->buf = nbuf;
-		msg->hdr = (struct radius_hdr *) msg->buf;
-		os_memset(msg->buf + msg->buf_size, 0, nlen - msg->buf_size);
-		msg->buf_size = nlen;
+		msg->hdr = wpabuf_mhead(msg->buf);
 	}
 
-	attr = (struct radius_attr_hdr *) (msg->buf + msg->buf_used);
+	attr = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr));
 	attr->type = type;
 	attr->length = sizeof(*attr) + data_len;
-	if (data_len > 0)
-		os_memcpy(attr + 1, data, data_len);
-
-	msg->buf_used += sizeof(*attr) + data_len;
+	wpabuf_put_data(msg->buf, data, data_len);
 
 	if (radius_msg_add_attr_to_array(msg, attr))
 		return NULL;
@@ -453,7 +487,16 @@ struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
 }
 
 
-struct radius_msg *radius_msg_parse(const u8 *data, size_t len)
+/**
+ * radius_msg_parse - Parse a RADIUS message
+ * @data: RADIUS message to be parsed
+ * @len: Length of data buffer in octets
+ * Returns: Parsed RADIUS message or %NULL on failure
+ *
+ * This parses a RADIUS message and makes a copy of its data. The caller is
+ * responsible for freeing the returned data with radius_msg_free().
+ */
+struct radius_msg * radius_msg_parse(const u8 *data, size_t len)
 {
 	struct radius_msg *msg;
 	struct radius_hdr *hdr;
@@ -468,30 +511,29 @@ struct radius_msg *radius_msg_parse(const u8 *data, size_t len)
 
 	msg_len = ntohs(hdr->length);
 	if (msg_len < sizeof(*hdr) || msg_len > len) {
-		printf("Invalid RADIUS message length\n");
+		wpa_printf(MSG_INFO, "RADIUS: Invalid message length");
 		return NULL;
 	}
 
 	if (msg_len < len) {
-		printf("Ignored %lu extra bytes after RADIUS message\n",
-		       (unsigned long) len - msg_len);
+		wpa_printf(MSG_DEBUG, "RADIUS: Ignored %lu extra bytes after "
+			   "RADIUS message", (unsigned long) len - msg_len);
 	}
 
-	msg = os_malloc(sizeof(*msg));
+	msg = os_zalloc(sizeof(*msg));
 	if (msg == NULL)
 		return NULL;
 
-	if (radius_msg_initialize(msg, msg_len)) {
-		os_free(msg);
+	msg->buf = wpabuf_alloc_copy(data, msg_len);
+	if (msg->buf == NULL || radius_msg_initialize(msg)) {
+		radius_msg_free(msg);
 		return NULL;
 	}
-
-	os_memcpy(msg->buf, data, msg_len);
-	msg->buf_size = msg->buf_used = msg_len;
+	msg->hdr = wpabuf_mhead(msg->buf);
 
 	/* parse attributes */
-	pos = (unsigned char *) (msg->hdr + 1);
-	end = msg->buf + msg->buf_used;
+	pos = wpabuf_mhead_u8(msg->buf) + sizeof(struct radius_hdr);
+	end = wpabuf_mhead_u8(msg->buf) + wpabuf_len(msg->buf);
 	while (pos < end) {
 		if ((size_t) (end - pos) < sizeof(*attr))
 			goto fail;
@@ -513,7 +555,6 @@ struct radius_msg *radius_msg_parse(const u8 *data, size_t len)
 
  fail:
 	radius_msg_free(msg);
-	os_free(msg);
 	return NULL;
 }
 
@@ -615,7 +656,8 @@ int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret,
 		os_memcpy(msg->hdr->authenticator, req_auth,
 			  sizeof(msg->hdr->authenticator));
 	}
-	hmac_md5(secret, secret_len, msg->buf, msg->buf_used, auth);
+	hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
+		 wpabuf_len(msg->buf), auth);
 	os_memcpy(attr + 1, orig, MD5_MAC_LEN);
 	if (req_auth) {
 		os_memcpy(msg->hdr->authenticator, orig_authenticator,
@@ -654,8 +696,8 @@ int radius_msg_verify(struct radius_msg *msg, const u8 *secret,
 	len[0] = 1 + 1 + 2;
 	addr[1] = sent_msg->hdr->authenticator;
 	len[1] = MD5_MAC_LEN;
-	addr[2] = (u8 *) (msg->hdr + 1);
-	len[2] = msg->buf_used - sizeof(*msg->hdr);
+	addr[2] = wpabuf_head_u8(msg->buf) + sizeof(struct radius_hdr);
+	len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr);
 	addr[3] = secret;
 	len[3] = secret_len;
 	md5_vector(4, addr, len, hash);
@@ -1232,3 +1274,44 @@ int radius_msg_get_vlanid(struct radius_msg *msg)
 
 	return -1;
 }
+
+
+void radius_free_class(struct radius_class_data *c)
+{
+	size_t i;
+	if (c == NULL)
+		return;
+	for (i = 0; i < c->count; i++)
+		os_free(c->attr[i].data);
+	os_free(c->attr);
+	c->attr = NULL;
+	c->count = 0;
+}
+
+
+int radius_copy_class(struct radius_class_data *dst,
+		      const struct radius_class_data *src)
+{
+	size_t i;
+
+	if (src->attr == NULL)
+		return 0;
+
+	dst->attr = os_zalloc(src->count * sizeof(struct radius_attr_data));
+	if (dst->attr == NULL)
+		return -1;
+
+	dst->count = 0;
+
+	for (i = 0; i < src->count; i++) {
+		dst->attr[i].data = os_malloc(src->attr[i].len);
+		if (dst->attr[i].data == NULL)
+			break;
+		dst->count++;
+		os_memcpy(dst->attr[i].data, src->attr[i].data,
+			  src->attr[i].len);
+		dst->attr[i].len = src->attr[i].len;
+	}
+
+	return 0;
+}
diff --git a/contrib/wpa/src/radius/radius.h b/contrib/wpa/src/radius/radius.h
index c30621dc2eaf..a3cdac0dac0a 100644
--- a/contrib/wpa/src/radius/radius.h
+++ b/contrib/wpa/src/radius/radius.h
@@ -1,6 +1,6 @@
 /*
- * hostapd / RADIUS message processing
- * Copyright (c) 2002-2007, Jouni Malinen 
+ * RADIUS message processing
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -173,21 +173,7 @@ struct radius_ms_mppe_keys {
 };
 
 
-/* RADIUS message structure for new and parsed messages */
-struct radius_msg {
-	unsigned char *buf;
-	size_t buf_size; /* total size allocated for buf */
-	size_t buf_used; /* bytes used in buf */
-
-	struct radius_hdr *hdr;
-
-	size_t *attr_pos; /* array of indexes to attributes (number of bytes
-			   * from buf to the beginning of
-			   * struct radius_attr_hdr). */
-	size_t attr_size; /* total size of the attribute pointer array */
-	size_t attr_used; /* total number of attributes in the array */
-};
-
+struct radius_msg;
 
 /* Default size to be allocated for new RADIUS messages */
 #define RADIUS_DEFAULT_MSG_SIZE 1024
@@ -202,9 +188,9 @@ struct radius_msg {
 /* MAC address ASCII format for non-802.1X use */
 #define RADIUS_ADDR_FORMAT "%02x%02x%02x%02x%02x%02x"
 
-struct radius_msg *radius_msg_new(u8 code, u8 identifier);
-int radius_msg_initialize(struct radius_msg *msg, size_t init_len);
-void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier);
+struct radius_hdr * radius_msg_get_hdr(struct radius_msg *msg);
+struct wpabuf * radius_msg_get_buf(struct radius_msg *msg);
+struct radius_msg * radius_msg_new(u8 code, u8 identifier);
 void radius_msg_free(struct radius_msg *msg);
 void radius_msg_dump(struct radius_msg *msg);
 int radius_msg_finish(struct radius_msg *msg, const u8 *secret,
@@ -213,9 +199,9 @@ int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
 			  size_t secret_len, const u8 *req_authenticator);
 void radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret,
 			    size_t secret_len);
-struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
-					    const u8 *data, size_t data_len);
-struct radius_msg *radius_msg_parse(const u8 *data, size_t len);
+struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u8 type,
+					     const u8 *data, size_t data_len);
+struct radius_msg * radius_msg_parse(const u8 *data, size_t len);
 int radius_msg_add_eap(struct radius_msg *msg, const u8 *data,
 		       size_t data_len);
 u8 *radius_msg_get_eap(struct radius_msg *msg, size_t *len);
@@ -269,4 +255,19 @@ int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf,
 			    size_t *len, const u8 *start);
 int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len);
 
+
+struct radius_attr_data {
+	u8 *data;
+	size_t len;
+};
+
+struct radius_class_data {
+	struct radius_attr_data *attr;
+	size_t count;
+};
+
+void radius_free_class(struct radius_class_data *c);
+int radius_copy_class(struct radius_class_data *dst,
+		      const struct radius_class_data *src);
+
 #endif /* RADIUS_H */
diff --git a/contrib/wpa/src/radius/radius_client.c b/contrib/wpa/src/radius/radius_client.c
index 826acad67840..171af2927b0f 100644
--- a/contrib/wpa/src/radius/radius_client.c
+++ b/contrib/wpa/src/radius/radius_client.c
@@ -1,6 +1,6 @@
 /*
- * hostapd / RADIUS client
- * Copyright (c) 2002-2005, Jouni Malinen 
+ * RADIUS client
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -20,68 +20,217 @@
 #include "eloop.h"
 
 /* Defaults for RADIUS retransmit values (exponential backoff) */
-#define RADIUS_CLIENT_FIRST_WAIT 3 /* seconds */
-#define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */
-#define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts
-				      * before entry is removed from retransmit
-				      * list */
-#define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit
-				      * list (oldest will be removed, if this
-				      * limit is exceeded) */
-#define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this
-				      * many failed retry attempts */
+
+/**
+ * RADIUS_CLIENT_FIRST_WAIT - RADIUS client timeout for first retry in seconds
+ */
+#define RADIUS_CLIENT_FIRST_WAIT 3
+
+/**
+ * RADIUS_CLIENT_MAX_WAIT - RADIUS client maximum retry timeout in seconds
+ */
+#define RADIUS_CLIENT_MAX_WAIT 120
+
+/**
+ * RADIUS_CLIENT_MAX_RETRIES - RADIUS client maximum retries
+ *
+ * Maximum number of retransmit attempts before the entry is removed from
+ * retransmit list.
+ */
+#define RADIUS_CLIENT_MAX_RETRIES 10
+
+/**
+ * RADIUS_CLIENT_MAX_ENTRIES - RADIUS client maximum pending messages
+ *
+ * Maximum number of entries in retransmit list (oldest entries will be
+ * removed, if this limit is exceeded).
+ */
+#define RADIUS_CLIENT_MAX_ENTRIES 30
+
+/**
+ * RADIUS_CLIENT_NUM_FAILOVER - RADIUS client failover point
+ *
+ * The number of failed retry attempts after which the RADIUS server will be
+ * changed (if one of more backup servers are configured).
+ */
+#define RADIUS_CLIENT_NUM_FAILOVER 4
 
 
+/**
+ * struct radius_rx_handler - RADIUS client RX handler
+ *
+ * This data structure is used internally inside the RADIUS client module to
+ * store registered RX handlers. These handlers are registered by calls to
+ * radius_client_register() and unregistered when the RADIUS client is
+ * deinitialized with a call to radius_client_deinit().
+ */
 struct radius_rx_handler {
+	/**
+	 * handler - Received RADIUS message handler
+	 */
 	RadiusRxResult (*handler)(struct radius_msg *msg,
 				  struct radius_msg *req,
 				  const u8 *shared_secret,
 				  size_t shared_secret_len,
 				  void *data);
+
+	/**
+	 * data - Context data for the handler
+	 */
 	void *data;
 };
 
 
-/* RADIUS message retransmit list */
+/**
+ * struct radius_msg_list - RADIUS client message retransmit list
+ *
+ * This data structure is used internally inside the RADIUS client module to
+ * store pending RADIUS requests that may still need to be retransmitted.
+ */
 struct radius_msg_list {
-	u8 addr[ETH_ALEN]; /* STA/client address; used to find RADIUS messages
-			    * for the same STA. */
+	/**
+	 * addr - STA/client address
+	 *
+	 * This is used to find RADIUS messages for the same STA.
+	 */
+	u8 addr[ETH_ALEN];
+
+	/**
+	 * msg - RADIUS message
+	 */
 	struct radius_msg *msg;
+
+	/**
+	 * msg_type - Message type
+	 */
 	RadiusType msg_type;
+
+	/**
+	 * first_try - Time of the first transmission attempt
+	 */
 	os_time_t first_try;
+
+	/**
+	 * next_try - Time for the next transmission attempt
+	 */
 	os_time_t next_try;
+
+	/**
+	 * attempts - Number of transmission attempts
+	 */
 	int attempts;
+
+	/**
+	 * next_wait - Next retransmission wait time in seconds
+	 */
 	int next_wait;
+
+	/**
+	 * last_attempt - Time of the last transmission attempt
+	 */
 	struct os_time last_attempt;
 
-	u8 *shared_secret;
+	/**
+	 * shared_secret - Shared secret with the target RADIUS server
+	 */
+	const u8 *shared_secret;
+
+	/**
+	 * shared_secret_len - shared_secret length in octets
+	 */
 	size_t shared_secret_len;
 
 	/* TODO: server config with failover to backup server(s) */
 
+	/**
+	 * next - Next message in the list
+	 */
 	struct radius_msg_list *next;
 };
 
 
+/**
+ * struct radius_client_data - Internal RADIUS client data
+ *
+ * This data structure is used internally inside the RADIUS client module.
+ * External users allocate this by calling radius_client_init() and free it by
+ * calling radius_client_deinit(). The pointer to this opaque data is used in
+ * calls to other functions as an identifier for the RADIUS client instance.
+ */
 struct radius_client_data {
+	/**
+	 * ctx - Context pointer for hostapd_logger() callbacks
+	 */
 	void *ctx;
+
+	/**
+	 * conf - RADIUS client configuration (list of RADIUS servers to use)
+	 */
 	struct hostapd_radius_servers *conf;
 
-	int auth_serv_sock; /* socket for authentication RADIUS messages */
-	int acct_serv_sock; /* socket for accounting RADIUS messages */
-	int auth_serv_sock6;
-	int acct_serv_sock6;
-	int auth_sock; /* currently used socket */
-	int acct_sock; /* currently used socket */
+	/**
+	 * auth_serv_sock - IPv4 socket for RADIUS authentication messages
+	 */
+	int auth_serv_sock;
 
+	/**
+	 * acct_serv_sock - IPv4 socket for RADIUS accounting messages
+	 */
+	int acct_serv_sock;
+
+	/**
+	 * auth_serv_sock6 - IPv6 socket for RADIUS authentication messages
+	 */
+	int auth_serv_sock6;
+
+	/**
+	 * acct_serv_sock6 - IPv6 socket for RADIUS accounting messages
+	 */
+	int acct_serv_sock6;
+
+	/**
+	 * auth_sock - Currently used socket for RADIUS authentication server
+	 */
+	int auth_sock;
+
+	/**
+	 * acct_sock - Currently used socket for RADIUS accounting server
+	 */
+	int acct_sock;
+
+	/**
+	 * auth_handlers - Authentication message handlers
+	 */
 	struct radius_rx_handler *auth_handlers;
+
+	/**
+	 * num_auth_handlers - Number of handlers in auth_handlers
+	 */
 	size_t num_auth_handlers;
+
+	/**
+	 * acct_handlers - Accounting message handlers
+	 */
 	struct radius_rx_handler *acct_handlers;
+
+	/**
+	 * num_acct_handlers - Number of handlers in acct_handlers
+	 */
 	size_t num_acct_handlers;
 
+	/**
+	 * msgs - Pending outgoing RADIUS messages
+	 */
 	struct radius_msg_list *msgs;
+
+	/**
+	 * num_msgs - Number of pending messages in the msgs list
+	 */
 	size_t num_msgs;
 
+	/**
+	 * next_radius_identifier - Next RADIUS message identifier to use
+	 */
 	u8 next_radius_identifier;
 };
 
@@ -98,11 +247,26 @@ static int radius_client_init_auth(struct radius_client_data *radius);
 static void radius_client_msg_free(struct radius_msg_list *req)
 {
 	radius_msg_free(req->msg);
-	os_free(req->msg);
 	os_free(req);
 }
 
 
+/**
+ * radius_client_register - Register a RADIUS client RX handler
+ * @radius: RADIUS client context from radius_client_init()
+ * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT)
+ * @handler: Handler for received RADIUS messages
+ * @data: Context pointer for handler callbacks
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to register a handler for processing received RADIUS
+ * authentication and accounting messages. The handler() callback function will
+ * be called whenever a RADIUS message is received from the active server.
+ *
+ * There can be multiple registered RADIUS message handlers. The handlers will
+ * be called in order until one of them indicates that it has processed or
+ * queued the message.
+ */
 int radius_client_register(struct radius_client_data *radius,
 			   RadiusType msg_type,
 			   RadiusRxResult (*handler)(struct radius_msg *msg,
@@ -166,6 +330,7 @@ static int radius_client_retransmit(struct radius_client_data *radius,
 {
 	struct hostapd_radius_servers *conf = radius->conf;
 	int s;
+	struct wpabuf *buf;
 
 	if (entry->msg_type == RADIUS_ACCT ||
 	    entry->msg_type == RADIUS_ACCT_INTERIM) {
@@ -190,10 +355,11 @@ static int radius_client_retransmit(struct radius_client_data *radius,
 	entry->attempts++;
 	hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
 		       HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
-		       entry->msg->hdr->identifier);
+		       radius_msg_get_hdr(entry->msg)->identifier);
 
 	os_get_time(&entry->last_attempt);
-	if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0)
+	buf = radius_msg_get_buf(entry->msg);
+	if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0)
 		radius_client_handle_send_error(radius, s, entry->msg_type);
 
 	entry->next_try = now + entry->next_wait;
@@ -351,7 +517,8 @@ static void radius_client_update_timeout(struct radius_client_data *radius)
 
 static void radius_client_list_add(struct radius_client_data *radius,
 				   struct radius_msg *msg,
-				   RadiusType msg_type, u8 *shared_secret,
+				   RadiusType msg_type,
+				   const u8 *shared_secret,
 				   size_t shared_secret_len, const u8 *addr)
 {
 	struct radius_msg_list *entry, *prev;
@@ -360,7 +527,6 @@ static void radius_client_list_add(struct radius_client_data *radius,
 		/* No point in adding entries to retransmit queue since event
 		 * loop has already been terminated. */
 		radius_msg_free(msg);
-		os_free(msg);
 		return;
 	}
 
@@ -368,7 +534,6 @@ static void radius_client_list_add(struct radius_client_data *radius,
 	if (entry == NULL) {
 		printf("Failed to add RADIUS packet into retransmit list\n");
 		radius_msg_free(msg);
-		os_free(msg);
 		return;
 	}
 
@@ -437,15 +602,38 @@ static void radius_client_list_del(struct radius_client_data *radius,
 }
 
 
+/**
+ * radius_client_send - Send a RADIUS request
+ * @radius: RADIUS client context from radius_client_init()
+ * @msg: RADIUS message to be sent
+ * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM)
+ * @addr: MAC address of the device related to this message or %NULL
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
+ * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
+ * between accounting and interim accounting messages is that the interim
+ * message will override any pending interim accounting updates while a new
+ * accounting message does not remove any pending messages.
+ *
+ * The message is added on the retransmission queue and will be retransmitted
+ * automatically until a response is received or maximum number of retries
+ * (RADIUS_CLIENT_MAX_RETRIES) is reached.
+ *
+ * The related device MAC address can be used to identify pending messages that
+ * can be removed with radius_client_flush_auth() or with interim accounting
+ * updates.
+ */
 int radius_client_send(struct radius_client_data *radius,
 		       struct radius_msg *msg, RadiusType msg_type,
 		       const u8 *addr)
 {
 	struct hostapd_radius_servers *conf = radius->conf;
-	u8 *shared_secret;
+	const u8 *shared_secret;
 	size_t shared_secret_len;
 	char *name;
 	int s, res;
+	struct wpabuf *buf;
 
 	if (msg_type == RADIUS_ACCT_INTERIM) {
 		/* Remove any pending interim acct update for the same STA. */
@@ -488,7 +676,8 @@ int radius_client_send(struct radius_client_data *radius,
 	if (conf->msg_dumps)
 		radius_msg_dump(msg);
 
-	res = send(s, msg->buf, msg->buf_used, 0);
+	buf = radius_msg_get_buf(msg);
+	res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0);
 	if (res < 0)
 		radius_client_handle_send_error(radius, s, msg_type);
 
@@ -507,6 +696,7 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
 	int len, roundtrip;
 	unsigned char buf[3000];
 	struct radius_msg *msg;
+	struct radius_hdr *hdr;
 	struct radius_rx_handler *handlers;
 	size_t num_handlers, i;
 	struct radius_msg_list *req, *prev_req;
@@ -544,13 +734,14 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
 		rconf->malformed_responses++;
 		return;
 	}
+	hdr = radius_msg_get_hdr(msg);
 
 	hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
 		       HOSTAPD_LEVEL_DEBUG, "Received RADIUS message");
 	if (conf->msg_dumps)
 		radius_msg_dump(msg);
 
-	switch (msg->hdr->code) {
+	switch (hdr->code) {
 	case RADIUS_CODE_ACCESS_ACCEPT:
 		rconf->access_accepts++;
 		break;
@@ -573,7 +764,8 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
 		if ((req->msg_type == msg_type ||
 		     (req->msg_type == RADIUS_ACCT_INTERIM &&
 		      msg_type == RADIUS_ACCT)) &&
-		    req->msg->hdr->identifier == msg->hdr->identifier)
+		    radius_msg_get_hdr(req->msg)->identifier ==
+		    hdr->identifier)
 			break;
 
 		prev_req = req;
@@ -585,7 +777,7 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
 			       HOSTAPD_LEVEL_DEBUG,
 			       "No matching RADIUS request found (type=%d "
 			       "id=%d) - dropping packet",
-			       msg_type, msg->hdr->identifier);
+			       msg_type, hdr->identifier);
 		goto fail;
 	}
 
@@ -614,7 +806,6 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
 		switch (res) {
 		case RADIUS_RX_PROCESSED:
 			radius_msg_free(msg);
-			os_free(msg);
 			/* continue */
 		case RADIUS_RX_QUEUED:
 			radius_client_msg_free(req);
@@ -635,17 +826,24 @@ static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx)
 	hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
 		       HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found "
 		       "(type=%d code=%d id=%d)%s - dropping packet",
-		       msg_type, msg->hdr->code, msg->hdr->identifier,
+		       msg_type, hdr->code, hdr->identifier,
 		       invalid_authenticator ? " [INVALID AUTHENTICATOR]" :
 		       "");
 	radius_client_msg_free(req);
 
  fail:
 	radius_msg_free(msg);
-	os_free(msg);
 }
 
 
+/**
+ * radius_client_get_id - Get an identifier for a new RADIUS message
+ * @radius: RADIUS client context from radius_client_init()
+ * Returns: Allocated identifier
+ *
+ * This function is used to fetch a unique (among pending requests) identifier
+ * for a new RADIUS message.
+ */
 u8 radius_client_get_id(struct radius_client_data *radius)
 {
 	struct radius_msg_list *entry, *prev, *_remove;
@@ -656,7 +854,7 @@ u8 radius_client_get_id(struct radius_client_data *radius)
 	entry = radius->msgs;
 	prev = NULL;
 	while (entry) {
-		if (entry->msg->hdr->identifier == id) {
+		if (radius_msg_get_hdr(entry->msg)->identifier == id) {
 			hostapd_logger(radius->ctx, entry->addr,
 				       HOSTAPD_MODULE_RADIUS,
 				       HOSTAPD_LEVEL_DEBUG,
@@ -681,6 +879,11 @@ u8 radius_client_get_id(struct radius_client_data *radius)
 }
 
 
+/**
+ * radius_client_flush - Flush all pending RADIUS client messages
+ * @radius: RADIUS client context from radius_client_init()
+ * @only_auth: Whether only authentication messages are removed
+ */
 void radius_client_flush(struct radius_client_data *radius, int only_auth)
 {
 	struct radius_msg_list *entry, *prev, *tmp;
@@ -714,7 +917,7 @@ void radius_client_flush(struct radius_client_data *radius, int only_auth)
 
 
 static void radius_client_update_acct_msgs(struct radius_client_data *radius,
-					   u8 *shared_secret,
+					   const u8 *shared_secret,
 					   size_t shared_secret_len)
 {
 	struct radius_msg_list *entry;
@@ -1037,6 +1240,16 @@ static int radius_client_init_acct(struct radius_client_data *radius)
 }
 
 
+/**
+ * radius_client_init - Initialize RADIUS client
+ * @ctx: Callback context to be used in hostapd_logger() calls
+ * @conf: RADIUS client configuration (RADIUS servers)
+ * Returns: Pointer to private RADIUS client context or %NULL on failure
+ *
+ * The caller is responsible for keeping the configuration data available for
+ * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is
+ * called for the returned context pointer.
+ */
 struct radius_client_data *
 radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
 {
@@ -1071,6 +1284,10 @@ radius_client_init(void *ctx, struct hostapd_radius_servers *conf)
 }
 
 
+/**
+ * radius_client_deinit - Deinitialize RADIUS client
+ * @radius: RADIUS client context from radius_client_init()
+ */
 void radius_client_deinit(struct radius_client_data *radius)
 {
 	if (!radius)
@@ -1096,7 +1313,18 @@ void radius_client_deinit(struct radius_client_data *radius)
 }
 
 
-void radius_client_flush_auth(struct radius_client_data *radius, u8 *addr)
+/**
+ * radius_client_flush_auth - Flush pending RADIUS messages for an address
+ * @radius: RADIUS client context from radius_client_init()
+ * @addr: MAC address of the related device
+ *
+ * This function can be used to remove pending RADIUS authentication messages
+ * that are related to a specific device. The addr parameter is matched with
+ * the one used in radius_client_send() call that was used to transmit the
+ * authentication request.
+ */
+void radius_client_flush_auth(struct radius_client_data *radius,
+			      const u8 *addr)
 {
 	struct radius_msg_list *entry, *prev, *tmp;
 
@@ -1224,6 +1452,13 @@ static int radius_client_dump_acct_server(char *buf, size_t buflen,
 }
 
 
+/**
+ * radius_client_get_mib - Get RADIUS client MIB information
+ * @radius: RADIUS client context from radius_client_init()
+ * @buf: Buffer for returning MIB data in text format
+ * @buflen: Maximum buf length in octets
+ * Returns: Number of octets written into the buffer
+ */
 int radius_client_get_mib(struct radius_client_data *radius, char *buf,
 			  size_t buflen)
 {
@@ -1254,48 +1489,3 @@ int radius_client_get_mib(struct radius_client_data *radius, char *buf,
 
 	return count;
 }
-
-
-static int radius_servers_diff(struct hostapd_radius_server *nserv,
-			       struct hostapd_radius_server *oserv,
-			       int num)
-{
-	int i;
-
-	for (i = 0; i < num; i++) {
-		if (hostapd_ip_diff(&nserv[i].addr, &oserv[i].addr) ||
-		    nserv[i].port != oserv[i].port ||
-		    nserv[i].shared_secret_len != oserv[i].shared_secret_len ||
-		    os_memcmp(nserv[i].shared_secret, oserv[i].shared_secret,
-			      nserv[i].shared_secret_len) != 0)
-			return 1;
-	}
-
-	return 0;
-}
-
-
-struct radius_client_data *
-radius_client_reconfig(struct radius_client_data *old, void *ctx,
-		       struct hostapd_radius_servers *oldconf,
-		       struct hostapd_radius_servers *newconf)
-{
-	radius_client_flush(old, 0);
-
-	if (newconf->retry_primary_interval !=
-	    oldconf->retry_primary_interval ||
-	    newconf->num_auth_servers != oldconf->num_auth_servers ||
-	    newconf->num_acct_servers != oldconf->num_acct_servers ||
-	    radius_servers_diff(newconf->auth_servers, oldconf->auth_servers,
-				newconf->num_auth_servers) ||
-	    radius_servers_diff(newconf->acct_servers, oldconf->acct_servers,
-				newconf->num_acct_servers)) {
-		hostapd_logger(ctx, NULL, HOSTAPD_MODULE_RADIUS,
-			       HOSTAPD_LEVEL_DEBUG,
-			       "Reconfiguring RADIUS client");
-		radius_client_deinit(old);
-		return radius_client_init(ctx, newconf);
-	}
-
-	return old;
-}
diff --git a/contrib/wpa/src/radius/radius_client.h b/contrib/wpa/src/radius/radius_client.h
index 4fe9ba9a42c7..644ea234fd25 100644
--- a/contrib/wpa/src/radius/radius_client.h
+++ b/contrib/wpa/src/radius/radius_client.h
@@ -1,6 +1,6 @@
 /*
- * hostapd / RADIUS client
- * Copyright (c) 2002-2005, Jouni Malinen 
+ * RADIUS client
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -19,63 +19,222 @@
 
 struct radius_msg;
 
+/**
+ * struct hostapd_radius_server - RADIUS server information for RADIUS client
+ *
+ * This structure contains information about a RADIUS server. The values are
+ * mainly for MIB information. The MIB variable prefix (radiusAuth or
+ * radiusAcc) depends on whether this is an authentication or accounting
+ * server.
+ *
+ * radiusAuthClientPendingRequests (or radiusAccClientPendingRequests) is the
+ * number struct radius_client_data::msgs for matching msg_type.
+ */
 struct hostapd_radius_server {
-	/* MIB prefix for shared variables:
-	 * @ = radiusAuth or radiusAcc depending on the type of the server */
-	struct hostapd_ip_addr addr; /* @ServerAddress */
-	int port; /* @ClientServerPortNumber */
+	/**
+	 * addr - radiusAuthServerAddress or radiusAccServerAddress
+	 */
+	struct hostapd_ip_addr addr;
+
+	/**
+	 * port - radiusAuthClientServerPortNumber or radiusAccClientServerPortNumber
+	 */
+	int port;
+
+	/**
+	 * shared_secret - Shared secret for authenticating RADIUS messages
+	 */
 	u8 *shared_secret;
+
+	/**
+	 * shared_secret_len - Length of shared_secret in octets
+	 */
 	size_t shared_secret_len;
 
 	/* Dynamic (not from configuration file) MIB data */
-	int index; /* @ServerIndex */
-	int round_trip_time; /* @ClientRoundTripTime; in hundredths of a
-			      * second */
-	u32 requests; /* @Client{Access,}Requests */
-	u32 retransmissions; /* @Client{Access,}Retransmissions */
-	u32 access_accepts; /* radiusAuthClientAccessAccepts */
-	u32 access_rejects; /* radiusAuthClientAccessRejects */
-	u32 access_challenges; /* radiusAuthClientAccessChallenges */
-	u32 responses; /* radiusAccClientResponses */
-	u32 malformed_responses; /* @ClientMalformed{Access,}Responses */
-	u32 bad_authenticators; /* @ClientBadAuthenticators */
-	u32 timeouts; /* @ClientTimeouts */
-	u32 unknown_types; /* @ClientUnknownTypes */
-	u32 packets_dropped; /* @ClientPacketsDropped */
-	/* @ClientPendingRequests: length of hapd->radius->msgs for matching
-	 * msg_type */
+
+	/**
+	 * index - radiusAuthServerIndex or radiusAccServerIndex
+	 */
+	int index;
+
+	/**
+	 * round_trip_time - radiusAuthClientRoundTripTime or radiusAccClientRoundTripTime
+	 * Round-trip time in hundredths of a second.
+	 */
+	int round_trip_time;
+
+	/**
+	 * requests - radiusAuthClientAccessRequests or radiusAccClientRequests
+	 */
+	u32 requests;
+
+	/**
+	 * retransmissions - radiusAuthClientAccessRetransmissions or radiusAccClientRetransmissions
+	 */
+	u32 retransmissions;
+
+	/**
+	 * access_accepts - radiusAuthClientAccessAccepts
+	 */
+	u32 access_accepts;
+
+	/**
+	 * access_rejects - radiusAuthClientAccessRejects
+	 */
+	u32 access_rejects;
+
+	/**
+	 * access_challenges - radiusAuthClientAccessChallenges
+	 */
+	u32 access_challenges;
+
+	/**
+	 * responses - radiusAccClientResponses
+	 */
+	u32 responses;
+
+	/**
+	 * malformed_responses - radiusAuthClientMalformedAccessResponses or radiusAccClientMalformedResponses
+	 */
+	u32 malformed_responses;
+
+	/**
+	 * bad_authenticators - radiusAuthClientBadAuthenticators or radiusAccClientBadAuthenticators
+	 */
+	u32 bad_authenticators;
+
+	/**
+	 * timeouts - radiusAuthClientTimeouts or radiusAccClientTimeouts
+	 */
+	u32 timeouts;
+
+	/**
+	 * unknown_types - radiusAuthClientUnknownTypes or radiusAccClientUnknownTypes
+	 */
+	u32 unknown_types;
+
+	/**
+	 * packets_dropped - radiusAuthClientPacketsDropped or radiusAccClientPacketsDropped
+	 */
+	u32 packets_dropped;
 };
 
+/**
+ * struct hostapd_radius_servers - RADIUS servers for RADIUS client
+ */
 struct hostapd_radius_servers {
-	/* RADIUS Authentication and Accounting servers in priority order */
-	struct hostapd_radius_server *auth_servers, *auth_server;
+	/**
+	 * auth_servers - RADIUS Authentication servers in priority order
+	 */
+	struct hostapd_radius_server *auth_servers;
+
+	/**
+	 * num_auth_servers - Number of auth_servers entries
+	 */
 	int num_auth_servers;
-	struct hostapd_radius_server *acct_servers, *acct_server;
+
+	/**
+	 * auth_server - The current Authentication server
+	 */
+	struct hostapd_radius_server *auth_server;
+
+	/**
+	 * acct_servers - RADIUS Accounting servers in priority order
+	 */
+	struct hostapd_radius_server *acct_servers;
+
+	/**
+	 * num_acct_servers - Number of acct_servers entries
+	 */
 	int num_acct_servers;
 
-	int retry_primary_interval;
-	int acct_interim_interval;
+	/**
+	 * acct_server - The current Accounting server
+	 */
+	struct hostapd_radius_server *acct_server;
 
+	/**
+	 * retry_primary_interval - Retry interval for trying primary server
+	 *
+	 * This specifies a retry interval in sexconds for trying to return to
+	 * the primary RADIUS server. 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 (non-zero), the primary server
+	 * will be retried after the specified number of seconds has passed
+	 * even if the current used secondary server is still working.
+	 */
+	int retry_primary_interval;
+
+	/**
+	 * msg_dumps - Whether RADIUS message details are shown in stdout
+	 */
 	int msg_dumps;
 
+	/**
+	 * client_addr - Client (local) address to use if force_client_addr
+	 */
 	struct hostapd_ip_addr client_addr;
+
+	/**
+	 * force_client_addr - Whether to force client (local) address
+	 */
 	int force_client_addr;
 };
 
 
+/**
+ * RadiusType - RADIUS server type for RADIUS client
+ */
 typedef enum {
+	/**
+	 * RADIUS authentication
+	 */
 	RADIUS_AUTH,
+
+	/**
+	 * RADIUS_ACCT - RADIUS accounting
+	 */
 	RADIUS_ACCT,
-	RADIUS_ACCT_INTERIM /* used only with radius_client_send(); just like
-			     * RADIUS_ACCT, but removes any pending interim
-			     * RADIUS Accounting packages for the same STA
-			     * before sending the new interim update */
+
+	/**
+	 * RADIUS_ACCT_INTERIM - RADIUS interim accounting message
+	 *
+	 * Used only with radius_client_send(). This behaves just like
+	 * RADIUS_ACCT, but removes any pending interim RADIUS Accounting
+	 * messages for the same STA before sending the new interim update.
+	 */
+	RADIUS_ACCT_INTERIM
 } RadiusType;
 
+/**
+ * RadiusRxResult - RADIUS client RX handler result
+ */
 typedef enum {
+	/**
+	 * RADIUS_RX_PROCESSED - Message processed
+	 *
+	 * This stops handler calls and frees the message.
+	 */
 	RADIUS_RX_PROCESSED,
+
+	/**
+	 * RADIUS_RX_QUEUED - Message has been queued
+	 *
+	 * This stops handler calls, but does not free the message; the handler
+	 * that returned this is responsible for eventually freeing the
+	 * message.
+	 */
 	RADIUS_RX_QUEUED,
+
+	/**
+	 * RADIUS_RX_UNKNOWN - Message is not for this handler
+	 */
 	RADIUS_RX_UNKNOWN,
+
+	/**
+	 * RADIUS_RX_INVALID_AUTHENTICATOR - Message has invalid Authenticator
+	 */
 	RADIUS_RX_INVALID_AUTHENTICATOR
 } RadiusRxResult;
 
@@ -92,17 +251,13 @@ int radius_client_send(struct radius_client_data *radius,
 		       struct radius_msg *msg,
 		       RadiusType msg_type, const u8 *addr);
 u8 radius_client_get_id(struct radius_client_data *radius);
-
 void radius_client_flush(struct radius_client_data *radius, int only_auth);
 struct radius_client_data *
 radius_client_init(void *ctx, struct hostapd_radius_servers *conf);
 void radius_client_deinit(struct radius_client_data *radius);
-void radius_client_flush_auth(struct radius_client_data *radius, u8 *addr);
+void radius_client_flush_auth(struct radius_client_data *radius,
+			      const u8 *addr);
 int radius_client_get_mib(struct radius_client_data *radius, char *buf,
 			  size_t buflen);
-struct radius_client_data *
-radius_client_reconfig(struct radius_client_data *old, void *ctx,
-		       struct hostapd_radius_servers *oldconf,
-		       struct hostapd_radius_servers *newconf);
 
 #endif /* RADIUS_CLIENT_H */
diff --git a/contrib/wpa/src/radius/radius_server.c b/contrib/wpa/src/radius/radius_server.c
index 4f399bcfd18d..f8780a692947 100644
--- a/contrib/wpa/src/radius/radius_server.c
+++ b/contrib/wpa/src/radius/radius_server.c
@@ -1,6 +1,6 @@
 /*
- * hostapd / RADIUS authentication server
- * Copyright (c) 2005-2008, Jouni Malinen 
+ * RADIUS authentication server
+ * Copyright (c) 2005-2009, Jouni Malinen 
  *
  * 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
@@ -18,12 +18,22 @@
 #include "common.h"
 #include "radius.h"
 #include "eloop.h"
-#include "defs.h"
 #include "eap_server/eap.h"
 #include "radius_server.h"
 
+/**
+ * RADIUS_SESSION_TIMEOUT - Session timeout in seconds
+ */
 #define RADIUS_SESSION_TIMEOUT 60
+
+/**
+ * RADIUS_MAX_SESSION - Maximum number of active sessions
+ */
 #define RADIUS_MAX_SESSION 100
+
+/**
+ * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages
+ */
 #define RADIUS_MAX_MSG_LEN 3000
 
 static struct eapol_callbacks radius_server_eapol_cb;
@@ -31,6 +41,9 @@ static struct eapol_callbacks radius_server_eapol_cb;
 struct radius_client;
 struct radius_server_data;
 
+/**
+ * struct radius_server_counters - RADIUS server statistics counters
+ */
 struct radius_server_counters {
 	u32 access_requests;
 	u32 invalid_requests;
@@ -44,6 +57,9 @@ struct radius_server_counters {
 	u32 unknown_types;
 };
 
+/**
+ * struct radius_session - Internal RADIUS server data for a session
+ */
 struct radius_session {
 	struct radius_session *next;
 	struct radius_client *client;
@@ -62,6 +78,9 @@ struct radius_session {
 	u8 last_authenticator[16];
 };
 
+/**
+ * struct radius_client - Internal RADIUS server data for a client
+ */
 struct radius_client {
 	struct radius_client *next;
 	struct in_addr addr;
@@ -76,31 +95,196 @@ struct radius_client {
 	struct radius_server_counters counters;
 };
 
+/**
+ * struct radius_server_data - Internal RADIUS server data
+ */
 struct radius_server_data {
+	/**
+	 * auth_sock - Socket for RADIUS authentication messages
+	 */
 	int auth_sock;
+
+	/**
+	 * clients - List of authorized RADIUS clients
+	 */
 	struct radius_client *clients;
+
+	/**
+	 * next_sess_id - Next session identifier
+	 */
 	unsigned int next_sess_id;
+
+	/**
+	 * conf_ctx - Context pointer for callbacks
+	 *
+	 * This is used as the ctx argument in get_eap_user() calls.
+	 */
 	void *conf_ctx;
+
+	/**
+	 * num_sess - Number of active sessions
+	 */
 	int num_sess;
+
+	/**
+	 * eap_sim_db_priv - EAP-SIM/AKA database context
+	 *
+	 * This is passed to the EAP-SIM/AKA server implementation as a
+	 * callback context.
+	 */
 	void *eap_sim_db_priv;
+
+	/**
+	 * ssl_ctx - TLS context
+	 *
+	 * This is passed to the EAP server implementation as a callback
+	 * context for TLS operations.
+	 */
 	void *ssl_ctx;
+
+	/**
+	 * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST
+	 *
+	 * This parameter is used to set a key for EAP-FAST to encrypt the
+	 * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If
+	 * set, must point to a 16-octet key.
+	 */
 	u8 *pac_opaque_encr_key;
+
+	/**
+	 * eap_fast_a_id - EAP-FAST authority identity (A-ID)
+	 *
+	 * If EAP-FAST is not used, this can be set to %NULL. 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 recommended to use
+	 * that length for the field to provide interoperability with deployed
+	 * peer implementations.
+	 */
 	u8 *eap_fast_a_id;
+
+	/**
+	 * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets
+	 */
 	size_t eap_fast_a_id_len;
+
+	/**
+	 * eap_fast_a_id_info - EAP-FAST authority identifier information
+	 *
+	 * This A-ID-Info contains a user-friendly name for the A-ID. For
+	 * example, this could be the enterprise and server names in
+	 * human-readable format. This field is encoded as UTF-8. If EAP-FAST
+	 * is not used, this can be set to %NULL.
+	 */
 	char *eap_fast_a_id_info;
+
+	/**
+	 * eap_fast_prov - EAP-FAST provisioning modes
+	 *
+	 * 0 = provisioning disabled, 1 = only anonymous provisioning allowed,
+	 * 2 = only authenticated provisioning allowed, 3 = both provisioning
+	 * modes allowed.
+	 */
 	int eap_fast_prov;
+
+	/**
+	 * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds
+	 *
+	 * This is the hard limit on how long a provisioned PAC-Key can be
+	 * used.
+	 */
 	int pac_key_lifetime;
+
+	/**
+	 * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds
+	 *
+	 * This is a soft limit on the PAC-Key. The server will automatically
+	 * generate a new PAC-Key when this number of seconds (or fewer) of the
+	 * lifetime remains.
+	 */
 	int pac_key_refresh_time;
+
+	/**
+	 * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
+	 *
+	 * This controls whether the protected success/failure indication
+	 * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA.
+	 */
 	int eap_sim_aka_result_ind;
+
+	/**
+	 * tnc - Trusted Network Connect (TNC)
+	 *
+	 * This controls whether TNC is enabled and 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.
+	 */
 	int tnc;
+
+	/**
+	 * wps - Wi-Fi Protected Setup context
+	 *
+	 * If WPS is used with an external RADIUS server (which is quite
+	 * unlikely configuration), this is used to provide a pointer to WPS
+	 * context data. Normally, this can be set to %NULL.
+	 */
 	struct wps_context *wps;
+
+	/**
+	 * ipv6 - Whether to enable IPv6 support in the RADIUS server
+	 */
 	int ipv6;
+
+	/**
+	 * start_time - Timestamp of server start
+	 */
 	struct os_time start_time;
+
+	/**
+	 * counters - Statistics counters for server operations
+	 *
+	 * These counters are the sum over all clients.
+	 */
 	struct radius_server_counters counters;
+
+	/**
+	 * get_eap_user - Callback for fetching EAP user information
+	 * @ctx: Context data from conf_ctx
+	 * @identity: User identity
+	 * @identity_len: identity buffer length in octets
+	 * @phase2: Whether this is for Phase 2 identity
+	 * @user: Data structure for filling in the user information
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This is used to fetch information from user database. The callback
+	 * will fill in information about allowed EAP methods and the user
+	 * password. The password field will be an allocated copy of the
+	 * password data and RADIUS server will free it after use.
+	 */
 	int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
 			    int phase2, struct eap_user *user);
+
+	/**
+	 * eap_req_id_text - Optional data for EAP-Request/Identity
+	 *
+	 * This can be used to configure an optional, displayable message that
+	 * will be sent in EAP-Request/Identity. This string can contain an
+	 * ASCII-0 character (nul) to separate network infromation per RFC
+	 * 4284. The actual string length is explicit provided in
+	 * eap_req_id_text_len since nul character will not be used as a string
+	 * terminator.
+	 */
 	char *eap_req_id_text;
+
+	/**
+	 * eap_req_id_text_len - Length of eap_req_id_text buffer in octets
+	 */
 	size_t eap_req_id_text_len;
+
+	/*
+	 * msg_ctx - Context data for wpa_msg() calls
+	 */
+	void *msg_ctx;
 };
 
 
@@ -182,15 +366,9 @@ static void radius_server_session_free(struct radius_server_data *data,
 	eloop_cancel_timeout(radius_server_session_timeout, data, sess);
 	eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess);
 	eap_server_sm_deinit(sess->eap);
-	if (sess->last_msg) {
-		radius_msg_free(sess->last_msg);
-		os_free(sess->last_msg);
-	}
+	radius_msg_free(sess->last_msg);
 	os_free(sess->last_from_addr);
-	if (sess->last_reply) {
-		radius_msg_free(sess->last_reply);
-		os_free(sess->last_reply);
-	}
+	radius_msg_free(sess->last_reply);
 	os_free(sess);
 	data->num_sess--;
 }
@@ -313,6 +491,7 @@ radius_server_get_new_session(struct radius_server_data *data,
 
 	os_memset(&eap_conf, 0, sizeof(eap_conf));
 	eap_conf.ssl_ctx = data->ssl_ctx;
+	eap_conf.msg_ctx = data->msg_ctx;
 	eap_conf.eap_sim_db_priv = data->eap_sim_db_priv;
 	eap_conf.backend_auth = TRUE;
 	eap_conf.eap_server = 1;
@@ -353,6 +532,7 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
 	struct radius_msg *msg;
 	int code;
 	unsigned int sess_id;
+	struct radius_hdr *hdr = radius_msg_get_hdr(request);
 
 	if (sess->eap_if->eapFail) {
 		sess->eap_if->eapFail = FALSE;
@@ -365,7 +545,7 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
 		code = RADIUS_CODE_ACCESS_CHALLENGE;
 	}
 
-	msg = radius_msg_new(code, request->hdr->identifier);
+	msg = radius_msg_new(code, hdr->identifier);
 	if (msg == NULL) {
 		RADIUS_DEBUG("Failed to allocate reply message");
 		return NULL;
@@ -391,7 +571,7 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
 		} else {
 			len = sess->eap_if->eapKeyDataLen / 2;
 		}
-		if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator,
+		if (!radius_msg_add_mppe_keys(msg, hdr->authenticator,
 					      (u8 *) client->shared_secret,
 					      client->shared_secret_len,
 					      sess->eap_if->eapKeyData + len,
@@ -404,13 +584,12 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
 	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
 		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
 		radius_msg_free(msg);
-		os_free(msg);
 		return NULL;
 	}
 
 	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
 				  client->shared_secret_len,
-				  request->hdr->authenticator) < 0) {
+				  hdr->authenticator) < 0) {
 		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
 	}
 
@@ -427,12 +606,13 @@ static int radius_server_reject(struct radius_server_data *data,
 	struct radius_msg *msg;
 	int ret = 0;
 	struct eap_hdr eapfail;
+	struct wpabuf *buf;
+	struct radius_hdr *hdr = radius_msg_get_hdr(request);
 
 	RADIUS_DEBUG("Reject invalid request from %s:%d",
 		     from_addr, from_port);
 
-	msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT,
-			     request->hdr->identifier);
+	msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier);
 	if (msg == NULL) {
 		return -1;
 	}
@@ -449,13 +629,13 @@ static int radius_server_reject(struct radius_server_data *data,
 	if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
 		RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)");
 		radius_msg_free(msg);
-		os_free(msg);
 		return -1;
 	}
 
 	if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
 				  client->shared_secret_len,
-				  request->hdr->authenticator) < 0) {
+				  hdr->authenticator) <
+	    0) {
 		RADIUS_DEBUG("Failed to add Message-Authenticator attribute");
 	}
 
@@ -465,14 +645,14 @@ static int radius_server_reject(struct radius_server_data *data,
 
 	data->counters.access_rejects++;
 	client->counters.access_rejects++;
-	if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0,
+	buf = radius_msg_get_buf(msg);
+	if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0,
 		   (struct sockaddr *) from, sizeof(*from)) < 0) {
 		perror("sendto[RADIUS SRV]");
 		ret = -1;
 	}
 
 	radius_msg_free(msg);
-	os_free(msg);
 
 	return ret;
 }
@@ -526,16 +706,18 @@ static int radius_server_request(struct radius_server_data *data,
 	}
 
 	if (sess->last_from_port == from_port &&
-	    sess->last_identifier == msg->hdr->identifier &&
-	    os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) ==
-	    0) {
+	    sess->last_identifier == radius_msg_get_hdr(msg)->identifier &&
+	    os_memcmp(sess->last_authenticator,
+		      radius_msg_get_hdr(msg)->authenticator, 16) == 0) {
 		RADIUS_DEBUG("Duplicate message from %s", from_addr);
 		data->counters.dup_access_requests++;
 		client->counters.dup_access_requests++;
 
 		if (sess->last_reply) {
-			res = sendto(data->auth_sock, sess->last_reply->buf,
-				     sess->last_reply->buf_used, 0,
+			struct wpabuf *buf;
+			buf = radius_msg_get_buf(sess->last_reply);
+			res = sendto(data->auth_sock, wpabuf_head(buf),
+				     wpabuf_len(buf), 0,
 				     (struct sockaddr *) from, fromlen);
 			if (res < 0) {
 				perror("sendto[RADIUS SRV]");
@@ -583,10 +765,7 @@ static int radius_server_request(struct radius_server_data *data,
 		RADIUS_DEBUG("No EAP data from the state machine, but eapFail "
 			     "set");
 	} else if (eap_sm_method_pending(sess->eap)) {
-		if (sess->last_msg) {
-			radius_msg_free(sess->last_msg);
-			os_free(sess->last_msg);
-		}
+		radius_msg_free(sess->last_msg);
 		sess->last_msg = msg;
 		sess->last_from_port = from_port;
 		os_free(sess->last_from_addr);
@@ -609,12 +788,15 @@ static int radius_server_request(struct radius_server_data *data,
 	reply = radius_server_encapsulate_eap(data, client, sess, msg);
 
 	if (reply) {
+		struct wpabuf *buf;
+		struct radius_hdr *hdr;
+
 		RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port);
 		if (wpa_debug_level <= MSG_MSGDUMP) {
 			radius_msg_dump(reply);
 		}
 
-		switch (reply->hdr->code) {
+		switch (radius_msg_get_hdr(reply)->code) {
 		case RADIUS_CODE_ACCESS_ACCEPT:
 			data->counters.access_accepts++;
 			client->counters.access_accepts++;
@@ -628,20 +810,19 @@ static int radius_server_request(struct radius_server_data *data,
 			client->counters.access_challenges++;
 			break;
 		}
-		res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0,
+		buf = radius_msg_get_buf(reply);
+		res = sendto(data->auth_sock, wpabuf_head(buf),
+			     wpabuf_len(buf), 0,
 			     (struct sockaddr *) from, fromlen);
 		if (res < 0) {
 			perror("sendto[RADIUS SRV]");
 		}
-		if (sess->last_reply) {
-			radius_msg_free(sess->last_reply);
-			os_free(sess->last_reply);
-		}
+		radius_msg_free(sess->last_reply);
 		sess->last_reply = reply;
 		sess->last_from_port = from_port;
-		sess->last_identifier = msg->hdr->identifier;
-		os_memcpy(sess->last_authenticator, msg->hdr->authenticator,
-			  16);
+		hdr = radius_msg_get_hdr(msg);
+		sess->last_identifier = hdr->identifier;
+		os_memcpy(sess->last_authenticator, hdr->authenticator, 16);
 	} else {
 		data->counters.packets_dropped++;
 		client->counters.packets_dropped++;
@@ -740,8 +921,9 @@ static void radius_server_receive_auth(int sock, void *eloop_ctx,
 		radius_msg_dump(msg);
 	}
 
-	if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) {
-		RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->code);
+	if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) {
+		RADIUS_DEBUG("Unexpected RADIUS code %d",
+			     radius_msg_get_hdr(msg)->code);
 		data->counters.unknown_types++;
 		client->counters.unknown_types++;
 		goto fail;
@@ -764,10 +946,7 @@ static void radius_server_receive_auth(int sock, void *eloop_ctx,
 		return; /* msg was stored with the session */
 
 fail:
-	if (msg) {
-		radius_msg_free(msg);
-		os_free(msg);
-	}
+	radius_msg_free(msg);
 	os_free(buf);
 }
 
@@ -1026,6 +1205,15 @@ radius_server_read_clients(const char *client_file, int ipv6)
 }
 
 
+/**
+ * radius_server_init - Initialize RADIUS server
+ * @conf: Configuration for the RADIUS server
+ * Returns: Pointer to private RADIUS server context or %NULL on failure
+ *
+ * This initializes a RADIUS server instance and returns a context pointer that
+ * will be used in other calls to the RADIUS server module. The server can be
+ * deinitialize by calling radius_server_deinit().
+ */
 struct radius_server_data *
 radius_server_init(struct radius_server_conf *conf)
 {
@@ -1047,6 +1235,7 @@ radius_server_init(struct radius_server_conf *conf)
 	data->conf_ctx = conf->conf_ctx;
 	data->eap_sim_db_priv = conf->eap_sim_db_priv;
 	data->ssl_ctx = conf->ssl_ctx;
+	data->msg_ctx = conf->msg_ctx;
 	data->ipv6 = conf->ipv6;
 	if (conf->pac_opaque_encr_key) {
 		data->pac_opaque_encr_key = os_malloc(16);
@@ -1110,6 +1299,10 @@ radius_server_init(struct radius_server_conf *conf)
 }
 
 
+/**
+ * radius_server_deinit - Deinitialize RADIUS server
+ * @data: RADIUS server context from radius_server_init()
+ */
 void radius_server_deinit(struct radius_server_data *data)
 {
 	if (data == NULL)
@@ -1130,6 +1323,13 @@ void radius_server_deinit(struct radius_server_data *data)
 }
 
 
+/**
+ * radius_server_get_mib - Get RADIUS server MIB information
+ * @data: RADIUS server context from radius_server_init()
+ * @buf: Buffer for returning the MIB data in text format
+ * @buflen: buf length in octets
+ * Returns: Number of octets written into buf
+ */
 int radius_server_get_mib(struct radius_server_data *data, char *buf,
 			  size_t buflen)
 {
@@ -1269,6 +1469,14 @@ static struct eapol_callbacks radius_server_eapol_cb =
 };
 
 
+/**
+ * radius_server_eap_pending_cb - Pending EAP data notification
+ * @data: RADIUS server context from radius_server_init()
+ * @ctx: Pending EAP context pointer
+ *
+ * This function is used to notify EAP server module that a pending operation
+ * has been completed and processing of the EAP session can proceed.
+ */
 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
 {
 	struct radius_client *cli;
@@ -1307,5 +1515,4 @@ void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
 		return; /* msg was stored with the session */
 
 	radius_msg_free(msg);
-	os_free(msg);
 }
diff --git a/contrib/wpa/src/radius/radius_server.h b/contrib/wpa/src/radius/radius_server.h
index d5fb6a1e3fee..f9c951d05f24 100644
--- a/contrib/wpa/src/radius/radius_server.h
+++ b/contrib/wpa/src/radius/radius_server.h
@@ -1,6 +1,6 @@
 /*
- * hostapd / RADIUS authentication server
- * Copyright (c) 2005-2007, Jouni Malinen 
+ * RADIUS authentication server
+ * Copyright (c) 2005-2009, Jouni Malinen 
  *
  * 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
@@ -18,32 +18,185 @@
 struct radius_server_data;
 struct eap_user;
 
+/**
+ * struct radius_server_conf - RADIUS server configuration
+ */
 struct radius_server_conf {
+	/**
+	 * auth_port - UDP port to listen to as an authentication server
+	 */
 	int auth_port;
+
+	/**
+	 * client_file - RADIUS client configuration file
+	 *
+	 * This file contains the RADIUS clients and the shared secret to be
+	 * used with them in a format where each client is on its own line. The
+	 * first item on the line is the IPv4 or IPv6 address of the client
+	 * with an optional address mask to allow full network to be specified
+	 * (e.g., 192.168.1.2 or 192.168.1.0/24). This is followed by white
+	 * space (space or tabulator) and the shared secret. Lines starting
+	 * with '#' are skipped and can be used as comments.
+	 */
 	char *client_file;
+
+	/**
+	 * conf_ctx - Context pointer for callbacks
+	 *
+	 * This is used as the ctx argument in get_eap_user() calls.
+	 */
 	void *conf_ctx;
+
+	/**
+	 * eap_sim_db_priv - EAP-SIM/AKA database context
+	 *
+	 * This is passed to the EAP-SIM/AKA server implementation as a
+	 * callback context.
+	 */
 	void *eap_sim_db_priv;
+
+	/**
+	 * ssl_ctx - TLS context
+	 *
+	 * This is passed to the EAP server implementation as a callback
+	 * context for TLS operations.
+	 */
 	void *ssl_ctx;
+
+	/**
+	 * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST
+	 *
+	 * This parameter is used to set a key for EAP-FAST to encrypt the
+	 * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If
+	 * set, must point to a 16-octet key.
+	 */
 	u8 *pac_opaque_encr_key;
+
+	/**
+	 * eap_fast_a_id - EAP-FAST authority identity (A-ID)
+	 *
+	 * If EAP-FAST is not used, this can be set to %NULL. 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 recommended to use
+	 * that length for the field to provide interoperability with deployed
+	 * peer implementations.
+	 */
 	u8 *eap_fast_a_id;
+
+	/**
+	 * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets
+	 */
 	size_t eap_fast_a_id_len;
+
+	/**
+	 * eap_fast_a_id_info - EAP-FAST authority identifier information
+	 *
+	 * This A-ID-Info contains a user-friendly name for the A-ID. For
+	 * example, this could be the enterprise and server names in
+	 * human-readable format. This field is encoded as UTF-8. If EAP-FAST
+	 * is not used, this can be set to %NULL.
+	 */
 	char *eap_fast_a_id_info;
+
+	/**
+	 * eap_fast_prov - EAP-FAST provisioning modes
+	 *
+	 * 0 = provisioning disabled, 1 = only anonymous provisioning allowed,
+	 * 2 = only authenticated provisioning allowed, 3 = both provisioning
+	 * modes allowed.
+	 */
 	int eap_fast_prov;
+
+	/**
+	 * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds
+	 *
+	 * This is the hard limit on how long a provisioned PAC-Key can be
+	 * used.
+	 */
 	int pac_key_lifetime;
+
+	/**
+	 * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds
+	 *
+	 * This is a soft limit on the PAC-Key. The server will automatically
+	 * generate a new PAC-Key when this number of seconds (or fewer) of the
+	 * lifetime remains.
+	 */
 	int pac_key_refresh_time;
+
+	/**
+	 * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
+	 *
+	 * This controls whether the protected success/failure indication
+	 * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA.
+	 */
 	int eap_sim_aka_result_ind;
+
+	/**
+	 * tnc - Trusted Network Connect (TNC)
+	 *
+	 * This controls whether TNC is enabled and 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.
+	 */
 	int tnc;
+
+	/**
+	 * wps - Wi-Fi Protected Setup context
+	 *
+	 * If WPS is used with an external RADIUS server (which is quite
+	 * unlikely configuration), this is used to provide a pointer to WPS
+	 * context data. Normally, this can be set to %NULL.
+	 */
 	struct wps_context *wps;
+
+	/**
+	 * ipv6 - Whether to enable IPv6 support in the RADIUS server
+	 */
 	int ipv6;
+
+	/**
+	 * get_eap_user - Callback for fetching EAP user information
+	 * @ctx: Context data from conf_ctx
+	 * @identity: User identity
+	 * @identity_len: identity buffer length in octets
+	 * @phase2: Whether this is for Phase 2 identity
+	 * @user: Data structure for filling in the user information
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This is used to fetch information from user database. The callback
+	 * will fill in information about allowed EAP methods and the user
+	 * password. The password field will be an allocated copy of the
+	 * password data and RADIUS server will free it after use.
+	 */
 	int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len,
 			    int phase2, struct eap_user *user);
+
+	/**
+	 * eap_req_id_text - Optional data for EAP-Request/Identity
+	 *
+	 * This can be used to configure an optional, displayable message that
+	 * will be sent in EAP-Request/Identity. This string can contain an
+	 * ASCII-0 character (nul) to separate network infromation per RFC
+	 * 4284. The actual string length is explicit provided in
+	 * eap_req_id_text_len since nul character will not be used as a string
+	 * terminator.
+	 */
 	const char *eap_req_id_text;
+
+	/**
+	 * eap_req_id_text_len - Length of eap_req_id_text buffer in octets
+	 */
 	size_t eap_req_id_text_len;
+
+	/*
+	 * msg_ctx - Context data for wpa_msg() calls
+	 */
+	void *msg_ctx;
 };
 
 
-#ifdef RADIUS_SERVER
-
 struct radius_server_data *
 radius_server_init(struct radius_server_conf *conf);
 
@@ -54,29 +207,4 @@ int radius_server_get_mib(struct radius_server_data *data, char *buf,
 
 void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx);
 
-#else /* RADIUS_SERVER */
-
-static inline struct radius_server_data *
-radius_server_init(struct radius_server_conf *conf)
-{
-	return NULL;
-}
-
-static inline void radius_server_deinit(struct radius_server_data *data)
-{
-}
-
-static inline int radius_server_get_mib(struct radius_server_data *data,
-					char *buf, size_t buflen)
-{
-	return 0;
-}
-
-static inline void
-radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
-{
-}
-
-#endif /* RADIUS_SERVER */
-
 #endif /* RADIUS_SERVER_H */
diff --git a/contrib/wpa/src/rsn_supp/Makefile b/contrib/wpa/src/rsn_supp/Makefile
index cffba620da04..9c41962fd7e1 100644
--- a/contrib/wpa/src/rsn_supp/Makefile
+++ b/contrib/wpa/src/rsn_supp/Makefile
@@ -2,7 +2,6 @@ all:
 	@echo Nothing to be made.
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
 	rm -f *~ *.o *.d
 
 install:
diff --git a/contrib/wpa/src/rsn_supp/peerkey.c b/contrib/wpa/src/rsn_supp/peerkey.c
index 45c256a0277f..9d60d4acedf5 100644
--- a/contrib/wpa/src/rsn_supp/peerkey.c
+++ b/contrib/wpa/src/rsn_supp/peerkey.c
@@ -17,13 +17,13 @@
 #ifdef CONFIG_PEERKEY
 
 #include "common.h"
-#include "sha1.h"
-#include "sha256.h"
 #include "eloop.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "common/ieee802_11_defs.h"
 #include "wpa.h"
 #include "wpa_i.h"
 #include "wpa_ie.h"
-#include "ieee802_11_defs.h"
 #include "peerkey.h"
 
 
@@ -255,7 +255,7 @@ static int wpa_supplicant_process_smk_m2(
 #endif /* CONFIG_IEEE80211W */
 
 	if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) {
-		wpa_msg(sm->ctx->ctx, MSG_WARNING,
+		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"WPA: Failed to get random data for PNonce");
 		wpa_supplicant_peerkey_free(sm, peerkey);
 		return -1;
@@ -371,7 +371,7 @@ static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm,
 		    peerkey->smkid, PMKID_LEN);
 
 	if (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) {
-		wpa_msg(sm->ctx->ctx, MSG_WARNING,
+		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"RSN: Failed to get random data for INonce (STK)");
 		os_free(mbuf);
 		return;
@@ -634,9 +634,11 @@ static int wpa_supplicant_process_smk_error(
 
 	if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN)
 		os_memcpy(peer, kde.mac_addr, ETH_ALEN);
+	else
+		os_memset(peer, 0, ETH_ALEN);
 	os_memcpy(&error, kde.error, sizeof(error));
 	error_type = be_to_host16(error.error_type);
-	wpa_msg(sm->ctx->ctx, MSG_INFO,
+	wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
 		"RSN: SMK Error KDE received: MUI %d error_type %d peer "
 		MACSTR,
 		be_to_host16(error.mui), error_type,
@@ -696,7 +698,7 @@ static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm,
 	}
 
 	if (os_get_random(peerkey->pnonce, WPA_NONCE_LEN)) {
-		wpa_msg(sm->ctx->ctx, MSG_WARNING,
+		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"RSN: Failed to get random data for PNonce");
 		return;
 	}
@@ -1096,7 +1098,7 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
 	inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
 
 	if (os_get_random(peerkey->inonce, WPA_NONCE_LEN)) {
-		wpa_msg(sm->ctx->ctx, MSG_WARNING,
+		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"WPA: Failed to get random data for INonce");
 		os_free(rbuf);
 		wpa_supplicant_peerkey_free(sm, peerkey);
diff --git a/contrib/wpa/src/rsn_supp/pmksa_cache.c b/contrib/wpa/src/rsn_supp/pmksa_cache.c
index f8373de6dd3d..cac8c83e6eeb 100644
--- a/contrib/wpa/src/rsn_supp/pmksa_cache.c
+++ b/contrib/wpa/src/rsn_supp/pmksa_cache.c
@@ -15,12 +15,10 @@
 #include "includes.h"
 
 #include "common.h"
-#include "wpa.h"
 #include "eloop.h"
-#include "sha1.h"
-#include "sha256.h"
-#include "wpa_i.h"
 #include "eapol_supp/eapol_supp_sm.h"
+#include "wpa.h"
+#include "wpa_i.h"
 #include "pmksa_cache.h"
 
 #if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
@@ -38,39 +36,6 @@ struct rsn_pmksa_cache {
 };
 
 
-/**
- * rsn_pmkid - Calculate PMK identifier
- * @pmk: Pairwise master key
- * @pmk_len: Length of pmk in bytes
- * @aa: Authenticator address
- * @spa: Supplicant address
- * @use_sha256: Whether to use SHA256-based KDF
- *
- * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
- * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
- */
-static void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa,
-		      const u8 *spa, u8 *pmkid, int use_sha256)
-{
-	char *title = "PMK Name";
-	const u8 *addr[3];
-	const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
-	unsigned char hash[SHA256_MAC_LEN];
-
-	addr[0] = (u8 *) title;
-	addr[1] = aa;
-	addr[2] = spa;
-
-#ifdef CONFIG_IEEE80211W
-	if (use_sha256)
-		hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
-	else
-#endif /* CONFIG_IEEE80211W */
-		hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
-	os_memcpy(pmkid, hash, PMKID_LEN);
-}
-
-
 static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
 
 
@@ -167,7 +132,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
 	struct rsn_pmksa_cache_entry *entry, *pos, *prev;
 	struct os_time now;
 
-	if (pmksa->sm->proto != WPA_PROTO_RSN || pmk_len > PMK_LEN)
+	if (pmk_len > PMK_LEN)
 		return NULL;
 
 	entry = os_zalloc(sizeof(*entry));
@@ -439,7 +404,7 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
 
 /**
  * pmksa_cache_list - Dump text list of entries in PMKSA cache
- * @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
  * @buf: Buffer for the list
  * @len: Length of the buffer
  * Returns: number of bytes written to buffer
@@ -447,7 +412,7 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
  * This function is used to generate a text format representation of the
  * current PMKSA cache contents for the ctrl_iface PMKSA command.
  */
-int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
+int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
 {
 	int i, ret;
 	char *pos = buf;
@@ -462,7 +427,7 @@ int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
 		return pos - buf;
 	pos += ret;
 	i = 0;
-	entry = sm->pmksa->pmksa;
+	entry = pmksa->pmksa;
 	while (entry) {
 		i++;
 		ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ",
diff --git a/contrib/wpa/src/rsn_supp/pmksa_cache.h b/contrib/wpa/src/rsn_supp/pmksa_cache.h
index a329b25b08fd..a1447e526d5b 100644
--- a/contrib/wpa/src/rsn_supp/pmksa_cache.h
+++ b/contrib/wpa/src/rsn_supp/pmksa_cache.h
@@ -53,7 +53,7 @@ pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
 void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa);
 struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
 					       const u8 *aa, const u8 *pmkid);
-int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len);
+int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
 struct rsn_pmksa_cache_entry *
 pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
 		const u8 *aa, const u8 *spa, void *network_ctx, int akmp);
@@ -93,7 +93,8 @@ pmksa_cache_get_current(struct wpa_sm *sm)
 	return NULL;
 }
 
-static inline int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
+static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf,
+				   size_t len)
 {
 	return -1;
 }
diff --git a/contrib/wpa/src/rsn_supp/preauth.c b/contrib/wpa/src/rsn_supp/preauth.c
index b00c004cf62c..6109f5e9f873 100644
--- a/contrib/wpa/src/rsn_supp/preauth.c
+++ b/contrib/wpa/src/rsn_supp/preauth.c
@@ -1,6 +1,6 @@
 /*
- * WPA Supplicant - RSN pre-authentication
- * Copyright (c) 2003-2008, Jouni Malinen 
+ * RSN pre-authentication (supplicant)
+ * Copyright (c) 2003-2010, Jouni Malinen 
  *
  * 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
@@ -16,14 +16,13 @@
 
 #include "common.h"
 #include "wpa.h"
-#include "drivers/driver.h"
 #include "eloop.h"
 #include "l2_packet/l2_packet.h"
 #include "eapol_supp/eapol_supp_sm.h"
 #include "preauth.h"
 #include "pmksa_cache.h"
 #include "wpa_i.h"
-#include "ieee802_11_defs.h"
+#include "common/ieee802_11_defs.h"
 
 
 #if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
@@ -32,7 +31,7 @@
 
 
 struct rsn_pmksa_candidate {
-	struct rsn_pmksa_candidate *next;
+	struct dl_list list;
 	u8 bssid[ETH_ALEN];
 	int priority;
 };
@@ -44,17 +43,15 @@ struct rsn_pmksa_candidate {
  */
 void pmksa_candidate_free(struct wpa_sm *sm)
 {
-	struct rsn_pmksa_candidate *entry, *prev;
+	struct rsn_pmksa_candidate *entry, *n;
 
 	if (sm == NULL)
 		return;
 
-	entry = sm->pmksa_candidates;
-	sm->pmksa_candidates = NULL;
-	while (entry) {
-		prev = entry;
-		entry = entry->next;
-		os_free(prev);
+	dl_list_for_each_safe(entry, n, &sm->pmksa_candidates,
+			      struct rsn_pmksa_candidate, list) {
+		dl_list_del(&entry->list);
+		os_free(entry);
 	}
 }
 
@@ -107,15 +104,15 @@ static void rsn_preauth_eapol_cb(struct eapol_sm *eapol, int success,
 					sm->network_ctx,
 					WPA_KEY_MGMT_IEEE8021X);
 		} else {
-			wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: failed to get "
-				"master session key from pre-auth EAPOL state "
-				"machines");
+			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+				"RSN: failed to get master session key from "
+				"pre-auth EAPOL state machines");
 			success = 0;
 		}
 	}
 
-	wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: pre-authentication with " MACSTR
-		" %s", MAC2STR(sm->preauth_bssid),
+	wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
+		MACSTR " %s", MAC2STR(sm->preauth_bssid),
 		success ? "completed successfully" : "failed");
 
 	rsn_preauth_deinit(sm);
@@ -127,8 +124,8 @@ static void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_sm *sm = eloop_ctx;
 
-	wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: pre-authentication with " MACSTR
-		" timed out", MAC2STR(sm->preauth_bssid));
+	wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
+		MACSTR " timed out", MAC2STR(sm->preauth_bssid));
 	rsn_preauth_deinit(sm);
 	rsn_preauth_candidate_process(sm);
 }
@@ -183,8 +180,8 @@ int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
 	if (sm->preauth_eapol)
 		return -1;
 
-	wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: starting pre-authentication "
-		"with " MACSTR, MAC2STR(dst));
+	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
+		"RSN: starting pre-authentication with " MACSTR, MAC2STR(dst));
 
 	sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr,
 					ETH_P_RSN_PREAUTH,
@@ -293,42 +290,42 @@ void rsn_preauth_deinit(struct wpa_sm *sm)
  */
 void rsn_preauth_candidate_process(struct wpa_sm *sm)
 {
-	struct rsn_pmksa_candidate *candidate;
+	struct rsn_pmksa_candidate *candidate, *n;
 
-	if (sm->pmksa_candidates == NULL)
+	if (dl_list_empty(&sm->pmksa_candidates))
 		return;
 
 	/* TODO: drop priority for old candidate entries */
 
-	wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: processing PMKSA candidate "
+	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: processing PMKSA candidate "
 		"list");
 	if (sm->preauth_eapol ||
 	    sm->proto != WPA_PROTO_RSN ||
 	    wpa_sm_get_state(sm) != WPA_COMPLETED ||
 	    (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
 	     sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256)) {
-		wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: not in suitable state "
-			"for new pre-authentication");
+		wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable "
+			"state for new pre-authentication");
 		return; /* invalid state for new pre-auth */
 	}
 
-	while (sm->pmksa_candidates) {
+	dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates,
+			      struct rsn_pmksa_candidate, list) {
 		struct rsn_pmksa_cache_entry *p = NULL;
-		candidate = sm->pmksa_candidates;
 		p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL);
 		if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
 		    (p == NULL || p->opportunistic)) {
-			wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA "
+			wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
 				"candidate " MACSTR
 				" selected for pre-authentication",
 				MAC2STR(candidate->bssid));
-			sm->pmksa_candidates = candidate->next;
+			dl_list_del(&candidate->list);
 			rsn_preauth_init(sm, candidate->bssid,
 					 sm->eap_conf_ctx);
 			os_free(candidate);
 			return;
 		}
-		wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA candidate "
+		wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA candidate "
 			MACSTR " does not need pre-authentication anymore",
 			MAC2STR(candidate->bssid));
 		/* Some drivers (e.g., NDIS) expect to get notified about the
@@ -337,10 +334,10 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm)
 			wpa_sm_add_pmkid(sm, candidate->bssid, p->pmkid);
 		}
 
-		sm->pmksa_candidates = candidate->next;
+		dl_list_del(&candidate->list);
 		os_free(candidate);
 	}
-	wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: no more pending PMKSA "
+	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: no more pending PMKSA "
 		"candidates");
 }
 
@@ -359,7 +356,7 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm)
 void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
 			 int prio, int preauth)
 {
-	struct rsn_pmksa_candidate *cand, *prev, *pos;
+	struct rsn_pmksa_candidate *cand, *pos;
 
 	if (sm->network_ctx && sm->proactive_key_caching)
 		pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx,
@@ -373,21 +370,17 @@ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
 
 	/* If BSSID already on candidate list, update the priority of the old
 	 * entry. Do not override priority based on normal scan results. */
-	prev = NULL;
-	cand = sm->pmksa_candidates;
-	while (cand) {
-		if (os_memcmp(cand->bssid, bssid, ETH_ALEN) == 0) {
-			if (prev)
-				prev->next = cand->next;
-			else
-				sm->pmksa_candidates = cand->next;
+	cand = NULL;
+	dl_list_for_each(pos, &sm->pmksa_candidates,
+			 struct rsn_pmksa_candidate, list) {
+		if (os_memcmp(pos->bssid, bssid, ETH_ALEN) == 0) {
+			cand = pos;
 			break;
 		}
-		prev = cand;
-		cand = cand->next;
 	}
 
 	if (cand) {
+		dl_list_del(&cand->list);
 		if (prio < PMKID_CANDIDATE_PRIO_SCAN)
 			cand->priority = prio;
 	} else {
@@ -400,21 +393,18 @@ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
 
 	/* Add candidate to the list; order by increasing priority value. i.e.,
 	 * highest priority (smallest value) first. */
-	prev = NULL;
-	pos = sm->pmksa_candidates;
-	while (pos) {
-		if (cand->priority <= pos->priority)
+	dl_list_for_each(pos, &sm->pmksa_candidates,
+			 struct rsn_pmksa_candidate, list) {
+		if (cand->priority <= pos->priority) {
+			dl_list_add(pos->list.prev, &cand->list);
+			cand = NULL;
 			break;
-		prev = pos;
-		pos = pos->next;
+		}
 	}
-	cand->next = pos;
-	if (prev)
-		prev->next = cand;
-	else
-		sm->pmksa_candidates = cand;
+	if (cand)
+		dl_list_add_tail(&sm->pmksa_candidates, &cand->list);
 
-	wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: added PMKSA cache "
+	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: added PMKSA cache "
 		"candidate " MACSTR " prio %d", MAC2STR(bssid), prio);
 	rsn_preauth_candidate_process(sm);
 }
@@ -423,23 +413,18 @@ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
 /* TODO: schedule periodic scans if current AP supports preauth */
 
 /**
- * rsn_preauth_scan_results - Process scan results to find PMKSA candidates
+ * rsn_preauth_scan_results - Start processing scan results for canditates
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
- * @results: Scan results
+ * Returns: 0 if ready to process results or -1 to skip processing
  *
- * This functions goes through the scan results and adds all suitable APs
- * (Authenticators) into PMKSA candidate list.
+ * This functions is used to notify RSN code about start of new scan results
+ * processing. The actual scan results will be provided by calling
+ * rsn_preauth_scan_result() for each BSS if this function returned 0.
  */
-void rsn_preauth_scan_results(struct wpa_sm *sm,
-			      struct wpa_scan_results *results)
+int rsn_preauth_scan_results(struct wpa_sm *sm)
 {
-	struct wpa_scan_res *r;
-	struct wpa_ie_data ie;
-	int i;
-	struct rsn_pmksa_cache_entry *pmksa;
-
 	if (sm->ssid_len == 0)
-		return;
+		return -1;
 
 	/*
 	 * TODO: is it ok to free all candidates? What about the entries
@@ -447,37 +432,41 @@ void rsn_preauth_scan_results(struct wpa_sm *sm,
 	 */
 	pmksa_candidate_free(sm);
 
-	for (i = results->num - 1; i >= 0; i--) {
-		const u8 *ssid, *rsn;
+	return 0;
+}
 
-		r = results->res[i];
 
-		ssid = wpa_scan_get_ie(r, WLAN_EID_SSID);
-		if (ssid == NULL || ssid[1] != sm->ssid_len ||
-		    os_memcmp(ssid + 2, sm->ssid, ssid[1]) != 0)
-			continue;
+/**
+ * rsn_preauth_scan_result - Processing scan result for PMKSA canditates
+ * @sm: Pointer to WPA state machine data from wpa_sm_init()
+ *
+ * Add all suitable APs (Authenticators) from scan results into PMKSA
+ * candidate list.
+ */
+void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid,
+			     const u8 *ssid, const u8 *rsn)
+{
+	struct wpa_ie_data ie;
+	struct rsn_pmksa_cache_entry *pmksa;
 
-		if (os_memcmp(r->bssid, sm->bssid, ETH_ALEN) == 0)
-			continue;
+	if (ssid[1] != sm->ssid_len ||
+	    os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0)
+		return; /* Not for the current SSID */
 
-		rsn = wpa_scan_get_ie(r, WLAN_EID_RSN);
-		if (rsn == NULL || wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
-			continue;
+	if (os_memcmp(bssid, sm->bssid, ETH_ALEN) == 0)
+		return; /* Ignore current AP */
 
-		pmksa = pmksa_cache_get(sm->pmksa, r->bssid, NULL);
-		if (pmksa &&
-		    (!pmksa->opportunistic ||
-		     !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
-			continue;
+	if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
+		return;
 
-		/*
-		 * Give less priority to candidates found from normal
-		 * scan results.
-		 */
-		pmksa_candidate_add(sm, r->bssid,
-				    PMKID_CANDIDATE_PRIO_SCAN,
-				    ie.capabilities & WPA_CAPABILITY_PREAUTH);
-	}
+	pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL);
+	if (pmksa && (!pmksa->opportunistic ||
+		      !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
+		return;
+
+	/* Give less priority to candidates found from normal scan results. */
+	pmksa_candidate_add(sm, bssid, PMKID_CANDIDATE_PRIO_SCAN,
+			    ie.capabilities & WPA_CAPABILITY_PREAUTH);
 }
 
 
diff --git a/contrib/wpa/src/rsn_supp/preauth.h b/contrib/wpa/src/rsn_supp/preauth.h
index b9ac57b531ba..f8240abef6df 100644
--- a/contrib/wpa/src/rsn_supp/preauth.h
+++ b/contrib/wpa/src/rsn_supp/preauth.h
@@ -1,6 +1,6 @@
 /*
  * wpa_supplicant - WPA2/RSN pre-authentication functions
- * Copyright (c) 2003-2005, Jouni Malinen 
+ * Copyright (c) 2003-2009, Jouni Malinen 
  *
  * 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
@@ -23,8 +23,9 @@ void pmksa_candidate_free(struct wpa_sm *sm);
 int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
 		     struct eap_peer_config *eap_conf);
 void rsn_preauth_deinit(struct wpa_sm *sm);
-void rsn_preauth_scan_results(struct wpa_sm *sm,
-			      struct wpa_scan_results *results);
+int rsn_preauth_scan_results(struct wpa_sm *sm);
+void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid,
+			     const u8 *ssid, const u8 *rsn);
 void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
 			 int prio, int preauth);
 void rsn_preauth_candidate_process(struct wpa_sm *sm);
@@ -51,8 +52,14 @@ static inline int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
 static inline void rsn_preauth_deinit(struct wpa_sm *sm)
 {
 }
-static inline void rsn_preauth_scan_results(struct wpa_sm *sm,
-					    struct wpa_scan_results *results)
+
+static inline int rsn_preauth_scan_results(struct wpa_sm *sm)
+{
+	return -1;
+}
+
+static inline void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid,
+					   const u8 *ssid, const u8 *rsn)
 {
 }
 
diff --git a/contrib/wpa/src/rsn_supp/wpa.c b/contrib/wpa/src/rsn_supp/wpa.c
index e611fc5e78a2..9439f97210b1 100644
--- a/contrib/wpa/src/rsn_supp/wpa.c
+++ b/contrib/wpa/src/rsn_supp/wpa.c
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - WPA state machine and EAPOL-Key processing
- * Copyright (c) 2003-2008, Jouni Malinen 
+ * Copyright (c) 2003-2010, Jouni Malinen 
  *
  * 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
@@ -15,78 +15,17 @@
 #include "includes.h"
 
 #include "common.h"
-#include "rc4.h"
-#include "aes_wrap.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/crypto.h"
+#include "common/ieee802_11_defs.h"
+#include "eapol_supp/eapol_supp_sm.h"
 #include "wpa.h"
 #include "eloop.h"
-#include "eapol_supp/eapol_supp_sm.h"
 #include "preauth.h"
 #include "pmksa_cache.h"
 #include "wpa_i.h"
 #include "wpa_ie.h"
 #include "peerkey.h"
-#include "ieee802_11_defs.h"
-
-
-/**
- * wpa_cipher_txt - Convert cipher suite to a text string
- * @cipher: Cipher suite (WPA_CIPHER_* enum)
- * Returns: Pointer to a text string of the cipher suite name
- */
-static const char * wpa_cipher_txt(int cipher)
-{
-	switch (cipher) {
-	case WPA_CIPHER_NONE:
-		return "NONE";
-	case WPA_CIPHER_WEP40:
-		return "WEP-40";
-	case WPA_CIPHER_WEP104:
-		return "WEP-104";
-	case WPA_CIPHER_TKIP:
-		return "TKIP";
-	case WPA_CIPHER_CCMP:
-		return "CCMP";
-	default:
-		return "UNKNOWN";
-	}
-}
-
-
-/**
- * wpa_key_mgmt_txt - Convert key management suite to a text string
- * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
- * @proto: WPA/WPA2 version (WPA_PROTO_*)
- * Returns: Pointer to a text string of the key management suite name
- */
-static const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
-{
-	switch (key_mgmt) {
-	case WPA_KEY_MGMT_IEEE8021X:
-		return proto == WPA_PROTO_RSN ?
-			"WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
-	case WPA_KEY_MGMT_PSK:
-		return proto == WPA_PROTO_RSN ?
-			"WPA2-PSK" : "WPA-PSK";
-	case WPA_KEY_MGMT_NONE:
-		return "NONE";
-	case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
-		return "IEEE 802.1X (no WPA)";
-#ifdef CONFIG_IEEE80211R
-	case WPA_KEY_MGMT_FT_IEEE8021X:
-		return "FT-EAP";
-	case WPA_KEY_MGMT_FT_PSK:
-		return "FT-PSK";
-#endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_IEEE80211W
-	case WPA_KEY_MGMT_IEEE8021X_SHA256:
-		return "WPA2-EAP-SHA256";
-	case WPA_KEY_MGMT_PSK_SHA256:
-		return "WPA2-PSK-SHA256";
-#endif /* CONFIG_IEEE80211W */
-	default:
-		return "UNKNOWN";
-	}
-}
 
 
 /**
@@ -119,11 +58,16 @@ void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck,
 				   MAC2STR(dest));
 		}
 	}
-	if (key_mic)
-		wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic);
+	if (key_mic &&
+	    wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic)) {
+		wpa_printf(MSG_ERROR, "WPA: Failed to generate EAPOL-Key "
+			   "version %d MIC", ver);
+		goto out;
+	}
 	wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
 	wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
 	eapol_sm_notify_tx_eapol_key(sm->eapol);
+out:
 	os_free(msg);
 }
 
@@ -246,9 +190,11 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
 			wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
 					"machines", sm->pmk, pmk_len);
 			sm->pmk_len = pmk_len;
-			pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len, src_addr,
-					sm->own_addr, sm->network_ctx,
-					sm->key_mgmt);
+			if (sm->proto == WPA_PROTO_RSN) {
+				pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len,
+						src_addr, sm->own_addr,
+						sm->network_ctx, sm->key_mgmt);
+			}
 			if (!sm->cur_pmksa && pmkid &&
 			    pmksa_cache_get(sm->pmksa, src_addr, pmkid)) {
 				wpa_printf(MSG_DEBUG, "RSN: the new PMK "
@@ -256,10 +202,10 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
 				abort_cached = 0;
 			}
 		} else {
-			wpa_msg(sm->ctx->ctx, MSG_WARNING,
+			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: Failed to get master session key from "
 				"EAPOL state machines");
-			wpa_msg(sm->ctx->ctx, MSG_WARNING,
+			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: Key handshake aborted");
 			if (sm->cur_pmksa) {
 				wpa_printf(MSG_DEBUG, "RSN: Cancelled PMKSA "
@@ -285,6 +231,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
 			wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
 					  buf, buflen);
 			os_free(buf);
+			return -2;
 		}
 
 		return -1;
@@ -315,6 +262,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
 	size_t rlen;
 	struct wpa_eapol_key *reply;
 	u8 *rbuf;
+	u8 *rsn_ie_buf = NULL;
 
 	if (wpa_ie == NULL) {
 		wpa_printf(MSG_WARNING, "WPA: No wpa_ie set - cannot "
@@ -322,13 +270,46 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
 		return -1;
 	}
 
+#ifdef CONFIG_IEEE80211R
+	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
+		int res;
+
+		/*
+		 * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and
+		 * FTIE from (Re)Association Response.
+		 */
+		rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN +
+				       sm->assoc_resp_ies_len);
+		if (rsn_ie_buf == NULL)
+			return -1;
+		os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
+		res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len,
+				       sm->pmk_r1_name);
+		if (res < 0) {
+			os_free(rsn_ie_buf);
+			return -1;
+		}
+		wpa_ie_len += res;
+
+		if (sm->assoc_resp_ies) {
+			os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
+				  sm->assoc_resp_ies_len);
+			wpa_ie_len += sm->assoc_resp_ies_len;
+		}
+
+		wpa_ie = rsn_ie_buf;
+	}
+#endif /* CONFIG_IEEE80211R */
+
 	wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
 
 	rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
 				  NULL, sizeof(*reply) + wpa_ie_len,
 				  &rlen, (void *) &reply);
-	if (rbuf == NULL)
+	if (rbuf == NULL) {
+		os_free(rsn_ie_buf);
 		return -1;
+	}
 
 	reply->type = sm->proto == WPA_PROTO_RSN ?
 		EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
@@ -343,6 +324,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
 
 	WPA_PUT_BE16(reply->key_data_length, wpa_ie_len);
 	os_memcpy(reply + 1, wpa_ie, wpa_ie_len);
+	os_free(rsn_ie_buf);
 
 	os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
 
@@ -380,6 +362,7 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
 	struct wpa_eapol_ie_parse ie;
 	struct wpa_ptk *ptk;
 	u8 buf[8];
+	int res;
 
 	if (wpa_sm_get_network_ctx(sm) == NULL) {
 		wpa_printf(MSG_WARNING, "WPA: No SSID info found (msg 1 of "
@@ -407,12 +390,18 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
 	}
 #endif /* CONFIG_NO_WPA2 */
 
-	if (wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid))
+	res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
+	if (res == -2) {
+		wpa_printf(MSG_DEBUG, "RSN: Do not reply to msg 1/4 - "
+			   "requesting full EAP authentication");
+		return;
+	}
+	if (res)
 		goto failed;
 
 	if (sm->renew_snonce) {
 		if (os_get_random(sm->snonce, WPA_NONCE_LEN)) {
-			wpa_msg(sm->ctx->ctx, MSG_WARNING,
+			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: Failed to get random data for SNonce");
 			goto failed;
 		}
@@ -454,7 +443,8 @@ static void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx)
 static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
 					    const u8 *addr, int secure)
 {
-	wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Key negotiation completed with "
+	wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+		"WPA: Key negotiation completed with "
 		MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),
 		wpa_cipher_txt(sm->pairwise_cipher),
 		wpa_cipher_txt(sm->group_cipher));
@@ -487,7 +477,7 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
 #ifdef CONFIG_IEEE80211R
 	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
 		/* Prepare for the next transition */
-		wpa_ft_prepare_auth_request(sm);
+		wpa_ft_prepare_auth_request(sm, NULL);
 	}
 #endif /* CONFIG_IEEE80211R */
 }
@@ -505,7 +495,7 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
 				      const struct wpa_eapol_key *key)
 {
 	int keylen, rsclen;
-	wpa_alg alg;
+	enum wpa_alg alg;
 	const u8 *key_rsc;
 	u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
@@ -559,7 +549,8 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
 
 static int wpa_supplicant_check_group_cipher(int group_cipher,
 					     int keylen, int maxkeylen,
-					     int *key_rsc_len, wpa_alg *alg)
+					     int *key_rsc_len,
+					     enum wpa_alg *alg)
 {
 	int ret = 0;
 
@@ -613,7 +604,7 @@ static int wpa_supplicant_check_group_cipher(int group_cipher,
 
 
 struct wpa_gtk_data {
-	wpa_alg alg;
+	enum wpa_alg alg;
 	int tx, key_rsc_len, keyidx;
 	u8 gtk[32];
 	int gtk_len;
@@ -774,7 +765,7 @@ static void wpa_report_ie_mismatch(struct wpa_sm *sm,
 				   const u8 *wpa_ie, size_t wpa_ie_len,
 				   const u8 *rsn_ie, size_t rsn_ie_len)
 {
-	wpa_msg(sm->ctx->ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")",
+	wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")",
 		reason, MAC2STR(src_addr));
 
 	if (sm->ap_wpa_ie) {
@@ -807,6 +798,135 @@ static void wpa_report_ie_mismatch(struct wpa_sm *sm,
 }
 
 
+#ifdef CONFIG_IEEE80211R
+
+static int ft_validate_mdie(struct wpa_sm *sm,
+			    const unsigned char *src_addr,
+			    struct wpa_eapol_ie_parse *ie,
+			    const u8 *assoc_resp_mdie)
+{
+	struct rsn_mdie *mdie;
+
+	mdie = (struct rsn_mdie *) (ie->mdie + 2);
+	if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) ||
+	    os_memcmp(mdie->mobility_domain, sm->mobility_domain,
+		      MOBILITY_DOMAIN_ID_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: MDIE in msg 3/4 did not "
+			   "match with the current mobility domain");
+		return -1;
+	}
+
+	if (assoc_resp_mdie &&
+	    (assoc_resp_mdie[1] != ie->mdie[1] ||
+	     os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) {
+		wpa_printf(MSG_DEBUG, "FT: MDIE mismatch");
+		wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4",
+			    ie->mdie, 2 + ie->mdie[1]);
+		wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response",
+			    assoc_resp_mdie, 2 + assoc_resp_mdie[1]);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int ft_validate_ftie(struct wpa_sm *sm,
+			    const unsigned char *src_addr,
+			    struct wpa_eapol_ie_parse *ie,
+			    const u8 *assoc_resp_ftie)
+{
+	if (ie->ftie == NULL) {
+		wpa_printf(MSG_DEBUG, "FT: No FTIE in EAPOL-Key msg 3/4");
+		return -1;
+	}
+
+	if (assoc_resp_ftie == NULL)
+		return 0;
+
+	if (assoc_resp_ftie[1] != ie->ftie[1] ||
+	    os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: FTIE mismatch");
+		wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4",
+			    ie->ftie, 2 + ie->ftie[1]);
+		wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response",
+			    assoc_resp_ftie, 2 + assoc_resp_ftie[1]);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int ft_validate_rsnie(struct wpa_sm *sm,
+			     const unsigned char *src_addr,
+			     struct wpa_eapol_ie_parse *ie)
+{
+	struct wpa_ie_data rsn;
+
+	if (!ie->rsn_ie)
+		return 0;
+
+	/*
+	 * Verify that PMKR1Name from EAPOL-Key message 3/4
+	 * matches with the value we derived.
+	 */
+	if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 ||
+	    rsn.num_pmkid != 1 || rsn.pmkid == NULL) {
+		wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in "
+			   "FT 4-way handshake message 3/4");
+		return -1;
+	}
+
+	if (os_memcmp(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: PMKR1Name mismatch in "
+			   "FT 4-way handshake message 3/4");
+		wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator",
+			    rsn.pmkid, WPA_PMK_NAME_LEN);
+		wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
+			    sm->pmk_r1_name, WPA_PMK_NAME_LEN);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
+					 const unsigned char *src_addr,
+					 struct wpa_eapol_ie_parse *ie)
+{
+	const u8 *pos, *end, *mdie = NULL, *ftie = NULL;
+
+	if (sm->assoc_resp_ies) {
+		pos = sm->assoc_resp_ies;
+		end = pos + sm->assoc_resp_ies_len;
+		while (pos + 2 < end) {
+			if (pos + 2 + pos[1] > end)
+				break;
+			switch (*pos) {
+			case WLAN_EID_MOBILITY_DOMAIN:
+				mdie = pos;
+				break;
+			case WLAN_EID_FAST_BSS_TRANSITION:
+				ftie = pos;
+				break;
+			}
+			pos += 2 + pos[1];
+		}
+	}
+
+	if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 ||
+	    ft_validate_ftie(sm, src_addr, ie, ftie) < 0 ||
+	    ft_validate_rsnie(sm, src_addr, ie) < 0)
+		return -1;
+
+	return 0;
+}
+
+#endif /* CONFIG_IEEE80211R */
+
+
 static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
 				      const unsigned char *src_addr,
 				      struct wpa_eapol_ie_parse *ie)
@@ -836,8 +956,9 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
 	     (ie->wpa_ie_len != sm->ap_wpa_ie_len ||
 	      os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||
 	    (ie->rsn_ie && sm->ap_rsn_ie &&
-	     (ie->rsn_ie_len != sm->ap_rsn_ie_len ||
-	      os_memcmp(ie->rsn_ie, sm->ap_rsn_ie, ie->rsn_ie_len) != 0))) {
+	     wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
+				sm->ap_rsn_ie, sm->ap_rsn_ie_len,
+				ie->rsn_ie, ie->rsn_ie_len))) {
 		wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
 				       "with IE in Beacon/ProbeResp",
 				       src_addr, ie->wpa_ie, ie->wpa_ie_len,
@@ -857,19 +978,9 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
 	}
 
 #ifdef CONFIG_IEEE80211R
-	if (wpa_key_mgmt_ft(sm->key_mgmt)) {
-		struct rsn_mdie *mdie;
-		/* TODO: verify that full MDIE matches with the one from scan
-		 * results, not only mobility domain */
-		mdie = (struct rsn_mdie *) (ie->mdie + 2);
-		if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) ||
-		    os_memcmp(mdie->mobility_domain, sm->mobility_domain,
-			      MOBILITY_DOMAIN_ID_LEN) != 0) {
-			wpa_printf(MSG_DEBUG, "FT: MDIE in msg 3/4 did not "
-				   "match with the current mobility domain");
-			return -1;
-		}
-	}
+	if (wpa_key_mgmt_ft(sm->key_mgmt) &&
+	    wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
+		return -1;
 #endif /* CONFIG_IEEE80211R */
 
 	return 0;
@@ -1128,7 +1239,10 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
 			return -1;
 		}
 		os_memcpy(gd->gtk, key + 1, keydatalen);
-		rc4_skip(ek, 32, 256, gd->gtk, keydatalen);
+		if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) {
+			wpa_printf(MSG_ERROR, "WPA: RC4 failed");
+			return -1;
+		}
 	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
 		if (keydatalen % 8) {
 			wpa_printf(MSG_WARNING, "WPA: Unsupported AES-WRAP "
@@ -1233,7 +1347,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
 		goto failed;
 
 	if (rekey) {
-		wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Group rekeying "
+		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying "
 			"completed with " MACSTR " [GTK=%s]",
 			MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
 		wpa_sm_cancel_auth_timeout(sm);
@@ -1319,7 +1433,10 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
 		u8 ek[32];
 		os_memcpy(ek, key->key_iv, 16);
 		os_memcpy(ek + 16, sm->ptk.kek, 16);
-		rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen);
+		if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) {
+			wpa_printf(MSG_ERROR, "WPA: RC4 failed");
+			return -1;
+		}
 	} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
 		   ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
 		u8 *buf;
@@ -1605,7 +1722,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 	extra_len = data_len - sizeof(*hdr) - sizeof(*key);
 
 	if (WPA_GET_BE16(key->key_data_length) > extra_len) {
-		wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
+		wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
 			"frame - key_data overflow (%d > %lu)",
 			WPA_GET_BE16(key->key_data_length),
 			(unsigned long) extra_len);
@@ -1855,6 +1972,7 @@ struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
 	sm = os_zalloc(sizeof(*sm));
 	if (sm == NULL)
 		return NULL;
+	dl_list_init(&sm->pmksa_candidates);
 	sm->renew_snonce = 1;
 	sm->ctx = ctx;
 
@@ -1890,6 +2008,9 @@ void wpa_sm_deinit(struct wpa_sm *sm)
 	os_free(sm->ap_rsn_ie);
 	os_free(sm->ctx);
 	peerkey_deinit(sm);
+#ifdef CONFIG_IEEE80211R
+	os_free(sm->assoc_resp_ies);
+#endif /* CONFIG_IEEE80211R */
 	os_free(sm);
 }
 
@@ -1919,10 +2040,15 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
 
 #ifdef CONFIG_IEEE80211R
 	if (wpa_ft_is_completed(sm)) {
+		/*
+		 * Clear portValid to kick EAPOL state machine to re-enter
+		 * AUTHENTICATED state to get the EAPOL port Authorized.
+		 */
+		eapol_sm_notify_portValid(sm->eapol, FALSE);
 		wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
 
 		/* Prepare for the next transition */
-		wpa_ft_prepare_auth_request(sm);
+		wpa_ft_prepare_auth_request(sm, NULL);
 
 		clear_ptk = 0;
 	}
@@ -2164,6 +2290,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
 	case WPA_PARAM_RSN_ENABLED:
 		sm->rsn_enabled = value;
 		break;
+	case WPA_PARAM_MFP:
+		sm->mfp = value;
+		break;
 	default:
 		break;
 	}
@@ -2406,3 +2535,32 @@ int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data)
 		return -2;
 	return 0;
 }
+
+
+int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
+{
+#ifndef CONFIG_NO_WPA2
+	return pmksa_cache_list(sm->pmksa, buf, len);
+#else /* CONFIG_NO_WPA2 */
+	return -1;
+#endif /* CONFIG_NO_WPA2 */
+}
+
+
+void wpa_sm_drop_sa(struct wpa_sm *sm)
+{
+	wpa_printf(MSG_DEBUG, "WPA: Clear old PMK and PTK");
+	sm->ptk_set = 0;
+	sm->tptk_set = 0;
+	os_memset(sm->pmk, 0, sizeof(sm->pmk));
+	os_memset(&sm->ptk, 0, sizeof(sm->ptk));
+	os_memset(&sm->tptk, 0, sizeof(sm->tptk));
+}
+
+
+int wpa_sm_has_ptk(struct wpa_sm *sm)
+{
+	if (sm == NULL)
+		return 0;
+	return sm->ptk_set;
+}
diff --git a/contrib/wpa/src/rsn_supp/wpa.h b/contrib/wpa/src/rsn_supp/wpa.h
index bdf778544f41..f1a5554133ce 100644
--- a/contrib/wpa/src/rsn_supp/wpa.h
+++ b/contrib/wpa/src/rsn_supp/wpa.h
@@ -15,17 +15,9 @@
 #ifndef WPA_H
 #define WPA_H
 
-#include "defs.h"
-#include "eapol_common.h"
-#include "wpa_common.h"
-
-#ifndef ETH_P_EAPOL
-#define ETH_P_EAPOL 0x888e
-#endif
-
-#ifndef ETH_P_RSN_PREAUTH
-#define ETH_P_RSN_PREAUTH 0x88c7
-#endif
+#include "common/defs.h"
+#include "common/eapol_common.h"
+#include "common/wpa_common.h"
 
 struct wpa_sm;
 struct eapol_sm;
@@ -33,12 +25,13 @@ struct wpa_config_blob;
 
 struct wpa_sm_ctx {
 	void *ctx; /* pointer to arbitrary upper level context */
+	void *msg_ctx; /* upper level context for wpa_msg() calls */
 
-	void (*set_state)(void *ctx, wpa_states state);
-	wpa_states (*get_state)(void *ctx);
+	void (*set_state)(void *ctx, enum wpa_states state);
+	enum wpa_states (*get_state)(void *ctx);
 	void (*deauthenticate)(void * ctx, int reason_code); 
 	void (*disassociate)(void *ctx, int reason_code);
-	int (*set_key)(void *ctx, wpa_alg alg,
+	int (*set_key)(void *ctx, enum wpa_alg alg,
 		       const u8 *addr, int key_idx, int set_tx,
 		       const u8 *seq, size_t seq_len,
 		       const u8 *key, size_t key_len);
@@ -61,6 +54,7 @@ struct wpa_sm_ctx {
 			     size_t ies_len);
 	int (*send_ft_action)(void *ctx, u8 action, const u8 *target_ap,
 			      const u8 *ies, size_t ies_len);
+	int (*mark_authenticated)(void *ctx, const u8 *target_ap);
 };
 
 
@@ -73,7 +67,8 @@ enum wpa_sm_conf_params {
 	WPA_PARAM_GROUP,
 	WPA_PARAM_KEY_MGMT,
 	WPA_PARAM_MGMT_GROUP,
-	WPA_PARAM_RSN_ENABLED
+	WPA_PARAM_RSN_ENABLED,
+	WPA_PARAM_MFP
 };
 
 struct rsn_supp_config {
@@ -127,6 +122,9 @@ void wpa_sm_aborted_cached(struct wpa_sm *sm);
 int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
 		    const u8 *buf, size_t len);
 int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data);
+int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len);
+void wpa_sm_drop_sa(struct wpa_sm *sm);
+int wpa_sm_has_ptk(struct wpa_sm *sm);
 
 #else /* CONFIG_NO_WPA */
 
@@ -258,6 +256,21 @@ static inline int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm,
 	return -1;
 }
 
+static inline int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf,
+					  size_t len)
+{
+	return -1;
+}
+
+static inline void wpa_sm_drop_sa(struct wpa_sm *sm)
+{
+}
+
+static inline int wpa_sm_has_ptk(struct wpa_sm *sm)
+{
+	return 0;
+}
+
 #endif /* CONFIG_NO_WPA */
 
 #ifdef CONFIG_PEERKEY
@@ -271,27 +284,27 @@ static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
 
 #ifdef CONFIG_IEEE80211R
 
-int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
-			 const u8 *r0kh_id, size_t r0kh_id_len,
-			 const u8 *r1kh_id);
-int wpa_ft_prepare_auth_request(struct wpa_sm *sm);
+int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len);
+int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie);
 int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
-			    int ft_action, const u8 *target_ap);
+			    int ft_action, const u8 *target_ap,
+			    const u8 *ric_ies, size_t ric_ies_len);
 int wpa_ft_is_completed(struct wpa_sm *sm);
 int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
 				 size_t ies_len, const u8 *src_addr);
-int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap);
+int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
+			 const u8 *mdie);
 
 #else /* CONFIG_IEEE80211R */
 
 static inline int
-wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
-		     const u8 *r0kh_id, const u8 *r1kh_id)
+wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
 {
 	return 0;
 }
 
-static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm)
+static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm,
+					      const u8 *mdie)
 {
 	return 0;
 }
diff --git a/contrib/wpa/src/rsn_supp/wpa_ft.c b/contrib/wpa/src/rsn_supp/wpa_ft.c
index 557b3114d250..23063bc2d472 100644
--- a/contrib/wpa/src/rsn_supp/wpa_ft.c
+++ b/contrib/wpa/src/rsn_supp/wpa_ft.c
@@ -15,19 +15,44 @@
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/aes_wrap.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
 #include "wpa.h"
 #include "wpa_i.h"
 #include "wpa_ie.h"
-#include "aes_wrap.h"
-#include "ieee802_11_defs.h"
 
 #ifdef CONFIG_IEEE80211R
 
+struct wpa_ft_ies {
+	const u8 *mdie;
+	size_t mdie_len;
+	const u8 *ftie;
+	size_t ftie_len;
+	const u8 *r1kh_id;
+	const u8 *gtk;
+	size_t gtk_len;
+	const u8 *r0kh_id;
+	size_t r0kh_id_len;
+	const u8 *rsn;
+	size_t rsn_len;
+	const u8 *rsn_pmkid;
+	const u8 *tie;
+	size_t tie_len;
+	const u8 *igtk;
+	size_t igtk_len;
+	const u8 *ric;
+	size_t ric_len;
+};
+
+static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
+			    struct wpa_ft_ies *parse);
+
+
 int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
 		      const struct wpa_eapol_key *key,
 		      struct wpa_ptk *ptk, size_t ptk_len)
 {
-	u8 pmk_r1_name[WPA_PMK_NAME_LEN];
 	u8 ptk_name[WPA_PMK_NAME_LEN];
 	const u8 *anonce = key->key_nonce;
 
@@ -45,11 +70,12 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
 	wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name",
 		    sm->pmk_r0_name, WPA_PMK_NAME_LEN);
 	wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
-			  sm->own_addr, sm->pmk_r1, pmk_r1_name);
+			  sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
 	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
-	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
+	wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
+		    WPA_PMK_NAME_LEN);
 	wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr,
-			  sm->bssid, pmk_r1_name,
+			  sm->bssid, sm->pmk_r1_name,
 			  (u8 *) ptk, ptk_len, ptk_name);
 	wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len);
 	wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
@@ -61,31 +87,40 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
 /**
  * wpa_sm_set_ft_params - Set FT (IEEE 802.11r) parameters
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
- * @mobility_domain: Mobility domain identifier (2 octets)
- * @r0kh_id: PMK-R0 key holder identity (1-48 octets)
- * @r0kh_id_len: R0KH-ID length (1-48)
- * @r1kh_id: PMK-R1 key holder identity (16 octets)
+ * @ies: Association Response IEs or %NULL to clear FT parameters
+ * @ies_len: Length of ies buffer in octets
  * Returns: 0 on success, -1 on failure
  */
-int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
-			 const u8 *r0kh_id, size_t r0kh_id_len,
-			 const u8 *r1kh_id)
+int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
 {
-	if (sm && mobility_domain) {
+	struct wpa_ft_ies ft;
+
+	if (sm == NULL)
+		return 0;
+
+	if (wpa_ft_parse_ies(ies, ies_len, &ft) < 0)
+		return -1;
+
+	if (ft.mdie && ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1)
+		return -1;
+
+	if (ft.mdie) {
 		wpa_hexdump(MSG_DEBUG, "FT: Mobility domain",
-			    mobility_domain, MOBILITY_DOMAIN_ID_LEN);
-		os_memcpy(sm->mobility_domain, mobility_domain,
+			    ft.mdie, MOBILITY_DOMAIN_ID_LEN);
+		os_memcpy(sm->mobility_domain, ft.mdie,
 			  MOBILITY_DOMAIN_ID_LEN);
-	} else if (sm)
+		sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN];
+		wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x",
+			   sm->mdie_ft_capab);
+	} else
 		os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN);
 
-	if (sm && r0kh_id) {
-		if (r0kh_id_len > FT_R0KH_ID_MAX_LEN)
-			return -1;
-		wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len);
-		os_memcpy(sm->r0kh_id, r0kh_id, r0kh_id_len);
-		sm->r0kh_id_len = r0kh_id_len;
-	} else if (sm) {
+	if (ft.r0kh_id) {
+		wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID",
+			    ft.r0kh_id, ft.r0kh_id_len);
+		os_memcpy(sm->r0kh_id, ft.r0kh_id, ft.r0kh_id_len);
+		sm->r0kh_id_len = ft.r0kh_id_len;
+	} else {
 		/* FIX: When should R0KH-ID be cleared? We need to keep the
 		 * old R0KH-ID in order to be able to use this during FT. */
 		/*
@@ -94,31 +129,55 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *mobility_domain,
 		 */
 	}
 
-	if (sm && r1kh_id) {
-		wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", r1kh_id, FT_R1KH_ID_LEN);
-		os_memcpy(sm->r1kh_id, r1kh_id, FT_R1KH_ID_LEN);
-	} else if (sm)
+	if (ft.r1kh_id) {
+		wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID",
+			    ft.r1kh_id, FT_R1KH_ID_LEN);
+		os_memcpy(sm->r1kh_id, ft.r1kh_id, FT_R1KH_ID_LEN);
+	} else
 		os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN);
 
+	os_free(sm->assoc_resp_ies);
+	sm->assoc_resp_ies = os_malloc(ft.mdie_len + 2 + ft.ftie_len + 2);
+	if (sm->assoc_resp_ies) {
+		u8 *pos = sm->assoc_resp_ies;
+		if (ft.mdie) {
+			os_memcpy(pos, ft.mdie - 2, ft.mdie_len + 2);
+			pos += ft.mdie_len + 2;
+		}
+		if (ft.ftie) {
+			os_memcpy(pos, ft.ftie - 2, ft.ftie_len + 2);
+			pos += ft.ftie_len + 2;
+		}
+		sm->assoc_resp_ies_len = pos - sm->assoc_resp_ies;
+		wpa_hexdump(MSG_DEBUG, "FT: Stored MDIE and FTIE from "
+			    "(Re)Association Response",
+			    sm->assoc_resp_ies, sm->assoc_resp_ies_len);
+	}
+
 	return 0;
 }
 
 
 /**
- * wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth Request
+ * wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth/ReAssoc Request
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
  * @len: Buffer for returning the length of the IEs
  * @anonce: ANonce or %NULL if not yet available
  * @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List
  * @kck: 128-bit KCK for MIC or %NULL if no MIC is used
  * @target_ap: Target AP address
+ * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL
+ * @ric_ies_len: Length of ric_ies buffer in octets
+ * @ap_mdie: Mobility Domain IE from the target AP
  * Returns: Pointer to buffer with IEs or %NULL on failure
  *
  * Caller is responsible for freeing the returned buffer with os_free();
  */
 static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
 			       const u8 *anonce, const u8 *pmk_name,
-			       const u8 *kck, const u8 *target_ap)
+			       const u8 *kck, const u8 *target_ap,
+			       const u8 *ric_ies, size_t ric_ies_len,
+			       const u8 *ap_mdie)
 {
 	size_t buf_len;
 	u8 *buf, *pos, *ftie_len, *ftie_pos;
@@ -130,13 +189,13 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
 	sm->ft_completed = 0;
 
 	buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
-		2 + sm->r0kh_id_len + 100;
+		2 + sm->r0kh_id_len + ric_ies_len + 100;
 	buf = os_zalloc(buf_len);
 	if (buf == NULL)
 		return NULL;
 	pos = buf;
 
-	/* RSNIE[PMKR0Name] */
+	/* RSNIE[PMKR0Name/PMKR1Name] */
 	rsnie = (struct rsn_ie_hdr *) pos;
 	rsnie->elem_id = WLAN_EID_RSN;
 	WPA_PUT_LE16(rsnie->version, RSN_VERSION);
@@ -223,9 +282,10 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
 	pos += sizeof(*mdie);
 	os_memcpy(mdie->mobility_domain, sm->mobility_domain,
 		  MOBILITY_DOMAIN_ID_LEN);
-	mdie->ft_capab = 0; /* FIX: copy from the target AP's MDIE */
+	mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] :
+		sm->mdie_ft_capab;
 
-	/* FTIE[SNonce, R0KH-ID] */
+	/* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */
 	ftie_pos = pos;
 	*pos++ = WLAN_EID_FAST_BSS_TRANSITION;
 	ftie_len = pos++;
@@ -234,6 +294,13 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
 	os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN);
 	if (anonce)
 		os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN);
+	if (kck) {
+		/* R1KH-ID sub-element in third FT message */
+		*pos++ = FTIE_SUBELEM_R1KH_ID;
+		*pos++ = FT_R1KH_ID_LEN;
+		os_memcpy(pos, sm->r1kh_id, FT_R1KH_ID_LEN);
+		pos += FT_R1KH_ID_LEN;
+	}
 	/* R0KH-ID sub-element */
 	*pos++ = FTIE_SUBELEM_R0KH_ID;
 	*pos++ = sm->r0kh_id_len;
@@ -241,6 +308,12 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
 	pos += sm->r0kh_id_len;
 	*ftie_len = pos - ftie_len - 1;
 
+	if (ric_ies) {
+		/* RIC Request */
+		os_memcpy(pos, ric_ies, ric_ies_len);
+		pos += ric_ies_len;
+	}
+
 	if (kck) {
 		/*
 		 * IEEE Std 802.11r-2008, 11A.8.4
@@ -253,12 +326,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
 		 * FTIE (with MIC field set to 0)
 		 * RIC-Request (if present)
 		 */
-		ftie->mic_control[1] = 3; /* Information element count */
+		/* Information element count */
+		ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies,
+							       ric_ies_len);
 		if (wpa_ft_mic(kck, sm->own_addr, target_ap, 5,
 			       ((u8 *) mdie) - 2, 2 + sizeof(*mdie),
 			       ftie_pos, 2 + *ftie_len,
-			       (u8 *) rsnie, 2 + rsnie->len, NULL, 0,
-			       ftie->mic) < 0) {
+			       (u8 *) rsnie, 2 + rsnie->len, ric_ies,
+			       ric_ies_len, ftie->mic) < 0) {
 			wpa_printf(MSG_INFO, "FT: Failed to calculate MIC");
 			os_free(buf);
 			return NULL;
@@ -271,26 +346,6 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
 }
 
 
-struct wpa_ft_ies {
-	const u8 *mdie;
-	size_t mdie_len;
-	const u8 *ftie;
-	size_t ftie_len;
-	const u8 *r1kh_id;
-	const u8 *gtk;
-	size_t gtk_len;
-	const u8 *r0kh_id;
-	size_t r0kh_id_len;
-	const u8 *rsn;
-	size_t rsn_len;
-	const u8 *rsn_pmkid;
-	const u8 *tie;
-	size_t tie_len;
-	const u8 *igtk;
-	size_t igtk_len;
-};
-
-
 static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
 			     struct wpa_ft_ies *parse)
 {
@@ -346,6 +401,8 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
 	const u8 *end, *pos;
 	struct wpa_ie_data data;
 	int ret;
+	const struct rsn_ftie *ftie;
+	int prot_ie_count = 0;
 
 	os_memset(parse, 0, sizeof(*parse));
 	if (ies == NULL)
@@ -374,6 +431,10 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
 			parse->mdie_len = pos[1];
 			break;
 		case WLAN_EID_FAST_BSS_TRANSITION:
+			if (pos[1] < sizeof(*ftie))
+				return -1;
+			ftie = (const struct rsn_ftie *) (pos + 2);
+			prot_ie_count = ftie->mic_control[1];
 			if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
 				return -1;
 			break;
@@ -381,11 +442,55 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
 			parse->tie = pos + 2;
 			parse->tie_len = pos[1];
 			break;
+		case WLAN_EID_RIC_DATA:
+			if (parse->ric == NULL)
+				parse->ric = pos;
 		}
 
 		pos += 2 + pos[1];
 	}
 
+	if (prot_ie_count == 0)
+		return 0; /* no MIC */
+
+	/*
+	 * Check that the protected IE count matches with IEs included in the
+	 * frame.
+	 */
+	if (parse->rsn)
+		prot_ie_count--;
+	if (parse->mdie)
+		prot_ie_count--;
+	if (parse->ftie)
+		prot_ie_count--;
+	if (parse->tie)
+		prot_ie_count--;
+	if (prot_ie_count < 0) {
+		wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
+			   "the protected IE count");
+		return -1;
+	}
+
+	if (prot_ie_count == 0 && parse->ric) {
+		wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
+			   "included in protected IE count");
+		return -1;
+	}
+
+	/* Determine the end of the RIC IE(s) */
+	pos = parse->ric;
+	while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
+	       prot_ie_count) {
+		prot_ie_count--;
+		pos += 2 + pos[1];
+	}
+	parse->ric_len = pos - parse->ric;
+	if (prot_ie_count) {
+		wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
+			   "frame", (int) prot_ie_count);
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -393,7 +498,7 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
 static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
 {
 	int keylen;
-	wpa_alg alg;
+	enum wpa_alg alg;
 	u8 null_rsc[6] = { 0, 0, 0, 0, 0, 0 };
 
 	wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver.");
@@ -426,9 +531,10 @@ static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
 /**
  * wpa_ft_prepare_auth_request - Generate over-the-air auth request
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @mdie: Target AP MDIE
  * Returns: 0 on success, -1 on failure
  */
-int wpa_ft_prepare_auth_request(struct wpa_sm *sm)
+int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie)
 {
 	u8 *ft_ies;
 	size_t ft_ies_len;
@@ -440,7 +546,7 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm)
 	}
 
 	ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
-				    NULL, sm->bssid);
+				    NULL, sm->bssid, NULL, 0, mdie);
 	if (ft_ies) {
 		wpa_sm_update_ft_ies(sm, sm->mobility_domain,
 				     ft_ies, ft_ies_len);
@@ -452,7 +558,8 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm)
 
 
 int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
-			    int ft_action, const u8 *target_ap)
+			    int ft_action, const u8 *target_ap,
+			    const u8 *ric_ies, size_t ric_ies_len)
 {
 	u8 *ft_ies;
 	size_t ft_ies_len, ptk_len;
@@ -464,6 +571,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
 	const u8 *bssid;
 
 	wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
+	wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len);
 
 	if (ft_action) {
 		if (!sm->over_the_ds_in_progress) {
@@ -506,6 +614,15 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
 		return -1;
 	}
 
+	if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
+		wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
+			    ftie->snonce, WPA_NONCE_LEN);
+		wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
+			    sm->snonce, WPA_NONCE_LEN);
+		return -1;
+	}
+
 	if (parse.r0kh_id == NULL) {
 		wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
 		return -1;
@@ -538,6 +655,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
 	wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", sm->r1kh_id, FT_R1KH_ID_LEN);
 	wpa_hexdump(MSG_DEBUG, "FT: SNonce", sm->snonce, WPA_NONCE_LEN);
 	wpa_hexdump(MSG_DEBUG, "FT: ANonce", ftie->anonce, WPA_NONCE_LEN);
+	os_memcpy(sm->anonce, ftie->anonce, WPA_NONCE_LEN);
 	wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
 			  sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
 	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
@@ -554,26 +672,40 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
 	wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
 
 	ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
-				    sm->pmk_r1_name, sm->ptk.kck, bssid);
+				    sm->pmk_r1_name, sm->ptk.kck, bssid,
+				    ric_ies, ric_ies_len,
+				    parse.mdie ? parse.mdie - 2 : NULL);
 	if (ft_ies) {
 		wpa_sm_update_ft_ies(sm, sm->mobility_domain,
 				     ft_ies, ft_ies_len);
 		os_free(ft_ies);
 	}
 
+	wpa_sm_mark_authenticated(sm, bssid);
 	ret = wpa_ft_install_ptk(sm, bssid);
+	if (ret) {
+		/*
+		 * Some drivers do not support key configuration when we are
+		 * not associated with the target AP. Work around this by
+		 * trying again after the following reassociation gets
+		 * completed.
+		 */
+		wpa_printf(MSG_DEBUG, "FT: Failed to set PTK prior to "
+			   "association - try again after reassociation");
+		sm->set_ptk_after_assoc = 1;
+	} else
+		sm->set_ptk_after_assoc = 0;
 
-	if (ret == 0) {
-		sm->ft_completed = 1;
-		if (ft_action) {
-			/* TODO: trigger re-association to the Target AP;
-			 * MLME is now doing this automatically, but it should
-			 * really be done only if we get here successfully. */
-			os_memcpy(sm->bssid, target_ap, ETH_ALEN);
-		}
+	sm->ft_completed = 1;
+	if (ft_action) {
+		/*
+		 * The caller is expected trigger re-association with the
+		 * Target AP.
+		 */
+		os_memcpy(sm->bssid, target_ap, ETH_ALEN);
 	}
 
-	return ret;
+	return 0;
 }
 
 
@@ -595,7 +727,7 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
 {
 	u8 gtk[32];
 	int keyidx;
-	wpa_alg alg;
+	enum wpa_alg alg;
 	size_t gtk_len, keylen, rsc_len;
 
 	if (gtk_elem == NULL) {
@@ -606,14 +738,14 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
 	wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp",
 			gtk_elem, gtk_elem_len);
 
-	if (gtk_elem_len < 10 + 24 || (gtk_elem_len - 10) % 8 ||
-	    gtk_elem_len - 18 > sizeof(gtk)) {
+	if (gtk_elem_len < 11 + 24 || (gtk_elem_len - 11) % 8 ||
+	    gtk_elem_len - 19 > sizeof(gtk)) {
 		wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem "
 			   "length %lu", (unsigned long) gtk_elem_len);
 		return -1;
 	}
-	gtk_len = gtk_elem_len - 18;
-	if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 10, gtk)) {
+	gtk_len = gtk_elem_len - 19;
+	if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 11, gtk)) {
 		wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
 			   "decrypt GTK");
 		return -1;
@@ -651,20 +783,20 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
 		return -1;
 	}
 
-	/* Key Info[1] | Key Length[1] | RSC[8] | Key[5..32]. */
+	/* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */
 
-	keyidx = gtk_elem[0] & 0x03;
+	keyidx = WPA_GET_LE16(gtk_elem) & 0x03;
 
-	if (gtk_elem[1] != keylen) {
+	if (gtk_elem[2] != keylen) {
 		wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d "
 			   "negotiated %lu",
-			   gtk_elem[1], (unsigned long) keylen);
+			   gtk_elem[2], (unsigned long) keylen);
 		return -1;
 	}
 
 	wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
 	if (wpa_sm_set_key(sm, alg, (u8 *) "\xff\xff\xff\xff\xff\xff",
-			   keyidx, 0, gtk_elem + 2, rsc_len, gtk, keylen) <
+			   keyidx, 0, gtk_elem + 3, rsc_len, gtk, keylen) <
 	    0) {
 		wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
 			   "driver.");
@@ -735,7 +867,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
 	struct wpa_ft_ies parse;
 	struct rsn_mdie *mdie;
 	struct rsn_ftie *ftie;
-	size_t count;
+	unsigned int count;
 	u8 mic[16];
 
 	wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
@@ -766,6 +898,24 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
 		return -1;
 	}
 
+	if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
+		wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
+			    ftie->snonce, WPA_NONCE_LEN);
+		wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
+			    sm->snonce, WPA_NONCE_LEN);
+		return -1;
+	}
+
+	if (os_memcmp(ftie->anonce, sm->anonce, WPA_NONCE_LEN) != 0) {
+		wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
+		wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
+			    ftie->anonce, WPA_NONCE_LEN);
+		wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
+			    sm->anonce, WPA_NONCE_LEN);
+		return -1;
+	}
+
 	if (parse.r0kh_id == NULL) {
 		wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
 		return -1;
@@ -803,17 +953,18 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
 	count = 3;
 	if (parse.tie)
 		count++;
-
 	if (ftie->mic_control[1] != count) {
-		wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in FTIE (%d)",
-			   ftie->mic_control[1]);
+		wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
+			   "Control: received %u expected %u",
+			   ftie->mic_control[1], count);
 		return -1;
 	}
 
 	if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, src_addr, 6,
 		       parse.mdie - 2, parse.mdie_len + 2,
 		       parse.ftie - 2, parse.ftie_len + 2,
-		       parse.rsn - 2, parse.rsn_len + 2, NULL, 0,
+		       parse.rsn - 2, parse.rsn_len + 2,
+		       parse.ric, parse.ric_len,
 		       mic) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
 		return -1;
@@ -834,6 +985,20 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
 		return -1;
 #endif /* CONFIG_IEEE80211W */
 
+	if (sm->set_ptk_after_assoc) {
+		wpa_printf(MSG_DEBUG, "FT: Try to set PTK again now that we "
+			   "are associated");
+		if (wpa_ft_install_ptk(sm, src_addr) < 0)
+			return -1;
+		sm->set_ptk_after_assoc = 0;
+	}
+
+	if (parse.ric) {
+		wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
+			    parse.ric, parse.ric_len);
+		/* TODO: parse response and inform driver about results */
+	}
+
 	return 0;
 }
 
@@ -841,9 +1006,12 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
 /**
  * wpa_ft_start_over_ds - Generate over-the-DS auth request
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @target_ap: Target AP Address
+ * @mdie: Mobility Domain IE from the target AP
  * Returns: 0 on success, -1 on failure
  */
-int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap)
+int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
+			 const u8 *mdie)
 {
 	u8 *ft_ies;
 	size_t ft_ies_len;
@@ -858,7 +1026,7 @@ int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap)
 	}
 
 	ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name,
-				    NULL, target_ap);
+				    NULL, target_ap, NULL, 0, mdie);
 	if (ft_ies) {
 		sm->over_the_ds_in_progress = 1;
 		os_memcpy(sm->target_ap, target_ap, ETH_ALEN);
diff --git a/contrib/wpa/src/rsn_supp/wpa_i.h b/contrib/wpa/src/rsn_supp/wpa_i.h
index e0dc6bd414e8..618c09028a45 100644
--- a/contrib/wpa/src/rsn_supp/wpa_i.h
+++ b/contrib/wpa/src/rsn_supp/wpa_i.h
@@ -1,6 +1,6 @@
 /*
- * wpa_supplicant - Internal WPA state machine definitions
- * Copyright (c) 2004-2007, Jouni Malinen 
+ * Internal WPA/RSN supplicant state machine definitions
+ * Copyright (c) 2004-2010, Jouni Malinen 
  *
  * 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
@@ -15,7 +15,8 @@
 #ifndef WPA_I_H
 #define WPA_I_H
 
-struct rsn_pmksa_candidate;
+#include "utils/list.h"
+
 struct wpa_peerkey;
 struct wpa_eapol_key;
 
@@ -38,7 +39,7 @@ struct wpa_sm {
 
 	struct rsn_pmksa_cache *pmksa; /* PMKSA cache */
 	struct rsn_pmksa_cache_entry *cur_pmksa; /* current PMKSA entry */
-	struct rsn_pmksa_candidate *pmksa_candidates;
+	struct dl_list pmksa_candidates;
 
 	struct l2_packet_data *l2_preauth;
 	struct l2_packet_data *l2_preauth_br;
@@ -81,6 +82,7 @@ struct wpa_sm {
 	unsigned int mgmt_group_cipher;
 
 	int rsn_enabled; /* Whether RSN is enabled in configuration */
+	int mfp; /* 0 = disabled, 1 = optional, 2 = mandatory */
 
 	u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */
 	size_t assoc_wpa_ie_len;
@@ -105,17 +107,21 @@ struct wpa_sm {
 	int ft_completed;
 	int over_the_ds_in_progress;
 	u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */
+	int set_ptk_after_assoc;
+	u8 mdie_ft_capab; /* FT Capability and Policy from target AP MDIE */
+	u8 *assoc_resp_ies; /* MDIE and FTIE from (Re)Association Response */
+	size_t assoc_resp_ies_len;
 #endif /* CONFIG_IEEE80211R */
 };
 
 
-static inline void wpa_sm_set_state(struct wpa_sm *sm, wpa_states state)
+static inline void wpa_sm_set_state(struct wpa_sm *sm, enum wpa_states state)
 {
 	WPA_ASSERT(sm->ctx->set_state);
 	sm->ctx->set_state(sm->ctx->ctx, state);
 }
 
-static inline wpa_states wpa_sm_get_state(struct wpa_sm *sm)
+static inline enum wpa_states wpa_sm_get_state(struct wpa_sm *sm)
 {
 	WPA_ASSERT(sm->ctx->get_state);
 	return sm->ctx->get_state(sm->ctx->ctx);
@@ -133,7 +139,7 @@ static inline void wpa_sm_disassociate(struct wpa_sm *sm, int reason_code)
 	sm->ctx->disassociate(sm->ctx->ctx, reason_code);
 }
 
-static inline int wpa_sm_set_key(struct wpa_sm *sm, wpa_alg alg,
+static inline int wpa_sm_set_key(struct wpa_sm *sm, enum wpa_alg alg,
 				 const u8 *addr, int key_idx, int set_tx,
 				 const u8 *seq, size_t seq_len,
 				 const u8 *key, size_t key_len)
@@ -223,6 +229,14 @@ static inline int wpa_sm_send_ft_action(struct wpa_sm *sm, u8 action,
 	return -1;
 }
 
+static inline int wpa_sm_mark_authenticated(struct wpa_sm *sm,
+					    const u8 *target_ap)
+{
+	if (sm->ctx->mark_authenticated)
+		return sm->ctx->mark_authenticated(sm->ctx->ctx, target_ap);
+	return -1;
+}
+
 
 void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck,
 			int ver, const u8 *dest, u16 proto,
diff --git a/contrib/wpa/src/rsn_supp/wpa_ie.c b/contrib/wpa/src/rsn_supp/wpa_ie.c
index 84f2811b8861..f447223bc3b9 100644
--- a/contrib/wpa/src/rsn_supp/wpa_ie.c
+++ b/contrib/wpa/src/rsn_supp/wpa_ie.c
@@ -17,7 +17,7 @@
 #include "common.h"
 #include "wpa.h"
 #include "pmksa_cache.h"
-#include "ieee802_11_defs.h"
+#include "common/ieee802_11_defs.h"
 #include "wpa_i.h"
 #include "wpa_ie.h"
 
@@ -332,8 +332,10 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
 	/* RSN Capabilities */
 	capab = 0;
 #ifdef CONFIG_IEEE80211W
-	if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC)
+	if (sm->mfp)
 		capab |= WPA_CAPABILITY_MFPC;
+	if (sm->mfp == 2)
+		capab |= WPA_CAPABILITY_MFPR;
 #endif /* CONFIG_IEEE80211W */
 	WPA_PUT_LE16(pos, capab);
 	pos += 2;
@@ -414,6 +416,8 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
 	    pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
 		ie->wpa_ie = pos;
 		ie->wpa_ie_len = pos[1] + 2;
+		wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key",
+			    ie->wpa_ie, ie->wpa_ie_len);
 		return 0;
 	}
 
@@ -421,6 +425,8 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
 	    pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
 		ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
+		wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key",
+			    pos, pos[1] + 2);
 		return 0;
 	}
 
@@ -428,6 +434,8 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
 		ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
 		ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
+		wpa_hexdump_key(MSG_DEBUG, "WPA: GTK in EAPOL-Key",
+				pos, pos[1] + 2);
 		return 0;
 	}
 
@@ -435,6 +443,8 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
 		ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
 		ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
+		wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key",
+			    pos, pos[1] + 2);
 		return 0;
 	}
 
@@ -443,6 +453,8 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) {
 		ie->smk = pos + 2 + RSN_SELECTOR_LEN;
 		ie->smk_len = pos[1] - RSN_SELECTOR_LEN;
+		wpa_hexdump_key(MSG_DEBUG, "WPA: SMK in EAPOL-Key",
+				pos, pos[1] + 2);
 		return 0;
 	}
 
@@ -450,6 +462,8 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) {
 		ie->nonce = pos + 2 + RSN_SELECTOR_LEN;
 		ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;
+		wpa_hexdump(MSG_DEBUG, "WPA: Nonce in EAPOL-Key",
+			    pos, pos[1] + 2);
 		return 0;
 	}
 
@@ -457,6 +471,8 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) {
 		ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;
 		ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;
+		wpa_hexdump(MSG_DEBUG, "WPA: Lifetime in EAPOL-Key",
+			    pos, pos[1] + 2);
 		return 0;
 	}
 
@@ -464,6 +480,8 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) {
 		ie->error = pos + 2 + RSN_SELECTOR_LEN;
 		ie->error_len = pos[1] - RSN_SELECTOR_LEN;
+		wpa_hexdump(MSG_DEBUG, "WPA: Error in EAPOL-Key",
+			    pos, pos[1] + 2);
 		return 0;
 	}
 #endif /* CONFIG_PEERKEY */
@@ -473,6 +491,8 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
 		ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
 		ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
+		wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK in EAPOL-Key",
+				pos, pos[1] + 2);
 		return 0;
 	}
 #endif /* CONFIG_IEEE80211W */
@@ -513,10 +533,35 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
 		if (*pos == WLAN_EID_RSN) {
 			ie->rsn_ie = pos;
 			ie->rsn_ie_len = pos[1] + 2;
+			wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key",
+				    ie->rsn_ie, ie->rsn_ie_len);
 #ifdef CONFIG_IEEE80211R
 		} else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
 			ie->mdie = pos;
 			ie->mdie_len = pos[1] + 2;
+			wpa_hexdump(MSG_DEBUG, "WPA: MDIE in EAPOL-Key",
+				    ie->mdie, ie->mdie_len);
+		} else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
+			ie->ftie = pos;
+			ie->ftie_len = pos[1] + 2;
+			wpa_hexdump(MSG_DEBUG, "WPA: FTIE in EAPOL-Key",
+				    ie->ftie, ie->ftie_len);
+		} else if (*pos == WLAN_EID_TIMEOUT_INTERVAL && pos[1] >= 5) {
+			if (pos[2] == WLAN_TIMEOUT_REASSOC_DEADLINE) {
+				ie->reassoc_deadline = pos;
+				wpa_hexdump(MSG_DEBUG, "WPA: Reassoc Deadline "
+					    "in EAPOL-Key",
+					    ie->reassoc_deadline, pos[1] + 2);
+			} else if (pos[2] == WLAN_TIMEOUT_KEY_LIFETIME) {
+				ie->key_lifetime = pos;
+				wpa_hexdump(MSG_DEBUG, "WPA: KeyLifetime "
+					    "in EAPOL-Key",
+					    ie->key_lifetime, pos[1] + 2);
+			} else {
+				wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized "
+					    "EAPOL-Key Key Data IE",
+					    pos, 2 + pos[1]);
+			}
 #endif /* CONFIG_IEEE80211R */
 		} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
 			ret = wpa_parse_generic(pos, end, ie);
diff --git a/contrib/wpa/src/rsn_supp/wpa_ie.h b/contrib/wpa/src/rsn_supp/wpa_ie.h
index 17e375aa21d8..94518d845787 100644
--- a/contrib/wpa/src/rsn_supp/wpa_ie.h
+++ b/contrib/wpa/src/rsn_supp/wpa_ie.h
@@ -42,6 +42,10 @@ struct wpa_eapol_ie_parse {
 #ifdef CONFIG_IEEE80211R
 	const u8 *mdie;
 	size_t mdie_len;
+	const u8 *ftie;
+	size_t ftie_len;
+	const u8 *reassoc_deadline;
+	const u8 *key_lifetime;
 #endif /* CONFIG_IEEE80211R */
 };
 
diff --git a/contrib/wpa/src/tls/.gitignore b/contrib/wpa/src/tls/.gitignore
new file mode 100644
index 000000000000..d43242d73390
--- /dev/null
+++ b/contrib/wpa/src/tls/.gitignore
@@ -0,0 +1 @@
+libtls.a
diff --git a/contrib/wpa/src/tls/Makefile b/contrib/wpa/src/tls/Makefile
index cffba620da04..a2da0965a5f9 100644
--- a/contrib/wpa/src/tls/Makefile
+++ b/contrib/wpa/src/tls/Makefile
@@ -1,9 +1,37 @@
-all:
-	@echo Nothing to be made.
+all: libtls.a
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
-	rm -f *~ *.o *.d
+	rm -f *~ *.o *.d libtls.a
 
 install:
 	@echo Nothing to be made.
+
+
+include ../lib.rules
+
+CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
+
+LIB_OBJS= \
+	asn1.o \
+	bignum.o \
+	pkcs1.o \
+	pkcs5.o \
+	pkcs8.o \
+	rsa.o \
+	tlsv1_client.o \
+	tlsv1_client_read.o \
+	tlsv1_client_write.o \
+	tlsv1_common.o \
+	tlsv1_cred.o \
+	tlsv1_record.o \
+	tlsv1_server.o \
+	tlsv1_server_read.o \
+	tlsv1_server_write.o \
+	x509v3.o
+
+
+libtls.a: $(LIB_OBJS)
+	$(AR) crT $@ $?
+
+-include $(OBJS:%.o=%.d)
diff --git a/contrib/wpa/src/tls/asn1.c b/contrib/wpa/src/tls/asn1.c
index 96bc1ac78a9d..3391245fe3cd 100644
--- a/contrib/wpa/src/tls/asn1.c
+++ b/contrib/wpa/src/tls/asn1.c
@@ -15,9 +15,6 @@
 #include "includes.h"
 
 #include "common.h"
-
-#ifdef CONFIG_INTERNAL_X509
-
 #include "asn1.h"
 
 int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr)
@@ -85,28 +82,16 @@ int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr)
 }
 
 
-int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
-		 const u8 **next)
+int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid)
 {
-	struct asn1_hdr hdr;
 	const u8 *pos, *end;
 	unsigned long val;
 	u8 tmp;
 
 	os_memset(oid, 0, sizeof(*oid));
 
-	if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0)
-		return -1;
-
-	if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) {
-		wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d "
-			   "tag 0x%x", hdr.class, hdr.tag);
-		return -1;
-	}
-
-	pos = hdr.payload;
-	end = hdr.payload + hdr.length;
-	*next = end;
+	pos = buf;
+	end = buf + len;
 
 	while (pos < end) {
 		val = 0;
@@ -141,6 +126,26 @@ int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
 }
 
 
+int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
+		 const u8 **next)
+{
+	struct asn1_hdr hdr;
+
+	if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0)
+		return -1;
+
+	if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) {
+		wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d "
+			   "tag 0x%x", hdr.class, hdr.tag);
+		return -1;
+	}
+
+	*next = hdr.payload + hdr.length;
+
+	return asn1_parse_oid(hdr.payload, hdr.length, oid);
+}
+
+
 void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len)
 {
 	char *pos = buf;
@@ -205,5 +210,3 @@ unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len)
 
 	return val;
 }
-
-#endif /* CONFIG_INTERNAL_X509 */
diff --git a/contrib/wpa/src/tls/asn1.h b/contrib/wpa/src/tls/asn1.h
index c02ada8278a2..2ff571ea909d 100644
--- a/contrib/wpa/src/tls/asn1.h
+++ b/contrib/wpa/src/tls/asn1.h
@@ -63,6 +63,7 @@ struct asn1_oid {
 
 
 int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr);
+int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid);
 int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid,
 		 const u8 **next);
 void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len);
diff --git a/contrib/wpa/src/tls/asn1_test.c b/contrib/wpa/src/tls/asn1_test.c
deleted file mode 100644
index a5c77535309f..000000000000
--- a/contrib/wpa/src/tls/asn1_test.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Testing tool for ASN.1/X.509v3 routines
- * Copyright (c) 2006, Jouni Malinen 
- *
- * 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 "asn1.h"
-#include "x509v3.h"
-
-extern int wpa_debug_level;
-
-
-static const char * asn1_class_str(int class)
-{
-	switch (class) {
-	case ASN1_CLASS_UNIVERSAL:
-		return "Universal";
-	case ASN1_CLASS_APPLICATION:
-		return "Application";
-	case ASN1_CLASS_CONTEXT_SPECIFIC:
-		return "Context-specific";
-	case ASN1_CLASS_PRIVATE:
-		return "Private";
-	default:
-		return "?";
-	}
-}
-
-
-int asn1_parse(const u8 *buf, size_t len, int level)
-{
-	const u8 *pos, *prev, *end;
-	char prefix[10], str[100];
-	int _level;
-	struct asn1_hdr hdr;
-	struct asn1_oid oid;
-	u8 tmp;
-
-	_level = level;
-	if ((size_t) _level > sizeof(prefix) - 1)
-		_level = sizeof(prefix) - 1;
-	memset(prefix, ' ', _level);
-	prefix[_level] = '\0';
-
-	pos = buf;
-	end = buf + len;
-
-	while (pos < end) {
-		if (asn1_get_next(pos, end - pos, &hdr) < 0)
-			return -1;
-
-		prev = pos;
-		pos = hdr.payload;
-
-		wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) "
-			   "Tag %u Length %u",
-			   prefix, hdr.class, asn1_class_str(hdr.class),
-			   hdr.constructed,
-			   hdr.constructed ? "Constructed" : "Primitive",
-			   hdr.tag, hdr.length);
-
-		if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC &&
-		    hdr.constructed) {
-			if (asn1_parse(pos, hdr.length, level + 1) < 0)
-				return -1;
-			pos += hdr.length;
-		}
-
-		if (hdr.class != ASN1_CLASS_UNIVERSAL)
-			continue;
-
-		switch (hdr.tag) {
-		case ASN1_TAG_EOC:
-			if (hdr.length) {
-				wpa_printf(MSG_DEBUG, "ASN.1: Non-zero "
-					   "end-of-contents length (%u)",
-					   hdr.length);
-				return -1;
-			}
-			wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix);
-			break;
-		case ASN1_TAG_BOOLEAN:
-			if (hdr.length != 1) {
-				wpa_printf(MSG_DEBUG, "ASN.1: Unexpected "
-					   "Boolean length (%u)", hdr.length);
-				return -1;
-			}
-			tmp = *pos++;
-			wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s",
-				   prefix, tmp ? "TRUE" : "FALSE");
-			break;
-		case ASN1_TAG_INTEGER:
-			wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER",
-				    pos, hdr.length);
-			pos += hdr.length;
-			break;
-		case ASN1_TAG_BITSTRING:
-			wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString",
-				    pos, hdr.length);
-			pos += hdr.length;
-			break;
-		case ASN1_TAG_OCTETSTRING:
-			wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString",
-				    pos, hdr.length);
-			pos += hdr.length;
-			break;
-		case ASN1_TAG_NULL:
-			if (hdr.length) {
-				wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null "
-					   "length (%u)", hdr.length);
-				return -1;
-			}
-			wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix);
-			break;
-		case ASN1_TAG_OID:
-			if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) {
-				wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID");
-				return -1;
-			}
-			asn1_oid_to_str(&oid, str, sizeof(str));
-			wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str);
-			pos += hdr.length;
-			break;
-		case ANS1_TAG_RELATIVE_OID:
-			wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID",
-				    pos, hdr.length);
-			pos += hdr.length;
-			break;
-		case ASN1_TAG_SEQUENCE:
-			wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix);
-			if (asn1_parse(pos, hdr.length, level + 1) < 0)
-				return -1;
-			pos += hdr.length;
-			break;
-		case ASN1_TAG_SET:
-			wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix);
-			if (asn1_parse(pos, hdr.length, level + 1) < 0)
-				return -1;
-			pos += hdr.length;
-			break;
-		case ASN1_TAG_PRINTABLESTRING:
-			wpa_hexdump_ascii(MSG_MSGDUMP,
-					  "ASN.1: PrintableString",
-					  pos, hdr.length);
-			pos += hdr.length;
-			break;
-		case ASN1_TAG_IA5STRING:
-			wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String",
-					  pos, hdr.length);
-			pos += hdr.length;
-			break;
-		case ASN1_TAG_UTCTIME:
-			wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME",
-					  pos, hdr.length);
-			pos += hdr.length;
-			break;
-		case ASN1_TAG_VISIBLESTRING:
-			wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString",
-					  pos, hdr.length);
-			pos += hdr.length;
-			break;
-		default:
-			wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d",
-				   hdr.tag);
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-
-int main(int argc, char *argv[])
-{
-	FILE *f;
-	u8 buf[3000];
-	size_t len;
-	struct x509_certificate *cert;
-
-	wpa_debug_level = 0;
-
-	f = fopen(argv[1], "rb");
-	if (f == NULL)
-		return -1;
-	len = fread(buf, 1, sizeof(buf), f);
-	fclose(f);
-
-	if (asn1_parse(buf, len, 0) < 0)
-		printf("Failed to parse DER ASN.1\n");
-
-	printf("\n\n");
-
-	cert = x509_certificate_parse(buf, len);
-	if (cert == NULL)
-		printf("Failed to parse X.509 certificate\n");
-	x509_certificate_free(cert);
-
-	return 0;
-}
diff --git a/contrib/wpa/src/tls/pkcs1.c b/contrib/wpa/src/tls/pkcs1.c
new file mode 100644
index 000000000000..72ebd8764857
--- /dev/null
+++ b/contrib/wpa/src/tls/pkcs1.c
@@ -0,0 +1,201 @@
+/*
+ * PKCS #1 (RSA Encryption)
+ * Copyright (c) 2006-2009, Jouni Malinen 
+ *
+ * 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 "rsa.h"
+#include "pkcs1.h"
+
+
+static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
+					   const u8 *in, size_t inlen,
+					   u8 *out, size_t *outlen)
+{
+	size_t ps_len;
+	u8 *pos;
+
+	/*
+	 * PKCS #1 v1.5, 8.1:
+	 *
+	 * EB = 00 || BT || PS || 00 || D
+	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
+	 * PS = k-3-||D||; at least eight octets
+	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
+	 * k = length of modulus in octets (modlen)
+	 */
+
+	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
+		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
+			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
+			   __func__, (unsigned long) modlen,
+			   (unsigned long) *outlen,
+			   (unsigned long) inlen);
+		return -1;
+	}
+
+	pos = out;
+	*pos++ = 0x00;
+	*pos++ = block_type; /* BT */
+	ps_len = modlen - inlen - 3;
+	switch (block_type) {
+	case 0:
+		os_memset(pos, 0x00, ps_len);
+		pos += ps_len;
+		break;
+	case 1:
+		os_memset(pos, 0xff, ps_len);
+		pos += ps_len;
+		break;
+	case 2:
+		if (os_get_random(pos, ps_len) < 0) {
+			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
+				   "random data for PS", __func__);
+			return -1;
+		}
+		while (ps_len--) {
+			if (*pos == 0x00)
+				*pos = 0x01;
+			pos++;
+		}
+		break;
+	default:
+		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
+			   "%d", __func__, block_type);
+		return -1;
+	}
+	*pos++ = 0x00;
+	os_memcpy(pos, in, inlen); /* D */
+
+	return 0;
+}
+
+
+int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key,
+		  int use_private, const u8 *in, size_t inlen,
+		  u8 *out, size_t *outlen)
+{
+	size_t modlen;
+
+	modlen = crypto_rsa_get_modulus_len(key);
+
+	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
+					    out, outlen) < 0)
+		return -1;
+
+	return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private);
+}
+
+
+int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key,
+				  const u8 *in, size_t inlen,
+				  u8 *out, size_t *outlen)
+{
+	int res;
+	u8 *pos, *end;
+
+	res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1);
+	if (res)
+		return res;
+
+	if (*outlen < 2 || out[0] != 0 || out[1] != 2)
+		return -1;
+
+	/* Skip PS (pseudorandom non-zero octets) */
+	pos = out + 2;
+	end = out + *outlen;
+	while (*pos && pos < end)
+		pos++;
+	if (pos == end)
+		return -1;
+	pos++;
+
+	*outlen -= pos - out;
+
+	/* Strip PKCS #1 header */
+	os_memmove(out, pos, *outlen);
+
+	return 0;
+}
+
+
+int pkcs1_decrypt_public_key(struct crypto_rsa_key *key,
+			     const u8 *crypt, size_t crypt_len,
+			     u8 *plain, size_t *plain_len)
+{
+	size_t len;
+	u8 *pos;
+
+	len = *plain_len;
+	if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, key, 0) < 0)
+		return -1;
+
+	/*
+	 * PKCS #1 v1.5, 8.1:
+	 *
+	 * EB = 00 || BT || PS || 00 || D
+	 * BT = 00 or 01
+	 * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01)
+	 * k = length of modulus in octets
+	 */
+
+	if (len < 3 + 8 + 16 /* min hash len */ ||
+	    plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) {
+		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
+			   "structure");
+		return -1;
+	}
+
+	pos = plain + 3;
+	if (plain[1] == 0x00) {
+		/* BT = 00 */
+		if (plain[2] != 0x00) {
+			wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
+				   "PS (BT=00)");
+			return -1;
+		}
+		while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00)
+			pos++;
+	} else {
+		/* BT = 01 */
+		if (plain[2] != 0xff) {
+			wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
+				   "PS (BT=01)");
+			return -1;
+		}
+		while (pos < plain + len && *pos == 0xff)
+			pos++;
+	}
+
+	if (pos - plain - 2 < 8) {
+		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
+		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
+			   "padding");
+		return -1;
+	}
+
+	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
+		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
+			   "structure (2)");
+		return -1;
+	}
+	pos++;
+	len -= pos - plain;
+
+	/* Strip PKCS #1 header */
+	os_memmove(plain, pos, len);
+	*plain_len = len;
+
+	return 0;
+}
diff --git a/contrib/wpa/src/tls/pkcs1.h b/contrib/wpa/src/tls/pkcs1.h
new file mode 100644
index 000000000000..68872b1502ed
--- /dev/null
+++ b/contrib/wpa/src/tls/pkcs1.h
@@ -0,0 +1,28 @@
+/*
+ * PKCS #1 (RSA Encryption)
+ * Copyright (c) 2006-2009, Jouni Malinen 
+ *
+ * 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 PKCS1_H
+#define PKCS1_H
+
+int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key,
+		  int use_private, const u8 *in, size_t inlen,
+		  u8 *out, size_t *outlen);
+int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key,
+				  const u8 *in, size_t inlen,
+				  u8 *out, size_t *outlen);
+int pkcs1_decrypt_public_key(struct crypto_rsa_key *key,
+			     const u8 *crypt, size_t crypt_len,
+			     u8 *plain, size_t *plain_len);
+
+#endif /* PKCS1_H */
diff --git a/contrib/wpa/src/tls/pkcs5.c b/contrib/wpa/src/tls/pkcs5.c
new file mode 100644
index 000000000000..4291b84f16d7
--- /dev/null
+++ b/contrib/wpa/src/tls/pkcs5.c
@@ -0,0 +1,238 @@
+/*
+ * PKCS #5 (Password-based Encryption)
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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/crypto.h"
+#include "crypto/md5.h"
+#include "asn1.h"
+#include "pkcs5.h"
+
+
+struct pkcs5_params {
+	enum pkcs5_alg {
+		PKCS5_ALG_UNKNOWN,
+		PKCS5_ALG_MD5_DES_CBC
+	} alg;
+	u8 salt[8];
+	size_t salt_len;
+	unsigned int iter_count;
+};
+
+
+enum pkcs5_alg pkcs5_get_alg(struct asn1_oid *oid)
+{
+	if (oid->len == 7 &&
+	    oid->oid[0] == 1 /* iso */ &&
+	    oid->oid[1] == 2 /* member-body */ &&
+	    oid->oid[2] == 840 /* us */ &&
+	    oid->oid[3] == 113549 /* rsadsi */ &&
+	    oid->oid[4] == 1 /* pkcs */ &&
+	    oid->oid[5] == 5 /* pkcs-5 */ &&
+	    oid->oid[6] == 3 /* pbeWithMD5AndDES-CBC */)
+		return PKCS5_ALG_MD5_DES_CBC;
+
+	return PKCS5_ALG_UNKNOWN;
+}
+
+
+static int pkcs5_get_params(const u8 *enc_alg, size_t enc_alg_len,
+			    struct pkcs5_params *params)
+{
+	struct asn1_hdr hdr;
+	const u8 *enc_alg_end, *pos, *end;
+	struct asn1_oid oid;
+	char obuf[80];
+
+	/* AlgorithmIdentifier */
+
+	enc_alg_end = enc_alg + enc_alg_len;
+
+	os_memset(params, 0, sizeof(*params));
+
+	if (asn1_get_oid(enc_alg, enc_alg_end - enc_alg, &oid, &pos)) {
+		wpa_printf(MSG_DEBUG, "PKCS #5: Failed to parse OID "
+			   "(algorithm)");
+		return -1;
+	}
+
+	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
+	wpa_printf(MSG_DEBUG, "PKCS #5: encryption algorithm %s", obuf);
+	params->alg = pkcs5_get_alg(&oid);
+	if (params->alg == PKCS5_ALG_UNKNOWN) {
+		wpa_printf(MSG_INFO, "PKCS #5: unsupported encryption "
+			   "algorithm %s", obuf);
+		return -1;
+	}
+
+	/*
+	 * PKCS#5, Section 8
+	 * PBEParameter ::= SEQUENCE {
+	 *   salt OCTET STRING SIZE(8),
+	 *   iterationCount INTEGER }
+	 */
+
+	if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_SEQUENCE) {
+		wpa_printf(MSG_DEBUG, "PKCS #5: Expected SEQUENCE "
+			   "(PBEParameter) - found class %d tag 0x%x",
+			   hdr.class, hdr.tag);
+		return -1;
+	}
+	pos = hdr.payload;
+	end = hdr.payload + hdr.length;
+
+	/* salt OCTET STRING SIZE(8) */
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_OCTETSTRING ||
+	    hdr.length != 8) {
+		wpa_printf(MSG_DEBUG, "PKCS #5: Expected OCTETSTRING SIZE(8) "
+			   "(salt) - found class %d tag 0x%x size %d",
+			   hdr.class, hdr.tag, hdr.length);
+		return -1;
+	}
+	pos = hdr.payload + hdr.length;
+	os_memcpy(params->salt, hdr.payload, hdr.length);
+	params->salt_len = hdr.length;
+	wpa_hexdump(MSG_DEBUG, "PKCS #5: salt",
+		    params->salt, params->salt_len);
+
+	/* iterationCount INTEGER */
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
+		wpa_printf(MSG_DEBUG, "PKCS #5: Expected INTEGER - found "
+			   "class %d tag 0x%x", hdr.class, hdr.tag);
+		return -1;
+	}
+	if (hdr.length == 1)
+		params->iter_count = *hdr.payload;
+	else if (hdr.length == 2)
+		params->iter_count = WPA_GET_BE16(hdr.payload);
+	else if (hdr.length == 4)
+		params->iter_count = WPA_GET_BE32(hdr.payload);
+	else {
+		wpa_hexdump(MSG_DEBUG, "PKCS #5: Unsupported INTEGER value "
+			    " (iterationCount)",
+			    hdr.payload, hdr.length);
+		return -1;
+	}
+	wpa_printf(MSG_DEBUG, "PKCS #5: iterationCount=0x%x",
+		   params->iter_count);
+	if (params->iter_count == 0 || params->iter_count > 0xffff) {
+		wpa_printf(MSG_INFO, "PKCS #5: Unsupported "
+			   "iterationCount=0x%x", params->iter_count);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static struct crypto_cipher * pkcs5_crypto_init(struct pkcs5_params *params,
+						const char *passwd)
+{
+	unsigned int i;
+	u8 hash[MD5_MAC_LEN];
+	const u8 *addr[2];
+	size_t len[2];
+
+	if (params->alg != PKCS5_ALG_MD5_DES_CBC)
+		return NULL;
+
+	addr[0] = (const u8 *) passwd;
+	len[0] = os_strlen(passwd);
+	addr[1] = params->salt;
+	len[1] = params->salt_len;
+	if (md5_vector(2, addr, len, hash) < 0)
+		return NULL;
+	addr[0] = hash;
+	len[0] = MD5_MAC_LEN;
+	for (i = 1; i < params->iter_count; i++) {
+		if (md5_vector(1, addr, len, hash) < 0)
+			return NULL;
+	}
+	/* TODO: DES key parity bits(?) */
+	wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES key", hash, 8);
+	wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES IV", hash + 8, 8);
+
+	return crypto_cipher_init(CRYPTO_CIPHER_ALG_DES, hash + 8, hash, 8);
+}
+
+
+u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len,
+		   const u8 *enc_data, size_t enc_data_len,
+		   const char *passwd, size_t *data_len)
+{
+	struct crypto_cipher *ctx;
+	u8 *eb, pad;
+	struct pkcs5_params params;
+	unsigned int i;
+
+	if (pkcs5_get_params(enc_alg, enc_alg_len, ¶ms) < 0) {
+		wpa_printf(MSG_DEBUG, "PKCS #5: Unsupported parameters");
+		return NULL;
+	}
+
+	ctx = pkcs5_crypto_init(¶ms, passwd);
+	if (ctx == NULL) {
+		wpa_printf(MSG_DEBUG, "PKCS #5: Failed to initialize crypto");
+		return NULL;
+	}
+
+	/* PKCS #5, Section 7 - Decryption process */
+	if (enc_data_len < 16 || enc_data_len % 8) {
+		wpa_printf(MSG_INFO, "PKCS #5: invalid length of ciphertext "
+			   "%d", (int) enc_data_len);
+		crypto_cipher_deinit(ctx);
+		return NULL;
+	}
+
+	eb = os_malloc(enc_data_len);
+	if (eb == NULL) {
+		crypto_cipher_deinit(ctx);
+		return NULL;
+	}
+
+	if (crypto_cipher_decrypt(ctx, enc_data, eb, enc_data_len) < 0) {
+		wpa_printf(MSG_DEBUG, "PKCS #5: Failed to decrypt EB");
+		crypto_cipher_deinit(ctx);
+		os_free(eb);
+		return NULL;
+	}
+	crypto_cipher_deinit(ctx);
+
+	pad = eb[enc_data_len - 1];
+	if (pad > 8) {
+		wpa_printf(MSG_INFO, "PKCS #5: Invalid PS octet 0x%x", pad);
+		os_free(eb);
+		return NULL;
+	}
+	for (i = enc_data_len - pad; i < enc_data_len; i++) {
+		if (eb[i] != pad) {
+			wpa_hexdump(MSG_INFO, "PKCS #5: Invalid PS",
+				    eb + enc_data_len - pad, pad);
+			os_free(eb);
+			return NULL;
+		}
+	}
+
+	wpa_hexdump_key(MSG_MSGDUMP, "PKCS #5: message M (encrypted key)",
+			eb, enc_data_len - pad);
+
+	*data_len = enc_data_len - pad;
+	return eb;
+}
diff --git a/contrib/wpa/src/tls/pkcs5.h b/contrib/wpa/src/tls/pkcs5.h
new file mode 100644
index 000000000000..6ed39230b533
--- /dev/null
+++ b/contrib/wpa/src/tls/pkcs5.h
@@ -0,0 +1,22 @@
+/*
+ * PKCS #5 (Password-based Encryption)
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 PKCS5_H
+#define PKCS5_H
+
+u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len,
+		   const u8 *enc_data, size_t enc_data_len,
+		   const char *passwd, size_t *data_len);
+
+#endif /* PKCS5_H */
diff --git a/contrib/wpa/src/tls/pkcs8.c b/contrib/wpa/src/tls/pkcs8.c
new file mode 100644
index 000000000000..69ab262e5ebe
--- /dev/null
+++ b/contrib/wpa/src/tls/pkcs8.c
@@ -0,0 +1,193 @@
+/*
+ * PKCS #8 (Private-key information syntax)
+ * Copyright (c) 2006-2009, Jouni Malinen 
+ *
+ * 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 "asn1.h"
+#include "bignum.h"
+#include "rsa.h"
+#include "pkcs5.h"
+#include "pkcs8.h"
+
+
+struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len)
+{
+	struct asn1_hdr hdr;
+	const u8 *pos, *end;
+	struct bignum *zero;
+	struct asn1_oid oid;
+	char obuf[80];
+
+	/* PKCS #8, Chapter 6 */
+
+	/* PrivateKeyInfo ::= SEQUENCE */
+	if (asn1_get_next(buf, len, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_SEQUENCE) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
+			   "header (SEQUENCE); assume PKCS #8 not used");
+		return NULL;
+	}
+	pos = hdr.payload;
+	end = pos + hdr.length;
+
+	/* version Version (Version ::= INTEGER) */
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found "
+			   "class %d tag 0x%x; assume PKCS #8 not used",
+			   hdr.class, hdr.tag);
+		return NULL;
+	}
+
+	zero = bignum_init();
+	if (zero == NULL)
+		return NULL;
+
+	if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
+		bignum_deinit(zero);
+		return NULL;
+	}
+	pos = hdr.payload + hdr.length;
+
+	if (bignum_cmp_d(zero, 0) != 0) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
+			   "beginning of private key; not found; assume "
+			   "PKCS #8 not used");
+		bignum_deinit(zero);
+		return NULL;
+	}
+	bignum_deinit(zero);
+
+	/* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
+	 * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
+	if (asn1_get_next(pos, len, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_SEQUENCE) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
+			   "(AlgorithmIdentifier) - found class %d tag 0x%x; "
+			   "assume PKCS #8 not used",
+			   hdr.class, hdr.tag);
+		return NULL;
+	}
+
+	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
+			   "(algorithm); assume PKCS #8 not used");
+		return NULL;
+	}
+
+	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
+	wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
+
+	if (oid.len != 7 ||
+	    oid.oid[0] != 1 /* iso */ ||
+	    oid.oid[1] != 2 /* member-body */ ||
+	    oid.oid[2] != 840 /* us */ ||
+	    oid.oid[3] != 113549 /* rsadsi */ ||
+	    oid.oid[4] != 1 /* pkcs */ ||
+	    oid.oid[5] != 1 /* pkcs-1 */ ||
+	    oid.oid[6] != 1 /* rsaEncryption */) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
+			   "algorithm %s", obuf);
+		return NULL;
+	}
+
+	pos = hdr.payload + hdr.length;
+
+	/* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_OCTETSTRING) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
+			   "(privateKey) - found class %d tag 0x%x",
+			   hdr.class, hdr.tag);
+		return NULL;
+	}
+	wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
+
+	return (struct crypto_private_key *)
+		crypto_rsa_import_private_key(hdr.payload, hdr.length);
+}
+
+
+struct crypto_private_key *
+pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd)
+{
+	struct asn1_hdr hdr;
+	const u8 *pos, *end, *enc_alg;
+	size_t enc_alg_len;
+	u8 *data;
+	size_t data_len;
+
+	if (passwd == NULL)
+		return NULL;
+
+	/*
+	 * PKCS #8, Chapter 7
+	 * EncryptedPrivateKeyInfo ::= SEQUENCE {
+	 *   encryptionAlgorithm EncryptionAlgorithmIdentifier,
+	 *   encryptedData EncryptedData }
+	 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+	 * EncryptedData ::= OCTET STRING
+	 */
+
+	if (asn1_get_next(buf, len, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_SEQUENCE) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
+			   "header (SEQUENCE); assume encrypted PKCS #8 not "
+			   "used");
+		return NULL;
+	}
+	pos = hdr.payload;
+	end = pos + hdr.length;
+
+	/* encryptionAlgorithm EncryptionAlgorithmIdentifier */
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_SEQUENCE) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
+			   "(AlgorithmIdentifier) - found class %d tag 0x%x; "
+			   "assume encrypted PKCS #8 not used",
+			   hdr.class, hdr.tag);
+		return NULL;
+	}
+	enc_alg = hdr.payload;
+	enc_alg_len = hdr.length;
+	pos = hdr.payload + hdr.length;
+
+	/* encryptedData EncryptedData */
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_OCTETSTRING) {
+		wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
+			   "(encryptedData) - found class %d tag 0x%x",
+			   hdr.class, hdr.tag);
+		return NULL;
+	}
+
+	data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length,
+			     passwd, &data_len);
+	if (data) {
+		struct crypto_private_key *key;
+		key = pkcs8_key_import(data, data_len);
+		os_free(data);
+		return key;
+	}
+
+	return NULL;
+}
diff --git a/contrib/wpa/src/tls/pkcs8.h b/contrib/wpa/src/tls/pkcs8.h
new file mode 100644
index 000000000000..dac517c91ac9
--- /dev/null
+++ b/contrib/wpa/src/tls/pkcs8.h
@@ -0,0 +1,22 @@
+/*
+ * PKCS #8 (Private-key information syntax)
+ * Copyright (c) 2006-2009, Jouni Malinen 
+ *
+ * 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 PKCS8_H
+#define PKCS8_H
+
+struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len);
+struct crypto_private_key *
+pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd);
+
+#endif /* PKCS8_H */
diff --git a/contrib/wpa/src/tls/rsa.c b/contrib/wpa/src/tls/rsa.c
index 4965a2a311cc..3084adc17579 100644
--- a/contrib/wpa/src/tls/rsa.c
+++ b/contrib/wpa/src/tls/rsa.c
@@ -15,7 +15,6 @@
 #include "includes.h"
 
 #include "common.h"
-#include "crypto.h"
 #include "asn1.h"
 #include "bignum.h"
 #include "rsa.h"
@@ -35,7 +34,6 @@ struct crypto_rsa_key {
 };
 
 
-#ifdef EAP_TLS_FUNCS
 static const u8 * crypto_rsa_parse_integer(const u8 *pos, const u8 *end,
 					   struct bignum *num)
 {
@@ -224,7 +222,6 @@ crypto_rsa_import_private_key(const u8 *buf, size_t len)
 	crypto_rsa_free(key);
 	return NULL;
 }
-#endif /* EAP_TLS_FUNCS */
 
 
 /**
diff --git a/contrib/wpa/src/tls/tlsv1_client.c b/contrib/wpa/src/tls/tlsv1_client.c
index 0bf11742ca93..afb603175a11 100644
--- a/contrib/wpa/src/tls/tlsv1_client.c
+++ b/contrib/wpa/src/tls/tlsv1_client.c
@@ -15,8 +15,8 @@
 #include "includes.h"
 
 #include "common.h"
-#include "sha1.h"
-#include "tls.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "tlsv1_common.h"
 #include "tlsv1_record.h"
 #include "tlsv1_client.h"
@@ -605,7 +605,6 @@ int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn)
  */
 int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers)
 {
-#ifdef EAP_FAST
 	size_t count;
 	u16 *suites;
 
@@ -635,9 +634,6 @@ int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers)
 	}
 
 	return 0;
-#else /* EAP_FAST */
-	return -1;
-#endif /* EAP_FAST */
 }
 
 
diff --git a/contrib/wpa/src/tls/tlsv1_client_read.c b/contrib/wpa/src/tls/tlsv1_client_read.c
index ee20330ce2c6..ed3f2606c8cc 100644
--- a/contrib/wpa/src/tls/tlsv1_client_read.c
+++ b/contrib/wpa/src/tls/tlsv1_client_read.c
@@ -15,10 +15,10 @@
 #include "includes.h"
 
 #include "common.h"
-#include "md5.h"
-#include "sha1.h"
+#include "crypto/md5.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "x509v3.h"
-#include "tls.h"
 #include "tlsv1_common.h"
 #include "tlsv1_record.h"
 #include "tlsv1_client.h"
diff --git a/contrib/wpa/src/tls/tlsv1_client_write.c b/contrib/wpa/src/tls/tlsv1_client_write.c
index e0c95cbe8ebe..b47425f232b7 100644
--- a/contrib/wpa/src/tls/tlsv1_client_write.c
+++ b/contrib/wpa/src/tls/tlsv1_client_write.c
@@ -15,10 +15,10 @@
 #include "includes.h"
 
 #include "common.h"
-#include "md5.h"
-#include "sha1.h"
+#include "crypto/md5.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "x509v3.h"
-#include "tls.h"
 #include "tlsv1_common.h"
 #include "tlsv1_record.h"
 #include "tlsv1_client.h"
@@ -209,7 +209,6 @@ static int tls_write_client_certificate(struct tlsv1_client *conn,
 
 static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end)
 {
-#ifdef EAP_FAST
 	/* ClientDiffieHellmanPublic */
 	u8 *csecret, *csecret_start, *dh_yc, *shared;
 	size_t csecret_len, dh_yc_len, shared_len;
@@ -321,10 +320,6 @@ static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end)
 	os_free(shared);
 	tlsv1_client_free_dh(conn);
 	return 0;
-#else /* EAP_FAST */
-	tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR);
-	return -1;
-#endif /* EAP_FAST */
 }
 
 
diff --git a/contrib/wpa/src/tls/tlsv1_common.h b/contrib/wpa/src/tls/tlsv1_common.h
index 77505649a252..763a4af3d561 100644
--- a/contrib/wpa/src/tls/tlsv1_common.h
+++ b/contrib/wpa/src/tls/tlsv1_common.h
@@ -15,7 +15,7 @@
 #ifndef TLSV1_COMMON_H
 #define TLSV1_COMMON_H
 
-#include "crypto.h"
+#include "crypto/crypto.h"
 
 #define TLS_VERSION 0x0301 /* TLSv1 */
 #define TLS_RANDOM_LEN 32
diff --git a/contrib/wpa/src/tls/tlsv1_cred.c b/contrib/wpa/src/tls/tlsv1_cred.c
index d5564672c8e1..aa467efc8c3c 100644
--- a/contrib/wpa/src/tls/tlsv1_cred.c
+++ b/contrib/wpa/src/tls/tlsv1_cred.c
@@ -1,6 +1,6 @@
 /*
  * TLSv1 credentials
- * Copyright (c) 2006-2007, Jouni Malinen 
+ * Copyright (c) 2006-2009, Jouni Malinen 
  *
  * 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
@@ -16,7 +16,7 @@
 
 #include "common.h"
 #include "base64.h"
-#include "crypto.h"
+#include "crypto/crypto.h"
 #include "x509v3.h"
 #include "tlsv1_cred.h"
 
@@ -68,6 +68,12 @@ static int tlsv1_add_cert_der(struct x509_certificate **chain,
 
 static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
 static const char *pem_cert_end = "-----END CERTIFICATE-----";
+static const char *pem_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
+static const char *pem_key_end = "-----END RSA PRIVATE KEY-----";
+static const char *pem_key2_begin = "-----BEGIN PRIVATE KEY-----";
+static const char *pem_key2_end = "-----END PRIVATE KEY-----";
+static const char *pem_key_enc_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
+static const char *pem_key_enc_end = "-----END ENCRYPTED PRIVATE KEY-----";
 
 
 static const u8 * search_tag(const char *tag, const u8 *buf, size_t len)
@@ -209,10 +215,74 @@ int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert,
 }
 
 
-static int tlsv1_set_key(struct tlsv1_credentials *cred,
-			 const u8 *key, size_t len)
+static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len)
 {
-	cred->key = crypto_private_key_import(key, len);
+	const u8 *pos, *end;
+	unsigned char *der;
+	size_t der_len;
+	struct crypto_private_key *pkey;
+
+	pos = search_tag(pem_key_begin, key, len);
+	if (!pos) {
+		pos = search_tag(pem_key2_begin, key, len);
+		if (!pos)
+			return NULL;
+		pos += os_strlen(pem_key2_begin);
+		end = search_tag(pem_key2_end, pos, key + len - pos);
+		if (!end)
+			return NULL;
+	} else {
+		pos += os_strlen(pem_key_begin);
+		end = search_tag(pem_key_end, pos, key + len - pos);
+		if (!end)
+			return NULL;
+	}
+
+	der = base64_decode(pos, end - pos, &der_len);
+	if (!der)
+		return NULL;
+	pkey = crypto_private_key_import(der, der_len, NULL);
+	os_free(der);
+	return pkey;
+}
+
+
+static struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key,
+							 size_t len,
+							 const char *passwd)
+{
+	const u8 *pos, *end;
+	unsigned char *der;
+	size_t der_len;
+	struct crypto_private_key *pkey;
+
+	if (passwd == NULL)
+		return NULL;
+	pos = search_tag(pem_key_enc_begin, key, len);
+	if (!pos)
+		return NULL;
+	pos += os_strlen(pem_key_enc_begin);
+	end = search_tag(pem_key_enc_end, pos, key + len - pos);
+	if (!end)
+		return NULL;
+
+	der = base64_decode(pos, end - pos, &der_len);
+	if (!der)
+		return NULL;
+	pkey = crypto_private_key_import(der, der_len, passwd);
+	os_free(der);
+	return pkey;
+}
+
+
+static int tlsv1_set_key(struct tlsv1_credentials *cred,
+			 const u8 *key, size_t len, const char *passwd)
+{
+	cred->key = crypto_private_key_import(key, len, passwd);
+	if (cred->key == NULL)
+		cred->key = tlsv1_set_key_pem(key, len);
+	if (cred->key == NULL)
+		cred->key = tlsv1_set_key_enc_pem(key, len, passwd);
 	if (cred->key == NULL) {
 		wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key");
 		return -1;
@@ -242,7 +312,8 @@ int tlsv1_set_private_key(struct tlsv1_credentials *cred,
 
 	if (private_key_blob)
 		return tlsv1_set_key(cred, private_key_blob,
-				     private_key_blob_len);
+				     private_key_blob_len,
+				     private_key_passwd);
 
 	if (private_key) {
 		u8 *buf;
@@ -256,7 +327,7 @@ int tlsv1_set_private_key(struct tlsv1_credentials *cred,
 			return -1;
 		}
 
-		ret = tlsv1_set_key(cred, buf, len);
+		ret = tlsv1_set_key(cred, buf, len, private_key_passwd);
 		os_free(buf);
 		return ret;
 	}
diff --git a/contrib/wpa/src/tls/tlsv1_record.c b/contrib/wpa/src/tls/tlsv1_record.c
index f226ac3f9b37..e811f0e33b44 100644
--- a/contrib/wpa/src/tls/tlsv1_record.c
+++ b/contrib/wpa/src/tls/tlsv1_record.c
@@ -15,8 +15,8 @@
 #include "includes.h"
 
 #include "common.h"
-#include "md5.h"
-#include "sha1.h"
+#include "crypto/md5.h"
+#include "crypto/sha1.h"
 #include "tlsv1_common.h"
 #include "tlsv1_record.h"
 
diff --git a/contrib/wpa/src/tls/tlsv1_record.h b/contrib/wpa/src/tls/tlsv1_record.h
index 9170fb1a2fe4..9c7c0a4e644e 100644
--- a/contrib/wpa/src/tls/tlsv1_record.h
+++ b/contrib/wpa/src/tls/tlsv1_record.h
@@ -15,7 +15,7 @@
 #ifndef TLSV1_RECORD_H
 #define TLSV1_RECORD_H
 
-#include "crypto.h"
+#include "crypto/crypto.h"
 
 #define TLS_MAX_WRITE_MAC_SECRET_LEN 20
 #define TLS_MAX_WRITE_KEY_LEN 32
diff --git a/contrib/wpa/src/tls/tlsv1_server.c b/contrib/wpa/src/tls/tlsv1_server.c
index c204a4778a74..6a6123564553 100644
--- a/contrib/wpa/src/tls/tlsv1_server.c
+++ b/contrib/wpa/src/tls/tlsv1_server.c
@@ -15,8 +15,8 @@
 #include "includes.h"
 
 #include "common.h"
-#include "sha1.h"
-#include "tls.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "tlsv1_common.h"
 #include "tlsv1_record.h"
 #include "tlsv1_server.h"
@@ -546,7 +546,6 @@ int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn)
  */
 int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers)
 {
-#ifdef EAP_FAST
 	size_t count;
 	u16 *suites;
 
@@ -572,9 +571,6 @@ int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers)
 	}
 
 	return 0;
-#else /* EAP_FAST */
-	return -1;
-#endif /* EAP_FAST */
 }
 
 
diff --git a/contrib/wpa/src/tls/tlsv1_server_read.c b/contrib/wpa/src/tls/tlsv1_server_read.c
index 397d74a197ab..49e811ffcff5 100644
--- a/contrib/wpa/src/tls/tlsv1_server_read.c
+++ b/contrib/wpa/src/tls/tlsv1_server_read.c
@@ -15,10 +15,10 @@
 #include "includes.h"
 
 #include "common.h"
-#include "md5.h"
-#include "sha1.h"
+#include "crypto/md5.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "x509v3.h"
-#include "tls.h"
 #include "tlsv1_common.h"
 #include "tlsv1_record.h"
 #include "tlsv1_server.h"
@@ -567,7 +567,6 @@ static int tls_process_client_key_exchange_rsa(
 static int tls_process_client_key_exchange_dh_anon(
 	struct tlsv1_server *conn, const u8 *pos, const u8 *end)
 {
-#ifdef EAP_FAST
 	const u8 *dh_yc;
 	u16 dh_yc_len;
 	u8 *shared;
@@ -665,9 +664,6 @@ static int tls_process_client_key_exchange_dh_anon(
 	}
 
 	return 0;
-#else /* EAP_FAST */
-	return -1;
-#endif /* EAP_FAST */
 }
 
 
diff --git a/contrib/wpa/src/tls/tlsv1_server_write.c b/contrib/wpa/src/tls/tlsv1_server_write.c
index cf54f4265c3a..6d1df7ff34f4 100644
--- a/contrib/wpa/src/tls/tlsv1_server_write.c
+++ b/contrib/wpa/src/tls/tlsv1_server_write.c
@@ -15,10 +15,10 @@
 #include "includes.h"
 
 #include "common.h"
-#include "md5.h"
-#include "sha1.h"
+#include "crypto/md5.h"
+#include "crypto/sha1.h"
+#include "crypto/tls.h"
 #include "x509v3.h"
-#include "tls.h"
 #include "tlsv1_common.h"
 #include "tlsv1_record.h"
 #include "tlsv1_server.h"
@@ -247,12 +247,10 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
 {
 	tls_key_exchange keyx;
 	const struct tls_cipher_suite *suite;
-#ifdef EAP_FAST
 	u8 *pos, *rhdr, *hs_start, *hs_length;
 	size_t rlen;
 	u8 *dh_ys;
 	size_t dh_ys_len;
-#endif /* EAP_FAST */
 
 	suite = tls_get_cipher_suite(conn->rl.cipher_suite);
 	if (suite == NULL)
@@ -272,7 +270,6 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
 		return -1;
 	}
 
-#ifdef EAP_FAST
 	if (conn->cred == NULL || conn->cred->dh_p == NULL ||
 	    conn->cred->dh_g == NULL) {
 		wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for "
@@ -433,9 +430,6 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
 	*msgpos = pos;
 
 	return 0;
-#else /* EAP_FAST */
-	return -1;
-#endif /* EAP_FAST */
 }
 
 
diff --git a/contrib/wpa/src/tls/x509v3.c b/contrib/wpa/src/tls/x509v3.c
index 59bf4ff0524a..bc93df683787 100644
--- a/contrib/wpa/src/tls/x509v3.c
+++ b/contrib/wpa/src/tls/x509v3.c
@@ -15,25 +15,32 @@
 #include "includes.h"
 
 #include "common.h"
-
-#ifdef CONFIG_INTERNAL_X509
-
+#include "crypto/crypto.h"
 #include "asn1.h"
-#include "crypto.h"
 #include "x509v3.h"
 
 
 static void x509_free_name(struct x509_name *name)
 {
-	os_free(name->cn);
-	os_free(name->c);
-	os_free(name->l);
-	os_free(name->st);
-	os_free(name->o);
-	os_free(name->ou);
+	size_t i;
+
+	for (i = 0; i < name->num_attr; i++) {
+		os_free(name->attr[i].value);
+		name->attr[i].value = NULL;
+		name->attr[i].type = X509_NAME_ATTR_NOT_USED;
+	}
+	name->num_attr = 0;
 	os_free(name->email);
-	name->cn = name->c = name->l = name->st = name->o = name->ou = NULL;
 	name->email = NULL;
+
+	os_free(name->alt_email);
+	os_free(name->dns);
+	os_free(name->uri);
+	os_free(name->ip);
+	name->alt_email = name->dns = name->uri = NULL;
+	name->ip = NULL;
+	name->ip_len = 0;
+	os_memset(&name->rid, 0, sizeof(name->rid));
 }
 
 
@@ -146,6 +153,7 @@ static int x509_str_compare(const char *a, const char *b)
 int x509_name_compare(struct x509_name *a, struct x509_name *b)
 {
 	int res;
+	size_t i;
 
 	if (!a && b)
 		return -1;
@@ -153,25 +161,20 @@ int x509_name_compare(struct x509_name *a, struct x509_name *b)
 		return 1;
 	if (!a && !b)
 		return 0;
+	if (a->num_attr < b->num_attr)
+		return -1;
+	if (a->num_attr > b->num_attr)
+		return 1;
 
-	res = x509_str_compare(a->cn, b->cn);
-	if (res)
-		return res;
-	res = x509_str_compare(a->c, b->c);
-	if (res)
-		return res;
-	res = x509_str_compare(a->l, b->l);
-	if (res)
-		return res;
-	res = x509_str_compare(a->st, b->st);
-	if (res)
-		return res;
-	res = x509_str_compare(a->o, b->o);
-	if (res)
-		return res;
-	res = x509_str_compare(a->ou, b->ou);
-	if (res)
-		return res;
+	for (i = 0; i < a->num_attr; i++) {
+		if (a->attr[i].type < b->attr[i].type)
+			return -1;
+		if (a->attr[i].type > b->attr[i].type)
+			return -1;
+		res = x509_str_compare(a->attr[i].value, b->attr[i].value);
+		if (res)
+			return res;
+	}
 	res = x509_str_compare(a->email, b->email);
 	if (res)
 		return res;
@@ -298,7 +301,7 @@ static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
 	struct asn1_hdr hdr;
 	const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end;
 	struct asn1_oid oid;
-	char **fieldp;
+	char *val;
 
 	/*
 	 * Name ::= CHOICE { RDNSequence }
@@ -328,6 +331,8 @@ static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
 	end = *next = pos + hdr.length;
 
 	while (pos < end) {
+		enum x509_name_attr_type type;
+
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
 		    hdr.class != ASN1_CLASS_UNIVERSAL ||
 		    hdr.tag != ASN1_TAG_SET) {
@@ -375,34 +380,34 @@ static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
 		 * pseudonym, generation qualifier.
 		 * MUST: domainComponent (RFC 2247).
 		 */
-		fieldp = NULL;
+		type = X509_NAME_ATTR_NOT_USED;
 		if (oid.len == 4 &&
 		    oid.oid[0] == 2 && oid.oid[1] == 5 && oid.oid[2] == 4) {
 			/* id-at ::= 2.5.4 */
 			switch (oid.oid[3]) {
 			case 3:
 				/* commonName */
-				fieldp = &name->cn;
+				type = X509_NAME_ATTR_CN;
 				break;
 			case 6:
 				/*  countryName */
-				fieldp = &name->c;
+				type = X509_NAME_ATTR_C;
 				break;
 			case 7:
 				/* localityName */
-				fieldp = &name->l;
+				type = X509_NAME_ATTR_L;
 				break;
 			case 8:
 				/* stateOrProvinceName */
-				fieldp = &name->st;
+				type = X509_NAME_ATTR_ST;
 				break;
 			case 10:
 				/* organizationName */
-				fieldp = &name->o;
+				type = X509_NAME_ATTR_O;
 				break;
 			case 11:
 				/* organizationalUnitName */
-				fieldp = &name->ou;
+				type = X509_NAME_ATTR_OU;
 				break;
 			}
 		} else if (oid.len == 7 &&
@@ -411,10 +416,25 @@ static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
 			   oid.oid[4] == 1 && oid.oid[5] == 9 &&
 			   oid.oid[6] == 1) {
 			/* 1.2.840.113549.1.9.1 - e-mailAddress */
-			fieldp = &name->email;
+			os_free(name->email);
+			name->email = os_malloc(hdr.length + 1);
+			if (name->email == NULL) {
+				x509_free_name(name);
+				return -1;
+			}
+			os_memcpy(name->email, hdr.payload, hdr.length);
+			name->email[hdr.length] = '\0';
+			continue;
+		} else if (oid.len == 7 &&
+			   oid.oid[0] == 0 && oid.oid[1] == 9 &&
+			   oid.oid[2] == 2342 && oid.oid[3] == 19200300 &&
+			   oid.oid[4] == 100 && oid.oid[5] == 1 &&
+			   oid.oid[6] == 25) {
+			/* 0.9.2342.19200300.100.1.25 - domainComponent */
+			type = X509_NAME_ATTR_DC;
 		}
 
-		if (fieldp == NULL) {
+		if (type == X509_NAME_ATTR_NOT_USED) {
 			wpa_hexdump(MSG_DEBUG, "X509: Unrecognized OID",
 				    (u8 *) oid.oid,
 				    oid.len * sizeof(oid.oid[0]));
@@ -423,20 +443,60 @@ static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
 			continue;
 		}
 
-		os_free(*fieldp);
-		*fieldp = os_malloc(hdr.length + 1);
-		if (*fieldp == NULL) {
+		if (name->num_attr == X509_MAX_NAME_ATTRIBUTES) {
+			wpa_printf(MSG_INFO, "X509: Too many Name attributes");
 			x509_free_name(name);
 			return -1;
 		}
-		os_memcpy(*fieldp, hdr.payload, hdr.length);
-		(*fieldp)[hdr.length] = '\0';
+
+		val = os_malloc(hdr.length + 1);
+		if (val == NULL) {
+			x509_free_name(name);
+			return -1;
+		}
+		os_memcpy(val, hdr.payload, hdr.length);
+		val[hdr.length] = '\0';
+		if (os_strlen(val) != hdr.length) {
+			wpa_printf(MSG_INFO, "X509: Reject certificate with "
+				   "embedded NUL byte in a string (%s[NUL])",
+				   val);
+			x509_free_name(name);
+			return -1;
+		}
+
+		name->attr[name->num_attr].type = type;
+		name->attr[name->num_attr].value = val;
+		name->num_attr++;
 	}
 
 	return 0;
 }
 
 
+static char * x509_name_attr_str(enum x509_name_attr_type type)
+{
+	switch (type) {
+	case X509_NAME_ATTR_NOT_USED:
+		return "[N/A]";
+	case X509_NAME_ATTR_DC:
+		return "DC";
+	case X509_NAME_ATTR_CN:
+		return "CN";
+	case X509_NAME_ATTR_C:
+		return "C";
+	case X509_NAME_ATTR_L:
+		return "L";
+	case X509_NAME_ATTR_ST:
+		return "ST";
+	case X509_NAME_ATTR_O:
+		return "O";
+	case X509_NAME_ATTR_OU:
+		return "OU";
+	}
+	return "?";
+}
+
+
 /**
  * x509_name_string - Convert an X.509 certificate name into a string
  * @name: Name to convert
@@ -447,6 +507,7 @@ void x509_name_string(struct x509_name *name, char *buf, size_t len)
 {
 	char *pos, *end;
 	int ret;
+	size_t i;
 
 	if (len == 0)
 		return;
@@ -454,46 +515,20 @@ void x509_name_string(struct x509_name *name, char *buf, size_t len)
 	pos = buf;
 	end = buf + len;
 
-	if (name->c) {
-		ret = os_snprintf(pos, end - pos, "C=%s, ", name->c);
-		if (ret < 0 || ret >= end - pos)
-			goto done;
-		pos += ret;
-	}
-	if (name->st) {
-		ret = os_snprintf(pos, end - pos, "ST=%s, ", name->st);
-		if (ret < 0 || ret >= end - pos)
-			goto done;
-		pos += ret;
-	}
-	if (name->l) {
-		ret = os_snprintf(pos, end - pos, "L=%s, ", name->l);
-		if (ret < 0 || ret >= end - pos)
-			goto done;
-		pos += ret;
-	}
-	if (name->o) {
-		ret = os_snprintf(pos, end - pos, "O=%s, ", name->o);
-		if (ret < 0 || ret >= end - pos)
-			goto done;
-		pos += ret;
-	}
-	if (name->ou) {
-		ret = os_snprintf(pos, end - pos, "OU=%s, ", name->ou);
-		if (ret < 0 || ret >= end - pos)
-			goto done;
-		pos += ret;
-	}
-	if (name->cn) {
-		ret = os_snprintf(pos, end - pos, "CN=%s, ", name->cn);
+	for (i = 0; i < name->num_attr; i++) {
+		ret = os_snprintf(pos, end - pos, "%s=%s, ",
+				  x509_name_attr_str(name->attr[i].type),
+				  name->attr[i].value);
 		if (ret < 0 || ret >= end - pos)
 			goto done;
 		pos += ret;
 	}
 
 	if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') {
-		*pos-- = '\0';
-		*pos-- = '\0';
+		pos--;
+		*pos = '\0';
+		pos--;
+		*pos = '\0';
 	}
 
 	if (name->email) {
@@ -815,6 +850,237 @@ static int x509_parse_ext_basic_constraints(struct x509_certificate *cert,
 }
 
 
+static int x509_parse_alt_name_rfc8222(struct x509_name *name,
+				       const u8 *pos, size_t len)
+{
+	/* rfc822Name IA5String */
+	wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - rfc822Name", pos, len);
+	os_free(name->alt_email);
+	name->alt_email = os_zalloc(len + 1);
+	if (name->alt_email == NULL)
+		return -1;
+	os_memcpy(name->alt_email, pos, len);
+	if (os_strlen(name->alt_email) != len) {
+		wpa_printf(MSG_INFO, "X509: Reject certificate with "
+			   "embedded NUL byte in rfc822Name (%s[NUL])",
+			   name->alt_email);
+		os_free(name->alt_email);
+		name->alt_email = NULL;
+		return -1;
+	}
+	return 0;
+}
+
+
+static int x509_parse_alt_name_dns(struct x509_name *name,
+				   const u8 *pos, size_t len)
+{
+	/* dNSName IA5String */
+	wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - dNSName", pos, len);
+	os_free(name->dns);
+	name->dns = os_zalloc(len + 1);
+	if (name->dns == NULL)
+		return -1;
+	os_memcpy(name->dns, pos, len);
+	if (os_strlen(name->dns) != len) {
+		wpa_printf(MSG_INFO, "X509: Reject certificate with "
+			   "embedded NUL byte in dNSName (%s[NUL])",
+			   name->dns);
+		os_free(name->dns);
+		name->dns = NULL;
+		return -1;
+	}
+	return 0;
+}
+
+
+static int x509_parse_alt_name_uri(struct x509_name *name,
+				   const u8 *pos, size_t len)
+{
+	/* uniformResourceIdentifier IA5String */
+	wpa_hexdump_ascii(MSG_MSGDUMP,
+			  "X509: altName - uniformResourceIdentifier",
+			  pos, len);
+	os_free(name->uri);
+	name->uri = os_zalloc(len + 1);
+	if (name->uri == NULL)
+		return -1;
+	os_memcpy(name->uri, pos, len);
+	if (os_strlen(name->uri) != len) {
+		wpa_printf(MSG_INFO, "X509: Reject certificate with "
+			   "embedded NUL byte in uniformResourceIdentifier "
+			   "(%s[NUL])", name->uri);
+		os_free(name->uri);
+		name->uri = NULL;
+		return -1;
+	}
+	return 0;
+}
+
+
+static int x509_parse_alt_name_ip(struct x509_name *name,
+				       const u8 *pos, size_t len)
+{
+	/* iPAddress OCTET STRING */
+	wpa_hexdump(MSG_MSGDUMP, "X509: altName - iPAddress", pos, len);
+	os_free(name->ip);
+	name->ip = os_malloc(len);
+	if (name->ip == NULL)
+		return -1;
+	os_memcpy(name->ip, pos, len);
+	name->ip_len = len;
+	return 0;
+}
+
+
+static int x509_parse_alt_name_rid(struct x509_name *name,
+				   const u8 *pos, size_t len)
+{
+	char buf[80];
+
+	/* registeredID OBJECT IDENTIFIER */
+	if (asn1_parse_oid(pos, len, &name->rid) < 0)
+		return -1;
+
+	asn1_oid_to_str(&name->rid, buf, sizeof(buf));
+	wpa_printf(MSG_MSGDUMP, "X509: altName - registeredID: %s", buf);
+
+	return 0;
+}
+
+
+static int x509_parse_ext_alt_name(struct x509_name *name,
+				   const u8 *pos, size_t len)
+{
+	struct asn1_hdr hdr;
+	const u8 *p, *end;
+
+	/*
+	 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+	 *
+	 * GeneralName ::= CHOICE {
+	 *     otherName                       [0]     OtherName,
+	 *     rfc822Name                      [1]     IA5String,
+	 *     dNSName                         [2]     IA5String,
+	 *     x400Address                     [3]     ORAddress,
+	 *     directoryName                   [4]     Name,
+	 *     ediPartyName                    [5]     EDIPartyName,
+	 *     uniformResourceIdentifier       [6]     IA5String,
+	 *     iPAddress                       [7]     OCTET STRING,
+	 *     registeredID                    [8]     OBJECT IDENTIFIER }
+	 *
+	 * OtherName ::= SEQUENCE {
+	 *     type-id    OBJECT IDENTIFIER,
+	 *     value      [0] EXPLICIT ANY DEFINED BY type-id }
+	 *
+	 * EDIPartyName ::= SEQUENCE {
+	 *     nameAssigner            [0]     DirectoryString OPTIONAL,
+	 *     partyName               [1]     DirectoryString }
+	 */
+
+	for (p = pos, end = pos + len; p < end; p = hdr.payload + hdr.length) {
+		int res;
+
+		if (asn1_get_next(p, end - p, &hdr) < 0) {
+			wpa_printf(MSG_DEBUG, "X509: Failed to parse "
+				   "SubjectAltName item");
+			return -1;
+		}
+
+		if (hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC)
+			continue;
+
+		switch (hdr.tag) {
+		case 1:
+			res = x509_parse_alt_name_rfc8222(name, hdr.payload,
+							  hdr.length);
+			break;
+		case 2:
+			res = x509_parse_alt_name_dns(name, hdr.payload,
+						      hdr.length);
+			break;
+		case 6:
+			res = x509_parse_alt_name_uri(name, hdr.payload,
+						      hdr.length);
+			break;
+		case 7:
+			res = x509_parse_alt_name_ip(name, hdr.payload,
+						     hdr.length);
+			break;
+		case 8:
+			res = x509_parse_alt_name_rid(name, hdr.payload,
+						      hdr.length);
+			break;
+		case 0: /* TODO: otherName */
+		case 3: /* TODO: x500Address */
+		case 4: /* TODO: directoryName */
+		case 5: /* TODO: ediPartyName */
+		default:
+			res = 0;
+			break;
+		}
+		if (res < 0)
+			return res;
+	}
+
+	return 0;
+}
+
+
+static int x509_parse_ext_subject_alt_name(struct x509_certificate *cert,
+					   const u8 *pos, size_t len)
+{
+	struct asn1_hdr hdr;
+
+	/* SubjectAltName ::= GeneralNames */
+
+	if (asn1_get_next(pos, len, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_SEQUENCE) {
+		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in "
+			   "SubjectAltName; found %d tag 0x%x",
+			   hdr.class, hdr.tag);
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "X509: SubjectAltName");
+	cert->extensions_present |= X509_EXT_SUBJECT_ALT_NAME;
+
+	if (hdr.length == 0)
+		return 0;
+
+	return x509_parse_ext_alt_name(&cert->subject, hdr.payload,
+				       hdr.length);
+}
+
+
+static int x509_parse_ext_issuer_alt_name(struct x509_certificate *cert,
+					  const u8 *pos, size_t len)
+{
+	struct asn1_hdr hdr;
+
+	/* IssuerAltName ::= GeneralNames */
+
+	if (asn1_get_next(pos, len, &hdr) < 0 ||
+	    hdr.class != ASN1_CLASS_UNIVERSAL ||
+	    hdr.tag != ASN1_TAG_SEQUENCE) {
+		wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in "
+			   "IssuerAltName; found %d tag 0x%x",
+			   hdr.class, hdr.tag);
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "X509: IssuerAltName");
+	cert->extensions_present |= X509_EXT_ISSUER_ALT_NAME;
+
+	if (hdr.length == 0)
+		return 0;
+
+	return x509_parse_ext_alt_name(&cert->issuer, hdr.payload,
+				       hdr.length);
+}
+
+
 static int x509_parse_extension_data(struct x509_certificate *cert,
 				     struct asn1_oid *oid,
 				     const u8 *pos, size_t len)
@@ -824,7 +1090,6 @@ static int x509_parse_extension_data(struct x509_certificate *cert,
 
 	/* TODO: add other extensions required by RFC 3280, Ch 4.2:
 	 * certificate policies (section 4.2.1.5)
-	 * the subject alternative name (section 4.2.1.7)
 	 * name constraints (section 4.2.1.11)
 	 * policy constraints (section 4.2.1.12)
 	 * extended key usage (section 4.2.1.13)
@@ -833,6 +1098,10 @@ static int x509_parse_extension_data(struct x509_certificate *cert,
 	switch (oid->oid[3]) {
 	case 15: /* id-ce-keyUsage */
 		return x509_parse_ext_key_usage(cert, pos, len);
+	case 17: /* id-ce-subjectAltName */
+		return x509_parse_ext_subject_alt_name(cert, pos, len);
+	case 18: /* id-ce-issuerAltName */
+		return x509_parse_ext_issuer_alt_name(cert, pos, len);
 	case 19: /* id-ce-basicConstraints */
 		return x509_parse_ext_basic_constraints(cert, pos, len);
 	default:
@@ -1495,18 +1764,12 @@ int x509_certificate_check_signature(struct x509_certificate *issuer,
 			    hash, hash_len);
 		break;
 	case 11: /* sha256WithRSAEncryption */
-#ifdef NEED_SHA256
 		sha256_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len,
 			      hash);
 		hash_len = 32;
 		wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)",
 			    hash, hash_len);
 		break;
-#else /* NEED_SHA256 */
-		wpa_printf(MSG_INFO, "X509: SHA256 support disabled");
-		os_free(data);
-		return -1;
-#endif /* NEED_SHA256 */
 	case 2: /* md2WithRSAEncryption */
 	case 12: /* sha384WithRSAEncryption */
 	case 13: /* sha512WithRSAEncryption */
@@ -1720,5 +1983,3 @@ int x509_certificate_self_signed(struct x509_certificate *cert)
 {
 	return x509_name_compare(&cert->issuer, &cert->subject) == 0;
 }
-
-#endif /* CONFIG_INTERNAL_X509 */
diff --git a/contrib/wpa/src/tls/x509v3.h b/contrib/wpa/src/tls/x509v3.h
index a52bcf886453..37292d7e7dec 100644
--- a/contrib/wpa/src/tls/x509v3.h
+++ b/contrib/wpa/src/tls/x509v3.h
@@ -21,14 +21,34 @@ struct x509_algorithm_identifier {
 	struct asn1_oid oid;
 };
 
+struct x509_name_attr {
+	enum x509_name_attr_type {
+		X509_NAME_ATTR_NOT_USED,
+		X509_NAME_ATTR_DC,
+		X509_NAME_ATTR_CN,
+		X509_NAME_ATTR_C,
+		X509_NAME_ATTR_L,
+		X509_NAME_ATTR_ST,
+		X509_NAME_ATTR_O,
+		X509_NAME_ATTR_OU
+	} type;
+	char *value;
+};
+
+#define X509_MAX_NAME_ATTRIBUTES 20
+
 struct x509_name {
-	char *cn; /* commonName */
-	char *c; /* countryName */
-	char *l; /* localityName */
-	char *st; /* stateOrProvinceName */
-	char *o; /* organizationName */
-	char *ou; /* organizationalUnitName */
+	struct x509_name_attr attr[X509_MAX_NAME_ATTRIBUTES];
+	size_t num_attr;
 	char *email; /* emailAddress */
+
+	/* from alternative name extension */
+	char *alt_email; /* rfc822Name */
+	char *dns; /* dNSName */
+	char *uri; /* uniformResourceIdentifier */
+	u8 *ip; /* iPAddress */
+	size_t ip_len; /* IPv4: 4, IPv6: 16 */
+	struct asn1_oid rid; /* registeredID */
 };
 
 struct x509_certificate {
@@ -52,6 +72,8 @@ struct x509_certificate {
 #define X509_EXT_BASIC_CONSTRAINTS		(1 << 0)
 #define X509_EXT_PATH_LEN_CONSTRAINT		(1 << 1)
 #define X509_EXT_KEY_USAGE			(1 << 2)
+#define X509_EXT_SUBJECT_ALT_NAME		(1 << 3)
+#define X509_EXT_ISSUER_ALT_NAME		(1 << 4)
 
 	/* BasicConstraints */
 	int ca; /* cA */
@@ -89,8 +111,6 @@ enum {
 	X509_VALIDATE_UNKNOWN_CA
 };
 
-#ifdef CONFIG_INTERNAL_X509
-
 void x509_certificate_free(struct x509_certificate *cert);
 struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len);
 void x509_name_string(struct x509_name *name, char *buf, size_t len);
@@ -106,49 +126,4 @@ x509_certificate_get_subject(struct x509_certificate *chain,
 			     struct x509_name *name);
 int x509_certificate_self_signed(struct x509_certificate *cert);
 
-#else /* CONFIG_INTERNAL_X509 */
-
-static inline void x509_certificate_free(struct x509_certificate *cert)
-{
-}
-
-static inline struct x509_certificate *
-x509_certificate_parse(const u8 *buf, size_t len)
-{
-	return NULL;
-}
-
-static inline void x509_name_string(struct x509_name *name, char *buf,
-				    size_t len)
-{
-	if (len)
-		buf[0] = '\0';
-}
-
-static inline void x509_certificate_chain_free(struct x509_certificate *cert)
-{
-}
-
-static inline int
-x509_certificate_chain_validate(struct x509_certificate *trusted,
-				struct x509_certificate *chain,
-				int *reason)
-{
-	return -1;
-}
-
-static inline struct x509_certificate *
-x509_certificate_get_subject(struct x509_certificate *chain,
-			     struct x509_name *name)
-{
-	return NULL;
-}
-
-static inline int x509_certificate_self_signed(struct x509_certificate *cert)
-{
-	return -1;
-}
-
-#endif /* CONFIG_INTERNAL_X509 */
-
 #endif /* X509V3_H */
diff --git a/contrib/wpa/src/utils/.gitignore b/contrib/wpa/src/utils/.gitignore
new file mode 100644
index 000000000000..833734f887ac
--- /dev/null
+++ b/contrib/wpa/src/utils/.gitignore
@@ -0,0 +1 @@
+libutils.a
diff --git a/contrib/wpa/src/utils/Makefile b/contrib/wpa/src/utils/Makefile
index cffba620da04..527cf3e73bb8 100644
--- a/contrib/wpa/src/utils/Makefile
+++ b/contrib/wpa/src/utils/Makefile
@@ -1,9 +1,36 @@
-all:
-	@echo Nothing to be made.
+all: libutils.a
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
-	rm -f *~ *.o *.d
+	rm -f *~ *.o *.d libutils.a
 
 install:
 	@echo Nothing to be made.
+
+
+include ../lib.rules
+
+#CFLAGS += -DWPA_TRACE
+CFLAGS += -DCONFIG_IPV6
+
+LIB_OBJS= \
+	base64.o \
+	common.o \
+	ip_addr.o \
+	radiotap.o \
+	trace.o \
+	uuid.o \
+	wpa_debug.o \
+	wpabuf.o
+
+# Pick correct OS wrapper implementation
+LIB_OBJS += os_unix.o
+
+# Pick correct event loop implementation
+LIB_OBJS += eloop.o
+
+#LIB_OBJS += pcsc_funcs.o
+
+libutils.a: $(LIB_OBJS)
+	$(AR) crT $@ $?
+
+-include $(OBJS:%.o=%.d)
diff --git a/contrib/wpa/src/utils/base64.c b/contrib/wpa/src/utils/base64.c
index 13fc511dc614..155bfce83aa5 100644
--- a/contrib/wpa/src/utils/base64.c
+++ b/contrib/wpa/src/utils/base64.c
@@ -152,38 +152,3 @@ unsigned char * base64_decode(const unsigned char *src, size_t len,
 	*out_len = pos - out;
 	return out;
 }
-
-
-#ifdef TEST_MAIN
-
-int main(int argc, char *argv[])
-{
-	FILE *f;
-	size_t len, elen;
-	unsigned char *buf, *e;
-
-	if (argc != 4) {
-		printf("Usage: base64   \n");
-		return -1;
-	}
-
-	buf = os_readfile(argv[2], &len);
-	if (buf == NULL)
-		return -1;
-
-	if (strcmp(argv[1], "encode") == 0)
-		e = base64_encode(buf, len, &elen);
-	else
-		e = base64_decode(buf, len, &elen);
-	if (e == NULL)
-		return -2;
-	f = fopen(argv[3], "w");
-	if (f == NULL)
-		return -3;
-	fwrite(e, 1, elen, f);
-	fclose(f);
-	free(e);
-
-	return 0;
-}
-#endif /* TEST_MAIN */
diff --git a/contrib/wpa/src/utils/build_config.h b/contrib/wpa/src/utils/build_config.h
index 1e147fe36911..366677849231 100644
--- a/contrib/wpa/src/utils/build_config.h
+++ b/contrib/wpa/src/utils/build_config.h
@@ -28,7 +28,6 @@
 #define CONFIG_ANSI_C_EXTRA
 #define CONFIG_WINPCAP
 #define IEEE8021X_EAPOL
-#define EAP_TLS_FUNCS
 #define PKCS12_FUNCS
 #define PCSC_FUNCS
 #define CONFIG_CTRL_IFACE
@@ -48,16 +47,8 @@
 #define _CRT_SECURE_NO_DEPRECATE
 
 #ifdef USE_INTERNAL_CRYPTO
-#define CONFIG_TLS_INTERNAL
 #define CONFIG_TLS_INTERNAL_CLIENT
 #define CONFIG_INTERNAL_LIBTOMMATH
-#define INTERNAL_AES
-#define INTERNAL_SHA1
-#define INTERNAL_SHA256
-#define INTERNAL_MD5
-#define INTERNAL_MD4
-#define INTERNAL_DES
-#define CONFIG_INTERNAL_X509
 #define CONFIG_CRYPTO_INTERNAL
 #endif /* USE_INTERNAL_CRYPTO */
 #endif /* CONFIG_WIN32_DEFAULTS */
@@ -69,15 +60,7 @@
 #define CONFIG_NO_HOSTAPD_LOGGER
 #define CONFIG_NO_STDOUT_DEBUG
 #define CONFIG_BACKEND_FILE
-#define INTERNAL_AES
-#define INTERNAL_SHA1
-#define INTERNAL_MD5
-#define INTERNAL_MD4
-#define INTERNAL_DES
 #define CONFIG_INTERNAL_LIBTOMMATH
-#define CONFIG_INTERNAL_X509
-#define EAP_TLS_FUNCS
-#define CONFIG_TLS_INTERNAL
 #define CONFIG_CRYPTO_INTERNAL
 #define IEEE8021X_EAPOL
 #define PKCS12_FUNCS
@@ -92,4 +75,31 @@
 #define EAP_FAST
 #endif /* __SYMBIAN32__ */
 
+#ifdef CONFIG_XCODE_DEFAULTS
+#define CONFIG_DRIVER_OSX
+#define CONFIG_BACKEND_FILE
+#define IEEE8021X_EAPOL
+#define PKCS12_FUNCS
+#define CONFIG_CTRL_IFACE
+#define CONFIG_CTRL_IFACE_UNIX
+#define CONFIG_DEBUG_FILE
+#define EAP_MD5
+#define EAP_TLS
+#define EAP_MSCHAPv2
+#define EAP_PEAP
+#define EAP_TTLS
+#define EAP_GTC
+#define EAP_OTP
+#define EAP_LEAP
+#define EAP_TNC
+#define CONFIG_WPS
+#define EAP_WSC
+
+#ifdef USE_INTERNAL_CRYPTO
+#define CONFIG_TLS_INTERNAL_CLIENT
+#define CONFIG_INTERNAL_LIBTOMMATH
+#define CONFIG_CRYPTO_INTERNAL
+#endif /* USE_INTERNAL_CRYPTO */
+#endif /* CONFIG_XCODE_DEFAULTS */
+
 #endif /* BUILD_CONFIG_H */
diff --git a/contrib/wpa/src/utils/common.c b/contrib/wpa/src/utils/common.c
index 9a46ebe461da..1b8ea80e7d05 100644
--- a/contrib/wpa/src/utils/common.c
+++ b/contrib/wpa/src/utils/common.c
@@ -43,7 +43,7 @@ static int hex2byte(const char *hex)
 
 
 /**
- * hwaddr_aton - Convert ASCII string to MAC address
+ * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format)
  * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
  * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
@@ -70,6 +70,36 @@ int hwaddr_aton(const char *txt, u8 *addr)
 }
 
 
+/**
+ * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
+ * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
+ * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
+ * Returns: Characters used (> 0) on success, -1 on failure
+ */
+int hwaddr_aton2(const char *txt, u8 *addr)
+{
+	int i;
+	const char *pos = txt;
+
+	for (i = 0; i < 6; i++) {
+		int a, b;
+
+		while (*pos == ':' || *pos == '.' || *pos == '-')
+			pos++;
+
+		a = hex2num(*pos++);
+		if (a < 0)
+			return -1;
+		b = hex2num(*pos++);
+		if (b < 0)
+			return -1;
+		*addr++ = (a << 4) | b;
+	}
+
+	return pos - txt;
+}
+
+
 /**
  * hexstr2bin - Convert ASCII hex string into binary data
  * @hex: ASCII hex string (e.g., "01ab")
diff --git a/contrib/wpa/src/utils/common.h b/contrib/wpa/src/utils/common.h
index d649391e37b6..f17bf69ff547 100644
--- a/contrib/wpa/src/utils/common.h
+++ b/contrib/wpa/src/utils/common.h
@@ -17,7 +17,7 @@
 
 #include "os.h"
 
-#ifdef __linux__
+#if defined(__linux__) || defined(__GLIBC__)
 #include 
 #include 
 #endif /* __linux__ */
@@ -314,6 +314,24 @@ static inline unsigned int wpa_swap_32(unsigned int v)
 #ifndef ETH_ALEN
 #define ETH_ALEN 6
 #endif
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+#ifndef ETH_P_ALL
+#define ETH_P_ALL 0x0003
+#endif
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
+#endif /* ETH_P_PAE */
+#ifndef ETH_P_EAPOL
+#define ETH_P_EAPOL ETH_P_PAE
+#endif /* ETH_P_EAPOL */
+#ifndef ETH_P_RSN_PREAUTH
+#define ETH_P_RSN_PREAUTH 0x88c7
+#endif /* ETH_P_RSN_PREAUTH */
+#ifndef ETH_P_RRB
+#define ETH_P_RRB 0x890D
+#endif /* ETH_P_RRB */
 
 
 #ifdef __GNUC__
@@ -418,6 +436,7 @@ typedef u64 __bitwise le64;
 #endif /* __must_check */
 
 int hwaddr_aton(const char *txt, u8 *addr);
+int hwaddr_aton2(const char *txt, u8 *addr);
 int hexstr2bin(const char *hex, u8 *buf, size_t len);
 void inc_byte_array(u8 *counter, size_t len);
 void wpa_get_ntp_timestamp(u8 *buf);
diff --git a/contrib/wpa/src/utils/eloop.c b/contrib/wpa/src/utils/eloop.c
index 4edb2a703396..4b615989c0bb 100644
--- a/contrib/wpa/src/utils/eloop.c
+++ b/contrib/wpa/src/utils/eloop.c
@@ -1,6 +1,6 @@
 /*
  * Event loop based on select() loop
- * Copyright (c) 2002-2005, Jouni Malinen 
+ * Copyright (c) 2002-2009, Jouni Malinen 
  *
  * 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
@@ -15,6 +15,8 @@
 #include "includes.h"
 
 #include "common.h"
+#include "trace.h"
+#include "list.h"
 #include "eloop.h"
 
 
@@ -23,14 +25,20 @@ struct eloop_sock {
 	void *eloop_data;
 	void *user_data;
 	eloop_sock_handler handler;
+	WPA_TRACE_REF(eloop);
+	WPA_TRACE_REF(user);
+	WPA_TRACE_INFO
 };
 
 struct eloop_timeout {
+	struct dl_list list;
 	struct os_time time;
 	void *eloop_data;
 	void *user_data;
 	eloop_timeout_handler handler;
-	struct eloop_timeout *next;
+	WPA_TRACE_REF(eloop);
+	WPA_TRACE_REF(user);
+	WPA_TRACE_INFO
 };
 
 struct eloop_signal {
@@ -47,15 +55,13 @@ struct eloop_sock_table {
 };
 
 struct eloop_data {
-	void *user_data;
-
 	int max_sock;
 
 	struct eloop_sock_table readers;
 	struct eloop_sock_table writers;
 	struct eloop_sock_table exceptions;
 
-	struct eloop_timeout *timeout;
+	struct dl_list timeout;
 
 	int signal_count;
 	struct eloop_signal *signals;
@@ -69,10 +75,56 @@ struct eloop_data {
 static struct eloop_data eloop;
 
 
-int eloop_init(void *user_data)
+#ifdef WPA_TRACE
+
+static void eloop_sigsegv_handler(int sig)
+{
+	wpa_trace_show("eloop SIGSEGV");
+	abort();
+}
+
+static void eloop_trace_sock_add_ref(struct eloop_sock_table *table)
+{
+	int i;
+	if (table == NULL || table->table == NULL)
+		return;
+	for (i = 0; i < table->count; i++) {
+		wpa_trace_add_ref(&table->table[i], eloop,
+				  table->table[i].eloop_data);
+		wpa_trace_add_ref(&table->table[i], user,
+				  table->table[i].user_data);
+	}
+}
+
+
+static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table)
+{
+	int i;
+	if (table == NULL || table->table == NULL)
+		return;
+	for (i = 0; i < table->count; i++) {
+		wpa_trace_remove_ref(&table->table[i], eloop,
+				     table->table[i].eloop_data);
+		wpa_trace_remove_ref(&table->table[i], user,
+				     table->table[i].user_data);
+	}
+}
+
+#else /* WPA_TRACE */
+
+#define eloop_trace_sock_add_ref(table) do { } while (0)
+#define eloop_trace_sock_remove_ref(table) do { } while (0)
+
+#endif /* WPA_TRACE */
+
+
+int eloop_init(void)
 {
 	os_memset(&eloop, 0, sizeof(eloop));
-	eloop.user_data = user_data;
+	dl_list_init(&eloop.timeout);
+#ifdef WPA_TRACE
+	signal(SIGSEGV, eloop_sigsegv_handler);
+#endif /* WPA_TRACE */
 	return 0;
 }
 
@@ -86,6 +138,7 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
 	if (table == NULL)
 		return -1;
 
+	eloop_trace_sock_remove_ref(table);
 	tmp = (struct eloop_sock *)
 		os_realloc(table->table,
 			   (table->count + 1) * sizeof(struct eloop_sock));
@@ -96,11 +149,13 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
 	tmp[table->count].eloop_data = eloop_data;
 	tmp[table->count].user_data = user_data;
 	tmp[table->count].handler = handler;
+	wpa_trace_record(&tmp[table->count]);
 	table->count++;
 	table->table = tmp;
 	if (sock > eloop.max_sock)
 		eloop.max_sock = sock;
 	table->changed = 1;
+	eloop_trace_sock_add_ref(table);
 
 	return 0;
 }
@@ -120,6 +175,7 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
 	}
 	if (i == table->count)
 		return;
+	eloop_trace_sock_remove_ref(table);
 	if (i != table->count - 1) {
 		os_memmove(&table->table[i], &table->table[i + 1],
 			   (table->count - i - 1) *
@@ -127,6 +183,7 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
 	}
 	table->count--;
 	table->changed = 1;
+	eloop_trace_sock_add_ref(table);
 }
 
 
@@ -171,12 +228,17 @@ static void eloop_sock_table_destroy(struct eloop_sock_table *table)
 	if (table) {
 		int i;
 		for (i = 0; i < table->count && table->table; i++) {
-			printf("ELOOP: remaining socket: sock=%d "
-			       "eloop_data=%p user_data=%p handler=%p\n",
-			       table->table[i].sock,
-			       table->table[i].eloop_data,
-			       table->table[i].user_data,
-			       table->table[i].handler);
+			wpa_printf(MSG_INFO, "ELOOP: remaining socket: "
+				   "sock=%d eloop_data=%p user_data=%p "
+				   "handler=%p",
+				   table->table[i].sock,
+				   table->table[i].eloop_data,
+				   table->table[i].user_data,
+				   table->table[i].handler);
+			wpa_trace_dump_funcname("eloop unregistered socket "
+						"handler",
+						table->table[i].handler);
+			wpa_trace_dump("eloop sock", &table->table[i]);
 		}
 		os_free(table->table);
 	}
@@ -237,9 +299,9 @@ int eloop_register_timeout(unsigned int secs, unsigned int usecs,
 			   eloop_timeout_handler handler,
 			   void *eloop_data, void *user_data)
 {
-	struct eloop_timeout *timeout, *tmp, *prev;
+	struct eloop_timeout *timeout, *tmp;
 
-	timeout = os_malloc(sizeof(*timeout));
+	timeout = os_zalloc(sizeof(*timeout));
 	if (timeout == NULL)
 		return -1;
 	if (os_get_time(&timeout->time) < 0) {
@@ -255,60 +317,48 @@ int eloop_register_timeout(unsigned int secs, unsigned int usecs,
 	timeout->eloop_data = eloop_data;
 	timeout->user_data = user_data;
 	timeout->handler = handler;
-	timeout->next = NULL;
+	wpa_trace_add_ref(timeout, eloop, eloop_data);
+	wpa_trace_add_ref(timeout, user, user_data);
+	wpa_trace_record(timeout);
 
-	if (eloop.timeout == NULL) {
-		eloop.timeout = timeout;
-		return 0;
-	}
-
-	prev = NULL;
-	tmp = eloop.timeout;
-	while (tmp != NULL) {
-		if (os_time_before(&timeout->time, &tmp->time))
-			break;
-		prev = tmp;
-		tmp = tmp->next;
-	}
-
-	if (prev == NULL) {
-		timeout->next = eloop.timeout;
-		eloop.timeout = timeout;
-	} else {
-		timeout->next = prev->next;
-		prev->next = timeout;
+	/* Maintain timeouts in order of increasing time */
+	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
+		if (os_time_before(&timeout->time, &tmp->time)) {
+			dl_list_add(tmp->list.prev, &timeout->list);
+			return 0;
+		}
 	}
+	dl_list_add_tail(&eloop.timeout, &timeout->list);
 
 	return 0;
 }
 
 
+static void eloop_remove_timeout(struct eloop_timeout *timeout)
+{
+	dl_list_del(&timeout->list);
+	wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data);
+	wpa_trace_remove_ref(timeout, user, timeout->user_data);
+	os_free(timeout);
+}
+
+
 int eloop_cancel_timeout(eloop_timeout_handler handler,
 			 void *eloop_data, void *user_data)
 {
-	struct eloop_timeout *timeout, *prev, *next;
+	struct eloop_timeout *timeout, *prev;
 	int removed = 0;
 
-	prev = NULL;
-	timeout = eloop.timeout;
-	while (timeout != NULL) {
-		next = timeout->next;
-
+	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
+			      struct eloop_timeout, list) {
 		if (timeout->handler == handler &&
 		    (timeout->eloop_data == eloop_data ||
 		     eloop_data == ELOOP_ALL_CTX) &&
 		    (timeout->user_data == user_data ||
 		     user_data == ELOOP_ALL_CTX)) {
-			if (prev == NULL)
-				eloop.timeout = next;
-			else
-				prev->next = next;
-			os_free(timeout);
+			eloop_remove_timeout(timeout);
 			removed++;
-		} else
-			prev = timeout;
-
-		timeout = next;
+		}
 	}
 
 	return removed;
@@ -320,14 +370,11 @@ int eloop_is_timeout_registered(eloop_timeout_handler handler,
 {
 	struct eloop_timeout *tmp;
 
-	tmp = eloop.timeout;
-	while (tmp != NULL) {
+	dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
 		if (tmp->handler == handler &&
 		    tmp->eloop_data == eloop_data &&
 		    tmp->user_data == user_data)
 			return 1;
-
-		tmp = tmp->next;
 	}
 
 	return 0;
@@ -337,11 +384,11 @@ int eloop_is_timeout_registered(eloop_timeout_handler handler,
 #ifndef CONFIG_NATIVE_WINDOWS
 static void eloop_handle_alarm(int sig)
 {
-	fprintf(stderr, "eloop: could not process SIGINT or SIGTERM in two "
-		"seconds. Looks like there\n"
-		"is a bug that ends up in a busy loop that "
-		"prevents clean shutdown.\n"
-		"Killing program forcefully.\n");
+	wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in "
+		   "two seconds. Looks like there\n"
+		   "is a bug that ends up in a busy loop that "
+		   "prevents clean shutdown.\n"
+		   "Killing program forcefully.\n");
 	exit(1);
 }
 #endif /* CONFIG_NATIVE_WINDOWS */
@@ -390,7 +437,6 @@ static void eloop_process_pending_signals(void)
 		if (eloop.signals[i].signaled) {
 			eloop.signals[i].signaled = 0;
 			eloop.signals[i].handler(eloop.signals[i].sig,
-						 eloop.user_data,
 						 eloop.signals[i].user_data);
 		}
 	}
@@ -452,24 +498,21 @@ void eloop_run(void)
 	rfds = os_malloc(sizeof(*rfds));
 	wfds = os_malloc(sizeof(*wfds));
 	efds = os_malloc(sizeof(*efds));
-	if (rfds == NULL || wfds == NULL || efds == NULL) {
-		printf("eloop_run - malloc failed\n");
+	if (rfds == NULL || wfds == NULL || efds == NULL)
 		goto out;
-	}
 
 	while (!eloop.terminate &&
-	       (eloop.timeout || eloop.readers.count > 0 ||
+	       (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
 		eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
-		if (eloop.timeout) {
+		struct eloop_timeout *timeout;
+		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
+					list);
+		if (timeout) {
 			os_get_time(&now);
-			if (os_time_before(&now, &eloop.timeout->time))
-				os_time_sub(&eloop.timeout->time, &now, &tv);
+			if (os_time_before(&now, &timeout->time))
+				os_time_sub(&timeout->time, &now, &tv);
 			else
 				tv.sec = tv.usec = 0;
-#if 0
-			printf("next timeout in %lu.%06lu sec\n",
-			       tv.sec, tv.usec);
-#endif
 			_tv.tv_sec = tv.sec;
 			_tv.tv_usec = tv.usec;
 		}
@@ -478,7 +521,7 @@ void eloop_run(void)
 		eloop_sock_table_set_fds(&eloop.writers, wfds);
 		eloop_sock_table_set_fds(&eloop.exceptions, efds);
 		res = select(eloop.max_sock + 1, rfds, wfds, efds,
-			     eloop.timeout ? &_tv : NULL);
+			     timeout ? &_tv : NULL);
 		if (res < 0 && errno != EINTR && errno != 0) {
 			perror("select");
 			goto out;
@@ -486,16 +529,17 @@ void eloop_run(void)
 		eloop_process_pending_signals();
 
 		/* check if some registered timeouts have occurred */
-		if (eloop.timeout) {
-			struct eloop_timeout *tmp;
-
+		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
+					list);
+		if (timeout) {
 			os_get_time(&now);
-			if (!os_time_before(&now, &eloop.timeout->time)) {
-				tmp = eloop.timeout;
-				eloop.timeout = eloop.timeout->next;
-				tmp->handler(tmp->eloop_data,
-					     tmp->user_data);
-				os_free(tmp);
+			if (!os_time_before(&now, &timeout->time)) {
+				void *eloop_data = timeout->eloop_data;
+				void *user_data = timeout->user_data;
+				eloop_timeout_handler handler =
+					timeout->handler;
+				eloop_remove_timeout(timeout);
+				handler(eloop_data, user_data);
 			}
 
 		}
@@ -526,24 +570,24 @@ void eloop_destroy(void)
 	struct eloop_timeout *timeout, *prev;
 	struct os_time now;
 
-	timeout = eloop.timeout;
-	if (timeout)
-		os_get_time(&now);
-	while (timeout != NULL) {
+	os_get_time(&now);
+	dl_list_for_each_safe(timeout, prev, &eloop.timeout,
+			      struct eloop_timeout, list) {
 		int sec, usec;
-		prev = timeout;
-		timeout = timeout->next;
-		sec = prev->time.sec - now.sec;
-		usec = prev->time.usec - now.usec;
-		if (prev->time.usec < now.usec) {
+		sec = timeout->time.sec - now.sec;
+		usec = timeout->time.usec - now.usec;
+		if (timeout->time.usec < now.usec) {
 			sec--;
 			usec += 1000000;
 		}
-		printf("ELOOP: remaining timeout: %d.%06d eloop_data=%p "
-		       "user_data=%p handler=%p\n",
-		       sec, usec, prev->eloop_data, prev->user_data,
-		       prev->handler);
-		os_free(prev);
+		wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d "
+			   "eloop_data=%p user_data=%p handler=%p",
+			   sec, usec, timeout->eloop_data, timeout->user_data,
+			   timeout->handler);
+		wpa_trace_dump_funcname("eloop unregistered timeout handler",
+					timeout->handler);
+		wpa_trace_dump("eloop timeout", timeout);
+		eloop_remove_timeout(timeout);
 	}
 	eloop_sock_table_destroy(&eloop.readers);
 	eloop_sock_table_destroy(&eloop.writers);
@@ -569,9 +613,3 @@ void eloop_wait_for_read_sock(int sock)
 	FD_SET(sock, &rfds);
 	select(sock + 1, &rfds, NULL, NULL, NULL);
 }
-
-
-void * eloop_get_user_data(void)
-{
-	return eloop.user_data;
-}
diff --git a/contrib/wpa/src/utils/eloop.h b/contrib/wpa/src/utils/eloop.h
index cf83f3836555..1228f24d22c8 100644
--- a/contrib/wpa/src/utils/eloop.h
+++ b/contrib/wpa/src/utils/eloop.h
@@ -65,25 +65,19 @@ typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx);
 /**
  * eloop_signal_handler - eloop signal event callback type
  * @sig: Signal number
- * @eloop_ctx: Registered callback context data (global user_data from
- * eloop_init() call)
  * @signal_ctx: Registered callback context data (user_data from
  * eloop_register_signal(), eloop_register_signal_terminate(), or
  * eloop_register_signal_reconfig() call)
  */
-typedef void (*eloop_signal_handler)(int sig, void *eloop_ctx,
-				     void *signal_ctx);
+typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
 
 /**
  * eloop_init() - Initialize global event loop data
- * @user_data: Pointer to global data passed as eloop_ctx to signal handlers
  * Returns: 0 on success, -1 on failure
  *
- * This function must be called before any other eloop_* function. user_data
- * can be used to configure a global (to the process) pointer that will be
- * passed as eloop_ctx parameter to signal handlers.
+ * This function must be called before any other eloop_* function.
  */
-int eloop_init(void *user_data);
+int eloop_init(void);
 
 /**
  * eloop_register_read_sock - Register handler for read events
@@ -231,10 +225,6 @@ int eloop_is_timeout_registered(eloop_timeout_handler handler,
  * handler has returned. This means that the normal limits for sighandlers
  * (i.e., only "safe functions" allowed) do not apply for the registered
  * callback.
- *
- * Signals are 'global' events and there is no local eloop_data pointer like
- * with other handlers. The global user_data pointer registered with
- * eloop_init() will be used as eloop_ctx for signal handlers.
  */
 int eloop_register_signal(int sig, eloop_signal_handler handler,
 			  void *user_data);
@@ -251,10 +241,6 @@ int eloop_register_signal(int sig, eloop_signal_handler handler,
  * sighandlers (i.e., only "safe functions" allowed) do not apply for the
  * registered callback.
  *
- * Signals are 'global' events and there is no local eloop_data pointer like
- * with other handlers. The global user_data pointer registered with
- * eloop_init() will be used as eloop_ctx for signal handlers.
- *
  * This function is a more portable version of eloop_register_signal() since
  * the knowledge of exact details of the signals is hidden in eloop
  * implementation. In case of operating systems using signal(), this function
@@ -275,10 +261,6 @@ int eloop_register_signal_terminate(eloop_signal_handler handler,
  * limits for sighandlers (i.e., only "safe functions" allowed) do not apply
  * for the registered callback.
  *
- * Signals are 'global' events and there is no local eloop_data pointer like
- * with other handlers. The global user_data pointer registered with
- * eloop_init() will be used as eloop_ctx for signal handlers.
- *
  * This function is a more portable version of eloop_register_signal() since
  * the knowledge of exact details of the signals is hidden in eloop
  * implementation. In case of operating systems using signal(), this function
@@ -331,10 +313,4 @@ int eloop_terminated(void);
  */
 void eloop_wait_for_read_sock(int sock);
 
-/**
- * eloop_get_user_data - Get global user data
- * Returns: user_data pointer that was registered with eloop_init()
- */
-void * eloop_get_user_data(void);
-
 #endif /* ELOOP_H */
diff --git a/contrib/wpa/src/utils/eloop_none.c b/contrib/wpa/src/utils/eloop_none.c
index 215030b2135f..18eae4e5a778 100644
--- a/contrib/wpa/src/utils/eloop_none.c
+++ b/contrib/wpa/src/utils/eloop_none.c
@@ -41,8 +41,6 @@ struct eloop_signal {
 };
 
 struct eloop_data {
-	void *user_data;
-
 	int max_sock, reader_count;
 	struct eloop_sock *readers;
 
@@ -60,10 +58,9 @@ struct eloop_data {
 static struct eloop_data eloop;
 
 
-int eloop_init(void *user_data)
+int eloop_init(void)
 {
 	memset(&eloop, 0, sizeof(eloop));
-	eloop.user_data = user_data;
 	return 0;
 }
 
@@ -402,9 +399,3 @@ void eloop_wait_for_read_sock(int sock)
 	 * reading
 	 */
 }
-
-
-void * eloop_get_user_data(void)
-{
-	return eloop.user_data;
-}
diff --git a/contrib/wpa/src/utils/eloop_win.c b/contrib/wpa/src/utils/eloop_win.c
index c95aa76b7882..94cc72d04c6b 100644
--- a/contrib/wpa/src/utils/eloop_win.c
+++ b/contrib/wpa/src/utils/eloop_win.c
@@ -50,8 +50,6 @@ struct eloop_signal {
 };
 
 struct eloop_data {
-	void *user_data;
-
 	int max_sock;
 	size_t reader_count;
 	struct eloop_sock *readers;
@@ -79,10 +77,9 @@ struct eloop_data {
 static struct eloop_data eloop;
 
 
-int eloop_init(void *user_data)
+int eloop_init(void)
 {
 	os_memset(&eloop, 0, sizeof(eloop));
-	eloop.user_data = user_data;
 	eloop.num_handles = 1;
 	eloop.handles = os_malloc(eloop.num_handles *
 				  sizeof(eloop.handles[0]));
@@ -372,7 +369,6 @@ static void eloop_process_pending_signals(void)
 		if (eloop.signals[i].signaled) {
 			eloop.signals[i].signaled = 0;
 			eloop.signals[i].handler(eloop.signals[i].sig,
-						 eloop.user_data,
 						 eloop.signals[i].user_data);
 		}
 	}
@@ -380,7 +376,6 @@ static void eloop_process_pending_signals(void)
 	if (eloop.term_signal.signaled) {
 		eloop.term_signal.signaled = 0;
 		eloop.term_signal.handler(eloop.term_signal.sig,
-					  eloop.user_data,
 					  eloop.term_signal.user_data);
 	}
 }
@@ -614,9 +609,3 @@ void eloop_wait_for_read_sock(int sock)
 	WSAEventSelect(sock, event, 0);
 	WSACloseEvent(event);
 }
-
-
-void * eloop_get_user_data(void)
-{
-	return eloop.user_data;
-}
diff --git a/contrib/wpa/src/utils/ip_addr.h b/contrib/wpa/src/utils/ip_addr.h
index 192049a58311..28ccaefdea2b 100644
--- a/contrib/wpa/src/utils/ip_addr.h
+++ b/contrib/wpa/src/utils/ip_addr.h
@@ -16,13 +16,14 @@
 #define IP_ADDR_H
 
 struct hostapd_ip_addr {
+	int af; /* AF_INET / AF_INET6 */
 	union {
 		struct in_addr v4;
 #ifdef CONFIG_IPV6
 		struct in6_addr v6;
 #endif /* CONFIG_IPV6 */
+		u8 max_len[16];
 	} u;
-	int af; /* AF_INET / AF_INET6 */
 };
 
 const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf,
diff --git a/contrib/wpa/src/utils/list.h b/contrib/wpa/src/utils/list.h
new file mode 100644
index 000000000000..ed7c0227264f
--- /dev/null
+++ b/contrib/wpa/src/utils/list.h
@@ -0,0 +1,89 @@
+/*
+ * Doubly-linked list
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 LIST_H
+#define LIST_H
+
+/**
+ * struct dl_list - Doubly-linked list
+ */
+struct dl_list {
+	struct dl_list *next;
+	struct dl_list *prev;
+};
+
+static inline void dl_list_init(struct dl_list *list)
+{
+	list->next = list;
+	list->prev = list;
+}
+
+static inline void dl_list_add(struct dl_list *list, struct dl_list *item)
+{
+	item->next = list->next;
+	item->prev = list;
+	list->next->prev = item;
+	list->next = item;
+}
+
+static inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item)
+{
+	dl_list_add(list->prev, item);
+}
+
+static inline void dl_list_del(struct dl_list *item)
+{
+	item->next->prev = item->prev;
+	item->prev->next = item->next;
+	item->next = NULL;
+	item->prev = NULL;
+}
+
+static inline int dl_list_empty(struct dl_list *list)
+{
+	return list->next == list;
+}
+
+static inline unsigned int dl_list_len(struct dl_list *list)
+{
+	struct dl_list *item;
+	int count = 0;
+	for (item = list->next; item != list; item = item->next)
+		count++;
+	return count;
+}
+
+#ifndef offsetof
+#define offsetof(type, member) ((long) &((type *) 0)->member)
+#endif
+
+#define dl_list_entry(item, type, member) \
+	((type *) ((char *) item - offsetof(type, member)))
+
+#define dl_list_first(list, type, member) \
+	(dl_list_empty((list)) ? NULL : \
+	 dl_list_entry((list)->next, type, member))
+
+#define dl_list_for_each(item, list, type, member) \
+	for (item = dl_list_entry((list)->next, type, member); \
+	     &item->member != (list); \
+	     item = dl_list_entry(item->member.next, type, member))
+
+#define dl_list_for_each_safe(item, n, list, type, member) \
+	for (item = dl_list_entry((list)->next, type, member), \
+		     n = dl_list_entry(item->member.next, type, member); \
+	     &item->member != (list); \
+	     item = n, n = dl_list_entry(n->member.next, type, member))
+
+#endif /* LIST_H */
diff --git a/contrib/wpa/src/utils/os.h b/contrib/wpa/src/utils/os.h
index d6dfea682c2e..f4723d87525d 100644
--- a/contrib/wpa/src/utils/os.h
+++ b/contrib/wpa/src/utils/os.h
@@ -1,6 +1,6 @@
 /*
- * wpa_supplicant/hostapd / OS specific functions
- * Copyright (c) 2005-2006, Jouni Malinen 
+ * OS specific functions
+ * Copyright (c) 2005-2009, Jouni Malinen 
  *
  * 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
@@ -379,6 +379,12 @@ int os_snprintf(char *str, size_t size, const char *format, ...);
 
 #else /* OS_NO_C_LIB_DEFINES */
 
+#ifdef WPA_TRACE
+void * os_malloc(size_t size);
+void * os_realloc(void *ptr, size_t size);
+void os_free(void *ptr);
+char * os_strdup(const char *s);
+#else /* WPA_TRACE */
 #ifndef os_malloc
 #define os_malloc(s) malloc((s))
 #endif
@@ -388,6 +394,14 @@ int os_snprintf(char *str, size_t size, const char *format, ...);
 #ifndef os_free
 #define os_free(p) free((p))
 #endif
+#ifndef os_strdup
+#ifdef _MSC_VER
+#define os_strdup(s) _strdup(s)
+#else
+#define os_strdup(s) strdup(s)
+#endif
+#endif
+#endif /* WPA_TRACE */
 
 #ifndef os_memcpy
 #define os_memcpy(d, s, n) memcpy((d), (s), (n))
@@ -402,13 +416,6 @@ int os_snprintf(char *str, size_t size, const char *format, ...);
 #define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n))
 #endif
 
-#ifndef os_strdup
-#ifdef _MSC_VER
-#define os_strdup(s) _strdup(s)
-#else
-#define os_strdup(s) strdup(s)
-#endif
-#endif
 #ifndef os_strlen
 #define os_strlen(s) strlen(s)
 #endif
diff --git a/contrib/wpa/src/utils/os_internal.c b/contrib/wpa/src/utils/os_internal.c
index 7b74bbf4abc7..5260e232101f 100644
--- a/contrib/wpa/src/utils/os_internal.c
+++ b/contrib/wpa/src/utils/os_internal.c
@@ -206,7 +206,12 @@ char * os_readfile(const char *name, size_t *len)
 		return NULL;
 	}
 
-	fread(buf, 1, *len, f);
+	if (fread(buf, 1, *len, f) != *len) {
+		fclose(f);
+		os_free(buf);
+		return NULL;
+	}
+
 	fclose(f);
 
 	return buf;
diff --git a/contrib/wpa/src/utils/os_unix.c b/contrib/wpa/src/utils/os_unix.c
index bc2fc40dd7eb..6f58fa46cf01 100644
--- a/contrib/wpa/src/utils/os_unix.c
+++ b/contrib/wpa/src/utils/os_unix.c
@@ -1,6 +1,6 @@
 /*
- * wpa_supplicant/hostapd / OS specific functions for UNIX/POSIX systems
- * Copyright (c) 2005-2006, Jouni Malinen 
+ * OS specific functions for UNIX/POSIX systems
+ * Copyright (c) 2005-2009, Jouni Malinen 
  *
  * 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
@@ -16,6 +16,28 @@
 
 #include "os.h"
 
+#ifdef WPA_TRACE
+
+#include "common.h"
+#include "list.h"
+#include "wpa_debug.h"
+#include "trace.h"
+
+static struct dl_list alloc_list;
+
+#define ALLOC_MAGIC 0xa84ef1b2
+#define FREED_MAGIC 0x67fd487a
+
+struct os_alloc_trace {
+	unsigned int magic;
+	struct dl_list list;
+	size_t len;
+	WPA_TRACE_INFO
+};
+
+#endif /* WPA_TRACE */
+
+
 void os_sleep(os_time_t sec, os_time_t usec)
 {
 	if (sec)
@@ -172,16 +194,16 @@ char * os_rel2abs_path(const char *rel_path)
 	int last_errno;
 
 	if (rel_path[0] == '/')
-		return strdup(rel_path);
+		return os_strdup(rel_path);
 
 	for (;;) {
-		buf = malloc(len);
+		buf = os_malloc(len);
 		if (buf == NULL)
 			return NULL;
 		cwd = getcwd(buf, len);
 		if (cwd == NULL) {
 			last_errno = errno;
-			free(buf);
+			os_free(buf);
 			if (last_errno != ERANGE)
 				return NULL;
 			len *= 2;
@@ -193,29 +215,51 @@ char * os_rel2abs_path(const char *rel_path)
 		}
 	}
 
-	cwd_len = strlen(cwd);
-	rel_len = strlen(rel_path);
+	cwd_len = os_strlen(cwd);
+	rel_len = os_strlen(rel_path);
 	ret_len = cwd_len + 1 + rel_len + 1;
-	ret = malloc(ret_len);
+	ret = os_malloc(ret_len);
 	if (ret) {
-		memcpy(ret, cwd, cwd_len);
+		os_memcpy(ret, cwd, cwd_len);
 		ret[cwd_len] = '/';
-		memcpy(ret + cwd_len + 1, rel_path, rel_len);
+		os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
 		ret[ret_len - 1] = '\0';
 	}
-	free(buf);
+	os_free(buf);
 	return ret;
 }
 
 
 int os_program_init(void)
 {
+#ifdef WPA_TRACE
+	dl_list_init(&alloc_list);
+#endif /* WPA_TRACE */
 	return 0;
 }
 
 
 void os_program_deinit(void)
 {
+#ifdef WPA_TRACE
+	struct os_alloc_trace *a;
+	unsigned long total = 0;
+	dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
+		total += a->len;
+		if (a->magic != ALLOC_MAGIC) {
+			wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
+				   "len %lu",
+				   a, a->magic, (unsigned long) a->len);
+			continue;
+		}
+		wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
+			   a, (unsigned long) a->len);
+		wpa_trace_dump("memleak", a);
+	}
+	if (total)
+		wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
+			   (unsigned long) total);
+#endif /* WPA_TRACE */
 }
 
 
@@ -250,7 +294,7 @@ char * os_readfile(const char *name, size_t *len)
 	*len = ftell(f);
 	fseek(f, 0, SEEK_SET);
 
-	buf = malloc(*len);
+	buf = os_malloc(*len);
 	if (buf == NULL) {
 		fclose(f);
 		return NULL;
@@ -258,7 +302,7 @@ char * os_readfile(const char *name, size_t *len)
 
 	if (fread(buf, 1, *len, f) != *len) {
 		fclose(f);
-		free(buf);
+		os_free(buf);
 		return NULL;
 	}
 
@@ -268,10 +312,12 @@ char * os_readfile(const char *name, size_t *len)
 }
 
 
+#ifndef WPA_TRACE
 void * os_zalloc(size_t size)
 {
 	return calloc(1, size);
 }
+#endif /* WPA_TRACE */
 
 
 size_t os_strlcpy(char *dest, const char *src, size_t siz)
@@ -297,3 +343,95 @@ size_t os_strlcpy(char *dest, const char *src, size_t siz)
 
 	return s - src - 1;
 }
+
+
+#ifdef WPA_TRACE
+
+void * os_malloc(size_t size)
+{
+	struct os_alloc_trace *a;
+	a = malloc(sizeof(*a) + size);
+	if (a == NULL)
+		return NULL;
+	a->magic = ALLOC_MAGIC;
+	dl_list_add(&alloc_list, &a->list);
+	a->len = size;
+	wpa_trace_record(a);
+	return a + 1;
+}
+
+
+void * os_realloc(void *ptr, size_t size)
+{
+	struct os_alloc_trace *a;
+	size_t copy_len;
+	void *n;
+
+	if (ptr == NULL)
+		return os_malloc(size);
+
+	a = (struct os_alloc_trace *) ptr - 1;
+	if (a->magic != ALLOC_MAGIC) {
+		wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
+			   a, a->magic,
+			   a->magic == FREED_MAGIC ? " (already freed)" : "");
+		wpa_trace_show("Invalid os_realloc() call");
+		abort();
+	}
+	n = os_malloc(size);
+	if (n == NULL)
+		return NULL;
+	copy_len = a->len;
+	if (copy_len > size)
+		copy_len = size;
+	os_memcpy(n, a + 1, copy_len);
+	os_free(ptr);
+	return n;
+}
+
+
+void os_free(void *ptr)
+{
+	struct os_alloc_trace *a;
+
+	if (ptr == NULL)
+		return;
+	a = (struct os_alloc_trace *) ptr - 1;
+	if (a->magic != ALLOC_MAGIC) {
+		wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
+			   a, a->magic,
+			   a->magic == FREED_MAGIC ? " (already freed)" : "");
+		wpa_trace_show("Invalid os_free() call");
+		abort();
+	}
+	dl_list_del(&a->list);
+	a->magic = FREED_MAGIC;
+
+	wpa_trace_check_ref(ptr);
+	free(a);
+}
+
+
+void * os_zalloc(size_t size)
+{
+	void *ptr = os_malloc(size);
+	if (ptr)
+		os_memset(ptr, 0, size);
+	return ptr;
+}
+
+
+char * os_strdup(const char *s)
+{
+	size_t len;
+	char *d;
+	len = os_strlen(s);
+	d = os_malloc(len + 1);
+	if (d == NULL)
+		return NULL;
+	os_memcpy(d, s, len);
+	d[len] = '\0';
+	return d;
+}
+
+#endif /* WPA_TRACE */
diff --git a/contrib/wpa/hostapd/radiotap.c b/contrib/wpa/src/utils/radiotap.c
similarity index 100%
rename from contrib/wpa/hostapd/radiotap.c
rename to contrib/wpa/src/utils/radiotap.c
diff --git a/contrib/wpa/src/drivers/radiotap.h b/contrib/wpa/src/utils/radiotap.h
similarity index 99%
rename from contrib/wpa/src/drivers/radiotap.h
rename to contrib/wpa/src/utils/radiotap.h
index 508264c4cf33..ba23ed38e7a0 100644
--- a/contrib/wpa/src/drivers/radiotap.h
+++ b/contrib/wpa/src/utils/radiotap.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
+/* $FreeBSD$ */
 /* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */
 
 /*-
diff --git a/contrib/wpa/hostapd/radiotap_iter.h b/contrib/wpa/src/utils/radiotap_iter.h
similarity index 100%
rename from contrib/wpa/hostapd/radiotap_iter.h
rename to contrib/wpa/src/utils/radiotap_iter.h
diff --git a/contrib/wpa/src/utils/trace.c b/contrib/wpa/src/utils/trace.c
new file mode 100644
index 000000000000..bb3eb24d4c01
--- /dev/null
+++ b/contrib/wpa/src/utils/trace.c
@@ -0,0 +1,329 @@
+/*
+ * Backtrace debugging
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 "trace.h"
+
+#ifdef WPA_TRACE
+
+static struct dl_list active_references =
+{ &active_references, &active_references };
+
+#ifdef WPA_TRACE_BFD
+#include 
+#ifdef __linux__
+#include 
+#else /* __linux__ */
+#include 
+#endif /* __linux__ */
+
+static char *prg_fname = NULL;
+static bfd *cached_abfd = NULL;
+static asymbol **syms = NULL;
+
+static void get_prg_fname(void)
+{
+	char exe[50], fname[512];
+	int len;
+	os_snprintf(exe, sizeof(exe) - 1, "/proc/%u/exe", getpid());
+	len = readlink(exe, fname, sizeof(fname) - 1);
+	if (len < 0 || len >= (int) sizeof(fname)) {
+		perror("readlink");
+		return;
+	}
+	fname[len] = '\0';
+	prg_fname = strdup(fname);
+}
+
+
+static bfd * open_bfd(const char *fname)
+{
+	bfd *abfd;
+	char **matching;
+
+	abfd = bfd_openr(prg_fname, NULL);
+	if (abfd == NULL) {
+		wpa_printf(MSG_INFO, "bfd_openr failed");
+		return NULL;
+	}
+
+	if (bfd_check_format(abfd, bfd_archive)) {
+		wpa_printf(MSG_INFO, "bfd_check_format failed");
+		bfd_close(abfd);
+		return NULL;
+	}
+
+	if (!bfd_check_format_matches(abfd, bfd_object, &matching)) {
+		wpa_printf(MSG_INFO, "bfd_check_format_matches failed");
+		free(matching);
+		bfd_close(abfd);
+		return NULL;
+	}
+
+	return abfd;
+}
+
+
+static void read_syms(bfd *abfd)
+{
+	long storage, symcount;
+	bfd_boolean dynamic = FALSE;
+
+	if (syms)
+		return;
+
+	if (!(bfd_get_file_flags(abfd) & HAS_SYMS)) {
+		wpa_printf(MSG_INFO, "No symbols");
+		return;
+	}
+
+	storage = bfd_get_symtab_upper_bound(abfd);
+	if (storage == 0) {
+		storage = bfd_get_dynamic_symtab_upper_bound(abfd);
+		dynamic = TRUE;
+	}
+	if (storage < 0) {
+		wpa_printf(MSG_INFO, "Unknown symtab upper bound");
+		return;
+	}
+
+	syms = malloc(storage);
+	if (syms == NULL) {
+		wpa_printf(MSG_INFO, "Failed to allocate memory for symtab "
+			   "(%ld bytes)", storage);
+		return;
+	}
+	if (dynamic)
+		symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
+	else
+		symcount = bfd_canonicalize_symtab(abfd, syms);
+	if (symcount < 0) {
+		wpa_printf(MSG_INFO, "Failed to canonicalize %ssymtab",
+			   dynamic ? "dynamic " : "");
+		free(syms);
+		syms = NULL;
+		return;
+	}
+}
+
+
+struct bfd_data {
+	bfd_vma pc;
+	bfd_boolean found;
+	const char *filename;
+	const char *function;
+	unsigned int line;
+};
+
+
+static void find_addr_sect(bfd *abfd, asection *section, void *obj)
+{
+	struct bfd_data *data = obj;
+	bfd_vma vma;
+	bfd_size_type size;
+
+	if (data->found)
+		return;
+
+	if (!(bfd_get_section_vma(abfd, section)))
+		return;
+
+	vma = bfd_get_section_vma(abfd, section);
+	if (data->pc < vma)
+		return;
+
+	size = bfd_get_section_size(section);
+	if (data->pc >= vma + size)
+		return;
+
+	data->found = bfd_find_nearest_line(abfd, section, syms,
+					    data->pc - vma,
+					    &data->filename,
+					    &data->function,
+					    &data->line);
+}
+
+
+static void wpa_trace_bfd_addr(void *pc)
+{
+	bfd *abfd = cached_abfd;
+	struct bfd_data data;
+	const char *name;
+	char *aname = NULL;
+	const char *filename;
+
+	if (abfd == NULL)
+		return;
+
+	data.pc = (bfd_vma) pc;
+	data.found = FALSE;
+	bfd_map_over_sections(abfd, find_addr_sect, &data);
+
+	if (!data.found)
+		return;
+
+	do {
+		if (data.function)
+			aname = bfd_demangle(abfd, data.function,
+					     DMGL_ANSI | DMGL_PARAMS);
+		name = aname ? aname : data.function;
+		filename = data.filename;
+		if (filename) {
+			char *end = os_strrchr(filename, '/');
+			int i = 0;
+			while (*filename && *filename == prg_fname[i] &&
+			       filename <= end) {
+				filename++;
+				i++;
+			}
+		}
+		wpa_printf(MSG_INFO, "     %s() %s:%u",
+			   name, filename, data.line);
+		free(aname);
+
+		data.found = bfd_find_inliner_info(abfd, &data.filename,
+						   &data.function, &data.line);
+	} while (data.found);
+}
+
+
+static const char * wpa_trace_bfd_addr2func(void *pc)
+{
+	bfd *abfd = cached_abfd;
+	struct bfd_data data;
+
+	if (abfd == NULL)
+		return NULL;
+
+	data.pc = (bfd_vma) pc;
+	data.found = FALSE;
+	bfd_map_over_sections(abfd, find_addr_sect, &data);
+
+	if (!data.found)
+		return NULL;
+
+	return data.function;
+}
+
+
+static void wpa_trace_bfd_init(void)
+{
+	if (!prg_fname) {
+		get_prg_fname();
+		if (!prg_fname)
+			return;
+	}
+
+	if (!cached_abfd) {
+		cached_abfd = open_bfd(prg_fname);
+		if (!cached_abfd) {
+			wpa_printf(MSG_INFO, "Failed to open bfd");
+			return;
+		}
+	}
+
+	read_syms(cached_abfd);
+	if (!syms) {
+		wpa_printf(MSG_INFO, "Failed to read symbols");
+		return;
+	}
+}
+
+
+void wpa_trace_dump_funcname(const char *title, void *pc)
+{
+	wpa_printf(MSG_INFO, "WPA_TRACE: %s: %p", title, pc);
+	wpa_trace_bfd_init();
+	wpa_trace_bfd_addr(pc);
+}
+
+#else /* WPA_TRACE_BFD */
+
+#define wpa_trace_bfd_init() do { } while (0)
+#define wpa_trace_bfd_addr(pc) do { } while (0)
+#define wpa_trace_bfd_addr2func(pc) NULL
+
+#endif /* WPA_TRACE_BFD */
+
+void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num)
+{
+	char **sym;
+	int i;
+	enum { TRACE_HEAD, TRACE_RELEVANT, TRACE_TAIL } state;
+
+	wpa_trace_bfd_init();
+	wpa_printf(MSG_INFO, "WPA_TRACE: %s - START", title);
+	sym = backtrace_symbols(btrace, btrace_num);
+	state = TRACE_HEAD;
+	for (i = 0; i < btrace_num; i++) {
+		const char *func = wpa_trace_bfd_addr2func(btrace[i]);
+		if (state == TRACE_HEAD && func &&
+		    (os_strcmp(func, "wpa_trace_add_ref_func") == 0 ||
+		     os_strcmp(func, "wpa_trace_check_ref") == 0 ||
+		     os_strcmp(func, "wpa_trace_show") == 0))
+			continue;
+		if (state == TRACE_TAIL && sym && sym[i] &&
+		    os_strstr(sym[i], "__libc_start_main"))
+			break;
+		if (state == TRACE_HEAD)
+			state = TRACE_RELEVANT;
+		if (sym)
+			wpa_printf(MSG_INFO, "[%d]: %s", i, sym[i]);
+		else
+			wpa_printf(MSG_INFO, "[%d]: ?? [%p]", i, btrace[i]);
+		wpa_trace_bfd_addr(btrace[i]);
+		if (state == TRACE_RELEVANT && func &&
+		    os_strcmp(func, "main") == 0)
+			state = TRACE_TAIL;
+	}
+	free(sym);
+	wpa_printf(MSG_INFO, "WPA_TRACE: %s - END", title);
+}
+
+
+void wpa_trace_show(const char *title)
+{
+	struct info {
+		WPA_TRACE_INFO
+	} info;
+	wpa_trace_record(&info);
+	wpa_trace_dump(title, &info);
+}
+
+
+void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr)
+{
+	if (addr == NULL)
+		return;
+	ref->addr = addr;
+	wpa_trace_record(ref);
+	dl_list_add(&active_references, &ref->list);
+}
+
+
+void wpa_trace_check_ref(const void *addr)
+{
+	struct wpa_trace_ref *ref;
+	dl_list_for_each(ref, &active_references, struct wpa_trace_ref, list) {
+		if (addr != ref->addr)
+			continue;
+		wpa_trace_show("Freeing referenced memory");
+		wpa_trace_dump("Reference registration", ref);
+		abort();
+	}
+}
+
+#endif /* WPA_TRACE */
diff --git a/contrib/wpa/src/utils/trace.h b/contrib/wpa/src/utils/trace.h
new file mode 100644
index 000000000000..22d3de035acb
--- /dev/null
+++ b/contrib/wpa/src/utils/trace.h
@@ -0,0 +1,74 @@
+/*
+ * Backtrace debugging
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 TRACE_H
+#define TRACE_H
+
+#define WPA_TRACE_LEN 16
+
+#ifdef WPA_TRACE
+#include 
+
+#include "list.h"
+
+#define WPA_TRACE_INFO void *btrace[WPA_TRACE_LEN]; int btrace_num;
+
+struct wpa_trace_ref {
+	struct dl_list list;
+	const void *addr;
+	WPA_TRACE_INFO
+};
+#define WPA_TRACE_REF(name) struct wpa_trace_ref wpa_trace_ref_##name
+
+#define wpa_trace_dump(title, ptr) \
+	wpa_trace_dump_func((title), (ptr)->btrace, (ptr)->btrace_num)
+void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num);
+#define wpa_trace_record(ptr) \
+	(ptr)->btrace_num = backtrace((ptr)->btrace, WPA_TRACE_LEN)
+void wpa_trace_show(const char *title);
+#define wpa_trace_add_ref(ptr, name, addr) \
+	wpa_trace_add_ref_func(&(ptr)->wpa_trace_ref_##name, (addr))
+void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr);
+#define wpa_trace_remove_ref(ptr, name, addr)	\
+	do { \
+		if ((addr)) \
+			dl_list_del(&(ptr)->wpa_trace_ref_##name.list); \
+	} while (0)
+void wpa_trace_check_ref(const void *addr);
+
+#else /* WPA_TRACE */
+
+#define WPA_TRACE_INFO
+#define WPA_TRACE_REF(n)
+#define wpa_trace_dump(title, ptr) do { } while (0)
+#define wpa_trace_record(ptr) do { } while (0)
+#define wpa_trace_show(title) do { } while (0)
+#define wpa_trace_add_ref(ptr, name, addr) do { } while (0)
+#define wpa_trace_remove_ref(ptr, name, addr) do { } while (0)
+#define wpa_trace_check_ref(addr) do { } while (0)
+
+#endif /* WPA_TRACE */
+
+
+#ifdef WPA_TRACE_BFD
+
+void wpa_trace_dump_funcname(const char *title, void *pc);
+
+#else /* WPA_TRACE_BFD */
+
+#define wpa_trace_dump_funcname(title, pc) do { } while (0)
+
+#endif /* WPA_TRACE_BFD */
+
+#endif /* TRACE_H */
diff --git a/contrib/wpa/src/utils/uuid.c b/contrib/wpa/src/utils/uuid.c
index 620d3d610cd8..d8cc26754b39 100644
--- a/contrib/wpa/src/utils/uuid.c
+++ b/contrib/wpa/src/utils/uuid.c
@@ -15,8 +15,6 @@
 #include "includes.h"
 
 #include "common.h"
-#include "crypto.h"
-#include "sha1.h"
 #include "uuid.h"
 
 int uuid_str2bin(const char *str, u8 *bin)
@@ -77,31 +75,3 @@ int is_nil_uuid(const u8 *uuid)
 			return 0;
 	return 1;
 }
-
-
-void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid)
-{
-	const u8 *addr[2];
-	size_t len[2];
-	u8 hash[SHA1_MAC_LEN];
-	u8 nsid[16] = {
-		0x52, 0x64, 0x80, 0xf8,
-		0xc9, 0x9b,
-		0x4b, 0xe5,
-		0xa6, 0x55,
-		0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84
-	};
-
-	addr[0] = nsid;
-	len[0] = sizeof(nsid);
-	addr[1] = mac_addr;
-	len[1] = 6;
-	sha1_vector(2, addr, len, hash);
-	os_memcpy(uuid, hash, 16);
-
-	/* Version: 5 = named-based version using SHA-1 */
-	uuid[6] = (5 << 4) | (uuid[6] & 0x0f);
-
-	/* Variant specified in RFC 4122 */
-	uuid[8] = 0x80 | (uuid[8] & 0x3f);
-}
diff --git a/contrib/wpa/src/utils/uuid.h b/contrib/wpa/src/utils/uuid.h
index 9fc2ba06822f..075916525357 100644
--- a/contrib/wpa/src/utils/uuid.h
+++ b/contrib/wpa/src/utils/uuid.h
@@ -20,6 +20,5 @@
 int uuid_str2bin(const char *str, u8 *bin);
 int uuid_bin2str(const u8 *bin, char *str, size_t max_len);
 int is_nil_uuid(const u8 *uuid);
-void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid);
 
 #endif /* UUID_H */
diff --git a/contrib/wpa/src/utils/wpa_debug.c b/contrib/wpa/src/utils/wpa_debug.c
index 0f46aeecc64d..6f6fc69ccc44 100644
--- a/contrib/wpa/src/utils/wpa_debug.c
+++ b/contrib/wpa/src/utils/wpa_debug.c
@@ -18,6 +18,8 @@
 
 #ifdef CONFIG_DEBUG_SYSLOG
 #include 
+
+static int wpa_debug_syslog = 0;
 #endif /* CONFIG_DEBUG_SYSLOG */
 
 
@@ -27,7 +29,6 @@ static FILE *out_file = NULL;
 int wpa_debug_level = MSG_INFO;
 int wpa_debug_show_keys = 0;
 int wpa_debug_timestamp = 0;
-int wpa_debug_syslog = 0;
 
 
 #ifndef CONFIG_NO_STDOUT_DEBUG
@@ -49,23 +50,22 @@ void wpa_debug_print_timestamp(void)
 	printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec);
 }
 
+
+#ifdef CONFIG_DEBUG_SYSLOG
 void wpa_debug_open_syslog(void)
 {
-#ifdef CONFIG_DEBUG_SYSLOG
 	openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_DAEMON);
 	wpa_debug_syslog++;
-#endif
 }
 
+
 void wpa_debug_close_syslog(void)
 {
-#ifdef CONFIG_DEBUG_SYSLOG
 	if (wpa_debug_syslog)
 		closelog();
-#endif
 }
 
-#ifdef CONFIG_DEBUG_SYSLOG
+
 static int syslog_priority(int level)
 {
 	switch (level) {
@@ -390,6 +390,9 @@ void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level,
 	va_end(ap);
 	if (hostapd_logger_cb)
 		hostapd_logger_cb(ctx, addr, module, level, buf, len);
+	else if (addr)
+		wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s",
+			   MAC2STR(addr), buf);
 	else
 		wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf);
 	os_free(buf);
diff --git a/contrib/wpa/src/utils/wpa_debug.h b/contrib/wpa/src/utils/wpa_debug.h
index b4010d542760..6e5e79e281c4 100644
--- a/contrib/wpa/src/utils/wpa_debug.h
+++ b/contrib/wpa/src/utils/wpa_debug.h
@@ -221,6 +221,23 @@ enum hostapd_logger_level {
 };
 
 
+#ifdef CONFIG_DEBUG_SYSLOG
+
+void wpa_debug_open_syslog(void);
+void wpa_debug_close_syslog(void);
+
+#else /* CONFIG_DEBUG_SYSLOG */
+
+static inline void wpa_debug_open_syslog(void)
+{
+}
+
+static inline void wpa_debug_close_syslog(void)
+{
+}
+
+#endif /* CONFIG_DEBUG_SYSLOG */
+
 
 #ifdef EAPOL_TEST
 #define WPA_ASSERT(a)						       \
diff --git a/contrib/wpa/src/utils/wpabuf.c b/contrib/wpa/src/utils/wpabuf.c
index 8181912ea9f7..eda779eaff4f 100644
--- a/contrib/wpa/src/utils/wpabuf.c
+++ b/contrib/wpa/src/utils/wpabuf.c
@@ -15,13 +15,37 @@
 #include "includes.h"
 
 #include "common.h"
+#include "trace.h"
 #include "wpabuf.h"
 
+#ifdef WPA_TRACE
+#define WPABUF_MAGIC 0x51a974e3
+
+struct wpabuf_trace {
+	unsigned int magic;
+};
+
+static struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf)
+{
+	return (struct wpabuf_trace *)
+		((const u8 *) buf - sizeof(struct wpabuf_trace));
+}
+#endif /* WPA_TRACE */
+
+
 static void wpabuf_overflow(const struct wpabuf *buf, size_t len)
 {
+#ifdef WPA_TRACE
+	struct wpabuf_trace *trace = wpabuf_get_trace(buf);
+	if (trace->magic != WPABUF_MAGIC) {
+		wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x",
+			   trace->magic);
+	}
+#endif /* WPA_TRACE */
 	wpa_printf(MSG_ERROR, "wpabuf %p (size=%lu used=%lu) overflow len=%lu",
 		   buf, (unsigned long) buf->size, (unsigned long) buf->used,
 		   (unsigned long) len);
+	wpa_trace_show("wpabuf overflow");
 	abort();
 }
 
@@ -29,10 +53,25 @@ static void wpabuf_overflow(const struct wpabuf *buf, size_t len)
 int wpabuf_resize(struct wpabuf **_buf, size_t add_len)
 {
 	struct wpabuf *buf = *_buf;
+#ifdef WPA_TRACE
+	struct wpabuf_trace *trace;
+#endif /* WPA_TRACE */
+
 	if (buf == NULL) {
 		*_buf = wpabuf_alloc(add_len);
 		return *_buf == NULL ? -1 : 0;
 	}
+
+#ifdef WPA_TRACE
+	trace = wpabuf_get_trace(buf);
+	if (trace->magic != WPABUF_MAGIC) {
+		wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x",
+			   trace->magic);
+		wpa_trace_show("wpabuf_resize invalid magic");
+		abort();
+	}
+#endif /* WPA_TRACE */
+
 	if (buf->used + add_len > buf->size) {
 		unsigned char *nbuf;
 		if (buf->ext_data) {
@@ -42,6 +81,18 @@ int wpabuf_resize(struct wpabuf **_buf, size_t add_len)
 			os_memset(nbuf + buf->used, 0, add_len);
 			buf->ext_data = nbuf;
 		} else {
+#ifdef WPA_TRACE
+			nbuf = os_realloc(trace, sizeof(struct wpabuf_trace) +
+					  sizeof(struct wpabuf) +
+					  buf->used + add_len);
+			if (nbuf == NULL)
+				return -1;
+			trace = (struct wpabuf_trace *) nbuf;
+			buf = (struct wpabuf *) (trace + 1);
+			os_memset(nbuf + sizeof(struct wpabuf_trace) +
+				  sizeof(struct wpabuf) + buf->used, 0,
+				  add_len);
+#else /* WPA_TRACE */
 			nbuf = os_realloc(buf, sizeof(struct wpabuf) +
 					  buf->used + add_len);
 			if (nbuf == NULL)
@@ -49,6 +100,7 @@ int wpabuf_resize(struct wpabuf **_buf, size_t add_len)
 			buf = (struct wpabuf *) nbuf;
 			os_memset(nbuf + sizeof(struct wpabuf) + buf->used, 0,
 				  add_len);
+#endif /* WPA_TRACE */
 			*_buf = buf;
 		}
 		buf->size = buf->used + add_len;
@@ -65,9 +117,20 @@ int wpabuf_resize(struct wpabuf **_buf, size_t add_len)
  */
 struct wpabuf * wpabuf_alloc(size_t len)
 {
+#ifdef WPA_TRACE
+	struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) +
+					       sizeof(struct wpabuf) + len);
+	struct wpabuf *buf;
+	if (trace == NULL)
+		return NULL;
+	trace->magic = WPABUF_MAGIC;
+	buf = (struct wpabuf *) (trace + 1);
+#else /* WPA_TRACE */
 	struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len);
 	if (buf == NULL)
 		return NULL;
+#endif /* WPA_TRACE */
+
 	buf->size = len;
 	return buf;
 }
@@ -75,9 +138,19 @@ struct wpabuf * wpabuf_alloc(size_t len)
 
 struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len)
 {
+#ifdef WPA_TRACE
+	struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) +
+					       sizeof(struct wpabuf));
+	struct wpabuf *buf;
+	if (trace == NULL)
+		return NULL;
+	trace->magic = WPABUF_MAGIC;
+	buf = (struct wpabuf *) (trace + 1);
+#else /* WPA_TRACE */
 	struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf));
 	if (buf == NULL)
 		return NULL;
+#endif /* WPA_TRACE */
 
 	buf->size = len;
 	buf->used = len;
@@ -111,10 +184,25 @@ struct wpabuf * wpabuf_dup(const struct wpabuf *src)
  */
 void wpabuf_free(struct wpabuf *buf)
 {
+#ifdef WPA_TRACE
+	struct wpabuf_trace *trace;
+	if (buf == NULL)
+		return;
+	trace = wpabuf_get_trace(buf);
+	if (trace->magic != WPABUF_MAGIC) {
+		wpa_printf(MSG_ERROR, "wpabuf_free: invalid magic %x",
+			   trace->magic);
+		wpa_trace_show("wpabuf_free magic mismatch");
+		abort();
+	}
+	os_free(buf->ext_data);
+	os_free(trace);
+#else /* WPA_TRACE */
 	if (buf == NULL)
 		return;
 	os_free(buf->ext_data);
 	os_free(buf);
+#endif /* WPA_TRACE */
 }
 
 
diff --git a/contrib/wpa/src/utils/wpabuf.h b/contrib/wpa/src/utils/wpabuf.h
index bd8f09e94f84..a150455a5a65 100644
--- a/contrib/wpa/src/utils/wpabuf.h
+++ b/contrib/wpa/src/utils/wpabuf.h
@@ -111,6 +111,12 @@ static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data)
 	*pos = data;
 }
 
+static inline void wpabuf_put_le16(struct wpabuf *buf, u16 data)
+{
+	u8 *pos = wpabuf_put(buf, 2);
+	WPA_PUT_LE16(pos, data);
+}
+
 static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data)
 {
 	u8 *pos = wpabuf_put(buf, 2);
diff --git a/contrib/wpa/src/wps/Makefile b/contrib/wpa/src/wps/Makefile
index cffba620da04..9c41962fd7e1 100644
--- a/contrib/wpa/src/wps/Makefile
+++ b/contrib/wpa/src/wps/Makefile
@@ -2,7 +2,6 @@ all:
 	@echo Nothing to be made.
 
 clean:
-	for d in $(SUBDIRS); do make -C $$d clean; done
 	rm -f *~ *.o *.d
 
 install:
diff --git a/contrib/wpa/src/wps/http.h b/contrib/wpa/src/wps/http.h
new file mode 100644
index 000000000000..2fee3a8f87a6
--- /dev/null
+++ b/contrib/wpa/src/wps/http.h
@@ -0,0 +1,29 @@
+/*
+ * HTTP for WPS
+ * Copyright (c) 2000-2003 Intel Corporation
+ * Copyright (c) 2006-2007 Sony Corporation
+ * Copyright (c) 2008-2009 Atheros Communications
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * See wps_upnp.c for more details on licensing and code history.
+ */
+
+#ifndef HTTP_H
+#define HTTP_H
+
+enum http_reply_code {
+	HTTP_OK = 200,
+	HTTP_BAD_REQUEST = 400,
+	UPNP_INVALID_ACTION = 401,
+	UPNP_INVALID_ARGS = 402,
+	HTTP_NOT_FOUND = 404,
+	HTTP_PRECONDITION_FAILED = 412,
+	HTTP_INTERNAL_SERVER_ERROR = 500,
+	HTTP_UNIMPLEMENTED = 501,
+	UPNP_ACTION_FAILED = 501,
+	UPNP_ARG_VALUE_INVALID = 600,
+	UPNP_ARG_VALUE_OUT_OF_RANGE = 601,
+	UPNP_OUT_OF_MEMORY = 603
+};
+
+#endif /* HTTP_H */
diff --git a/contrib/wpa/src/wps/http_client.c b/contrib/wpa/src/wps/http_client.c
new file mode 100644
index 000000000000..fea2a04ea973
--- /dev/null
+++ b/contrib/wpa/src/wps/http_client.c
@@ -0,0 +1,371 @@
+/*
+ * http_client - HTTP client
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 
+
+#include "common.h"
+#include "eloop.h"
+#include "httpread.h"
+#include "http_client.h"
+
+
+#define HTTP_CLIENT_TIMEOUT 30
+
+
+struct http_client {
+	struct sockaddr_in dst;
+	int sd;
+	struct wpabuf *req;
+	size_t req_pos;
+	size_t max_response;
+
+	void (*cb)(void *ctx, struct http_client *c,
+		   enum http_client_event event);
+	void *cb_ctx;
+	struct httpread *hread;
+	struct wpabuf body;
+};
+
+
+static void http_client_timeout(void *eloop_data, void *user_ctx)
+{
+	struct http_client *c = eloop_data;
+	wpa_printf(MSG_DEBUG, "HTTP: Timeout");
+	c->cb(c->cb_ctx, c, HTTP_CLIENT_TIMEOUT);
+}
+
+
+static void http_client_got_response(struct httpread *handle, void *cookie,
+				     enum httpread_event e)
+{
+	struct http_client *c = cookie;
+
+	eloop_cancel_timeout(http_client_timeout, c, NULL);
+	switch (e) {
+	case HTTPREAD_EVENT_FILE_READY:
+		if (httpread_hdr_type_get(c->hread) == HTTPREAD_HDR_TYPE_REPLY)
+		{
+			int reply_code = httpread_reply_code_get(c->hread);
+			if (reply_code == 200 /* OK */) {
+				wpa_printf(MSG_DEBUG, "HTTP: Response OK from "
+					   "%s:%d",
+					   inet_ntoa(c->dst.sin_addr),
+					   ntohs(c->dst.sin_port));
+				c->cb(c->cb_ctx, c, HTTP_CLIENT_OK);
+			} else {
+				wpa_printf(MSG_DEBUG, "HTTP: Error %d from "
+					   "%s:%d", reply_code,
+					   inet_ntoa(c->dst.sin_addr),
+					   ntohs(c->dst.sin_port));
+				c->cb(c->cb_ctx, c, HTTP_CLIENT_INVALID_REPLY);
+			}
+		} else
+			c->cb(c->cb_ctx, c, HTTP_CLIENT_INVALID_REPLY);
+		break;
+	case HTTPREAD_EVENT_TIMEOUT:
+		c->cb(c->cb_ctx, c, HTTP_CLIENT_TIMEOUT);
+		break;
+	case HTTPREAD_EVENT_ERROR:
+		c->cb(c->cb_ctx, c, HTTP_CLIENT_FAILED);
+		break;
+	}
+}
+
+
+static void http_client_tx_ready(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	struct http_client *c = eloop_ctx;
+	int res;
+
+	wpa_printf(MSG_DEBUG, "HTTP: Send client request to %s:%d (%lu of %lu "
+		   "bytes remaining)",
+		   inet_ntoa(c->dst.sin_addr), ntohs(c->dst.sin_port),
+		   (unsigned long) wpabuf_len(c->req),
+		   (unsigned long) wpabuf_len(c->req) - c->req_pos);
+
+	res = send(c->sd, wpabuf_head(c->req) + c->req_pos,
+		   wpabuf_len(c->req) - c->req_pos, 0);
+	if (res < 0) {
+		wpa_printf(MSG_DEBUG, "HTTP: Failed to send buffer: %s",
+			   strerror(errno));
+		eloop_unregister_sock(c->sd, EVENT_TYPE_WRITE);
+		c->cb(c->cb_ctx, c, HTTP_CLIENT_FAILED);
+		return;
+	}
+
+	if ((size_t) res < wpabuf_len(c->req) - c->req_pos) {
+		wpa_printf(MSG_DEBUG, "HTTP: Sent %d of %lu bytes; %lu bytes "
+			   "remaining",
+			   res, (unsigned long) wpabuf_len(c->req),
+			   (unsigned long) wpabuf_len(c->req) - c->req_pos -
+			   res);
+		c->req_pos += res;
+		return;
+	}
+
+	wpa_printf(MSG_DEBUG, "HTTP: Full client request sent to %s:%d",
+		   inet_ntoa(c->dst.sin_addr), ntohs(c->dst.sin_port));
+	eloop_unregister_sock(c->sd, EVENT_TYPE_WRITE);
+	wpabuf_free(c->req);
+	c->req = NULL;
+
+	c->hread = httpread_create(c->sd, http_client_got_response, c,
+				   c->max_response, HTTP_CLIENT_TIMEOUT);
+	if (c->hread == NULL) {
+		c->cb(c->cb_ctx, c, HTTP_CLIENT_FAILED);
+		return;
+	}
+}
+
+
+struct http_client * http_client_addr(struct sockaddr_in *dst,
+				      struct wpabuf *req, size_t max_response,
+				      void (*cb)(void *ctx,
+						 struct http_client *c,
+						 enum http_client_event event),
+				      void *cb_ctx)
+{
+	struct http_client *c;
+
+	c = os_zalloc(sizeof(*c));
+	if (c == NULL)
+		return NULL;
+	c->sd = -1;
+	c->dst = *dst;
+	c->max_response = max_response;
+	c->cb = cb;
+	c->cb_ctx = cb_ctx;
+
+	c->sd = socket(AF_INET, SOCK_STREAM, 0);
+	if (c->sd < 0) {
+		http_client_free(c);
+		return NULL;
+	}
+
+	if (fcntl(c->sd, F_SETFL, O_NONBLOCK) != 0) {
+		wpa_printf(MSG_DEBUG, "HTTP: fnctl(O_NONBLOCK) failed: %s",
+			   strerror(errno));
+		http_client_free(c);
+		return NULL;
+	}
+
+	if (connect(c->sd, (struct sockaddr *) dst, sizeof(*dst))) {
+		if (errno != EINPROGRESS) {
+			wpa_printf(MSG_DEBUG, "HTTP: Failed to connect: %s",
+				   strerror(errno));
+			http_client_free(c);
+			return NULL;
+		}
+
+		/*
+		 * Continue connecting in the background; eloop will call us
+		 * once the connection is ready (or failed).
+		 */
+	}
+
+	if (eloop_register_sock(c->sd, EVENT_TYPE_WRITE, http_client_tx_ready,
+				c, NULL)) {
+		http_client_free(c);
+		return NULL;
+	}
+
+	if (eloop_register_timeout(HTTP_CLIENT_TIMEOUT, 0, http_client_timeout,
+				   c, NULL)) {
+		http_client_free(c);
+		return NULL;
+	}
+
+	c->req = req;
+
+	return c;
+}
+
+
+char * http_client_url_parse(const char *url, struct sockaddr_in *dst,
+			     char **ret_path)
+{
+	char *u, *addr, *port, *path;
+
+	u = os_strdup(url);
+	if (u == NULL)
+		return NULL;
+
+	os_memset(dst, 0, sizeof(*dst));
+	dst->sin_family = AF_INET;
+	addr = u + 7;
+	path = os_strchr(addr, '/');
+	port = os_strchr(addr, ':');
+	if (path == NULL) {
+		path = "/";
+	} else {
+		*path = '\0'; /* temporary nul termination for address */
+		if (port > path)
+			port = NULL;
+	}
+	if (port)
+		*port++ = '\0';
+
+	if (inet_aton(addr, &dst->sin_addr) == 0) {
+		/* TODO: name lookup */
+		wpa_printf(MSG_DEBUG, "HTTP: Unsupported address in URL '%s' "
+			   "(addr='%s' port='%s')",
+			   url, addr, port);
+		os_free(u);
+		return NULL;
+	}
+
+	if (port)
+		dst->sin_port = htons(atoi(port));
+	else
+		dst->sin_port = htons(80);
+
+	if (*path == '\0') {
+		/* remove temporary nul termination for address */
+		*path = '/';
+	}
+
+	*ret_path = path;
+
+	return u;
+}
+
+
+struct http_client * http_client_url(const char *url,
+				     struct wpabuf *req, size_t max_response,
+				     void (*cb)(void *ctx,
+						struct http_client *c,
+						enum http_client_event event),
+				     void *cb_ctx)
+{
+	struct sockaddr_in dst;
+	struct http_client *c;
+	char *u, *path;
+	struct wpabuf *req_buf = NULL;
+
+	if (os_strncmp(url, "http://", 7) != 0)
+		return NULL;
+	u = http_client_url_parse(url, &dst, &path);
+	if (u == NULL)
+		return NULL;
+
+	if (req == NULL) {
+		req_buf = wpabuf_alloc(os_strlen(url) + 1000);
+		if (req_buf == NULL) {
+			os_free(u);
+			return NULL;
+		}
+		req = req_buf;
+		wpabuf_printf(req,
+			      "GET %s HTTP/1.1\r\n"
+			      "Cache-Control: no-cache\r\n"
+			      "Pragma: no-cache\r\n"
+			      "Accept: text/xml, application/xml\r\n"
+			      "User-Agent: wpa_supplicant\r\n"
+			      "Host: %s:%d\r\n"
+			      "\r\n",
+			      path, inet_ntoa(dst.sin_addr),
+			      ntohs(dst.sin_port));
+	}
+	os_free(u);
+
+	c = http_client_addr(&dst, req, max_response, cb, cb_ctx);
+	if (c == NULL) {
+		wpabuf_free(req_buf);
+		return NULL;
+	}
+
+	return c;
+}
+
+
+void http_client_free(struct http_client *c)
+{
+	if (c == NULL)
+		return;
+	httpread_destroy(c->hread);
+	wpabuf_free(c->req);
+	if (c->sd >= 0) {
+		eloop_unregister_sock(c->sd, EVENT_TYPE_WRITE);
+		close(c->sd);
+	}
+	eloop_cancel_timeout(http_client_timeout, c, NULL);
+	os_free(c);
+}
+
+
+struct wpabuf * http_client_get_body(struct http_client *c)
+{
+	if (c->hread == NULL)
+		return NULL;
+	wpabuf_set(&c->body, httpread_data_get(c->hread),
+		   httpread_length_get(c->hread));
+	return &c->body;
+}
+
+
+char * http_client_get_hdr_line(struct http_client *c, const char *tag)
+{
+	if (c->hread == NULL)
+		return NULL;
+	return httpread_hdr_line_get(c->hread, tag);
+}
+
+
+char * http_link_update(char *url, const char *base)
+{
+	char *n;
+	size_t len;
+	const char *pos;
+
+	/* RFC 2396, Chapter 5.2 */
+	/* TODO: consider adding all cases described in RFC 2396 */
+
+	if (url == NULL)
+		return NULL;
+
+	if (os_strncmp(url, "http://", 7) == 0)
+		return url; /* absolute link */
+
+	if (os_strncmp(base, "http://", 7) != 0)
+		return url; /* unable to handle base URL */
+
+	len = os_strlen(url) + 1 + os_strlen(base) + 1;
+	n = os_malloc(len);
+	if (n == NULL)
+		return url; /* failed */
+
+	if (url[0] == '/') {
+		pos = os_strchr(base + 7, '/');
+		if (pos == NULL) {
+			os_snprintf(n, len, "%s%s", base, url);
+		} else {
+			os_memcpy(n, base, pos - base);
+			os_memcpy(n + (pos - base), url, os_strlen(url) + 1);
+		}
+	} else {
+		pos = os_strrchr(base + 7, '/');
+		if (pos == NULL) {
+			os_snprintf(n, len, "%s/%s", base, url);
+		} else {
+			os_memcpy(n, base, pos - base + 1);
+			os_memcpy(n + (pos - base) + 1, url, os_strlen(url) +
+				  1);
+		}
+	}
+
+	os_free(url);
+
+	return n;
+}
diff --git a/contrib/wpa/src/wps/http_client.h b/contrib/wpa/src/wps/http_client.h
new file mode 100644
index 000000000000..924d6ab4a2a4
--- /dev/null
+++ b/contrib/wpa/src/wps/http_client.h
@@ -0,0 +1,46 @@
+/*
+ * http_client - HTTP client
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 HTTP_CLIENT_H
+#define HTTP_CLIENT_H
+
+struct http_client;
+
+enum http_client_event {
+	HTTP_CLIENT_FAILED,
+	HTTP_CLIENT_TIMEOUT,
+	HTTP_CLIENT_OK,
+	HTTP_CLIENT_INVALID_REPLY,
+};
+
+char * http_client_url_parse(const char *url, struct sockaddr_in *dst,
+			     char **path);
+struct http_client * http_client_addr(struct sockaddr_in *dst,
+				      struct wpabuf *req, size_t max_response,
+				      void (*cb)(void *ctx,
+						 struct http_client *c,
+						 enum http_client_event event),
+				      void *cb_ctx);
+struct http_client * http_client_url(const char *url,
+				     struct wpabuf *req, size_t max_response,
+				     void (*cb)(void *ctx,
+						struct http_client *c,
+						enum http_client_event event),
+				     void *cb_ctx);
+void http_client_free(struct http_client *c);
+struct wpabuf * http_client_get_body(struct http_client *c);
+char * http_client_get_hdr_line(struct http_client *c, const char *tag);
+char * http_link_update(char *url, const char *base);
+
+#endif /* HTTP_CLIENT_H */
diff --git a/contrib/wpa/src/wps/http_server.c b/contrib/wpa/src/wps/http_server.c
new file mode 100644
index 000000000000..356f599abe05
--- /dev/null
+++ b/contrib/wpa/src/wps/http_server.c
@@ -0,0 +1,312 @@
+/*
+ * http_server - HTTP server
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 
+
+#include "common.h"
+#include "eloop.h"
+#include "httpread.h"
+#include "http_server.h"
+
+#define HTTP_SERVER_TIMEOUT 30
+#define HTTP_SERVER_MAX_REQ_LEN 8000
+#define HTTP_SERVER_MAX_CONNECTIONS 10
+
+struct http_request {
+	struct http_request *next;
+	struct http_server *srv;
+	int fd;
+	struct sockaddr_in cli;
+	struct httpread *hread;
+};
+
+struct http_server {
+	void (*cb)(void *ctx, struct http_request *req);
+	void *cb_ctx;
+
+	int fd;
+	int port;
+
+	struct http_request *requests;
+	unsigned int request_count;
+};
+
+
+static void http_request_cb(struct httpread *handle, void *cookie,
+			    enum httpread_event en)
+{
+	struct http_request *req = cookie;
+	struct http_server *srv = req->srv;
+
+	if (en == HTTPREAD_EVENT_FILE_READY) {
+		wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d received",
+			   inet_ntoa(req->cli.sin_addr),
+			   ntohs(req->cli.sin_port));
+		srv->cb(srv->cb_ctx, req);
+		return;
+	}
+	wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d could not be received "
+		   "completely", inet_ntoa(req->cli.sin_addr),
+		   ntohs(req->cli.sin_port));
+	http_request_deinit(req);
+}
+
+
+static struct http_request * http_request_init(struct http_server *srv, int fd,
+					       struct sockaddr_in *cli)
+{
+	struct http_request *req;
+
+	if (srv->request_count >= HTTP_SERVER_MAX_CONNECTIONS) {
+		wpa_printf(MSG_DEBUG, "HTTP: Too many concurrent requests");
+		return NULL;
+	}
+
+	req = os_zalloc(sizeof(*req));
+	if (req == NULL)
+		return NULL;
+
+	req->srv = srv;
+	req->fd = fd;
+	req->cli = *cli;
+
+	req->hread = httpread_create(req->fd, http_request_cb, req,
+				     HTTP_SERVER_MAX_REQ_LEN,
+				     HTTP_SERVER_TIMEOUT);
+	if (req->hread == NULL) {
+		http_request_deinit(req);
+		return NULL;
+	}
+
+	return req;
+}
+
+
+void http_request_deinit(struct http_request *req)
+{
+	struct http_request *r, *p;
+	struct http_server *srv;
+
+	if (req == NULL)
+		return;
+
+	srv = req->srv;
+	p = NULL;
+	r = srv->requests;
+	while (r) {
+		if (r == req) {
+			if (p)
+				p->next = r->next;
+			else
+				srv->requests = r->next;
+			srv->request_count--;
+			break;
+		}
+		p = r;
+		r = r->next;
+	}
+
+	httpread_destroy(req->hread);
+	close(req->fd);
+	os_free(req);
+}
+
+
+static void http_request_free_all(struct http_request *req)
+{
+	struct http_request *prev;
+	while (req) {
+		prev = req;
+		req = req->next;
+		http_request_deinit(prev);
+	}
+}
+
+
+void http_request_send(struct http_request *req, struct wpabuf *resp)
+{
+	int res;
+
+	wpa_printf(MSG_DEBUG, "HTTP: Send %lu byte response to %s:%d",
+		   (unsigned long) wpabuf_len(resp),
+		   inet_ntoa(req->cli.sin_addr),
+		   ntohs(req->cli.sin_port));
+
+	res = send(req->fd, wpabuf_head(resp), wpabuf_len(resp), 0);
+	if (res < 0) {
+		wpa_printf(MSG_DEBUG, "HTTP: Send failed: %s",
+			   strerror(errno));
+	} else if ((size_t) res < wpabuf_len(resp)) {
+		wpa_printf(MSG_DEBUG, "HTTP: Sent only %d of %lu bytes",
+			   res, (unsigned long) wpabuf_len(resp));
+		/* TODO: add eloop handler for sending rest of the data */
+	}
+
+	wpabuf_free(resp);
+}
+
+
+void http_request_send_and_deinit(struct http_request *req,
+				  struct wpabuf *resp)
+{
+	http_request_send(req, resp);
+	http_request_deinit(req);
+}
+
+
+enum httpread_hdr_type http_request_get_type(struct http_request *req)
+{
+	return httpread_hdr_type_get(req->hread);
+}
+
+
+char * http_request_get_uri(struct http_request *req)
+{
+	return httpread_uri_get(req->hread);
+}
+
+
+char * http_request_get_hdr(struct http_request *req)
+{
+	return httpread_hdr_get(req->hread);
+}
+
+
+char * http_request_get_data(struct http_request *req)
+{
+	return httpread_data_get(req->hread);
+}
+
+
+char * http_request_get_hdr_line(struct http_request *req, const char *tag)
+{
+	return httpread_hdr_line_get(req->hread, tag);
+}
+
+
+struct sockaddr_in * http_request_get_cli_addr(struct http_request *req)
+{
+	return &req->cli;
+}
+
+
+static void http_server_cb(int sd, void *eloop_ctx, void *sock_ctx)
+{
+	struct sockaddr_in addr;
+	socklen_t addr_len = sizeof(addr);
+	struct http_server *srv = eloop_ctx;
+	int conn;
+	struct http_request *req;
+
+	conn = accept(srv->fd, (struct sockaddr *) &addr, &addr_len);
+	if (conn < 0) {
+		wpa_printf(MSG_DEBUG, "HTTP: Failed to accept new connection: "
+			   "%s", strerror(errno));
+		return;
+	}
+	wpa_printf(MSG_DEBUG, "HTTP: Connection from %s:%d",
+		   inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+
+	req = http_request_init(srv, conn, &addr);
+	if (req == NULL) {
+		close(conn);
+		return;
+	}
+
+	req->next = srv->requests;
+	srv->requests = req;
+	srv->request_count++;
+}
+
+
+struct http_server * http_server_init(struct in_addr *addr, int port,
+				      void (*cb)(void *ctx,
+						 struct http_request *req),
+				      void *cb_ctx)
+{
+	struct sockaddr_in sin;
+	struct http_server *srv;
+
+	srv = os_zalloc(sizeof(*srv));
+	if (srv == NULL)
+		return NULL;
+	srv->cb = cb;
+	srv->cb_ctx = cb_ctx;
+
+	srv->fd = socket(AF_INET, SOCK_STREAM, 0);
+	if (srv->fd < 0)
+		goto fail;
+	if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0)
+		goto fail;
+	if (port < 0)
+		srv->port = 49152;
+	else
+		srv->port = port;
+
+	os_memset(&sin, 0, sizeof(sin));
+	sin.sin_family = AF_INET;
+	sin.sin_addr.s_addr = addr->s_addr;
+
+	for (;;) {
+		sin.sin_port = htons(srv->port);
+		if (bind(srv->fd, (struct sockaddr *) &sin, sizeof(sin)) == 0)
+			break;
+		if (errno == EADDRINUSE) {
+			/* search for unused port */
+			if (++srv->port == 65535 || port >= 0)
+				goto fail;
+			continue;
+		}
+		wpa_printf(MSG_DEBUG, "HTTP: Failed to bind server port %d: "
+			   "%s", srv->port, strerror(errno));
+		goto fail;
+	}
+	if (listen(srv->fd, 10 /* max backlog */) < 0)
+		goto fail;
+	if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0)
+		goto fail;
+	if (eloop_register_sock(srv->fd, EVENT_TYPE_READ, http_server_cb,
+				srv, NULL))
+		goto fail;
+
+	wpa_printf(MSG_DEBUG, "HTTP: Started server on %s:%d",
+		   inet_ntoa(*addr), srv->port);
+
+	return srv;
+
+fail:
+	http_server_deinit(srv);
+	return NULL;
+}
+
+
+void http_server_deinit(struct http_server *srv)
+{
+	if (srv == NULL)
+		return;
+	if (srv->fd >= 0) {
+		eloop_unregister_sock(srv->fd, EVENT_TYPE_READ);
+		close(srv->fd);
+	}
+	http_request_free_all(srv->requests);
+
+	os_free(srv);
+}
+
+
+int http_server_get_port(struct http_server *srv)
+{
+	return srv->port;
+}
diff --git a/contrib/wpa/src/wps/http_server.h b/contrib/wpa/src/wps/http_server.h
new file mode 100644
index 000000000000..219941c5ab5a
--- /dev/null
+++ b/contrib/wpa/src/wps/http_server.h
@@ -0,0 +1,39 @@
+/*
+ * http_server - HTTP server
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * 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 HTTP_SERVER_H
+#define HTTP_SERVER_H
+
+struct http_server;
+struct http_request;
+
+void http_request_deinit(struct http_request *req);
+void http_request_send(struct http_request *req, struct wpabuf *resp);
+void http_request_send_and_deinit(struct http_request *req,
+				  struct wpabuf *resp);
+enum httpread_hdr_type http_request_get_type(struct http_request *req);
+char * http_request_get_uri(struct http_request *req);
+char * http_request_get_hdr(struct http_request *req);
+char * http_request_get_data(struct http_request *req);
+char * http_request_get_hdr_line(struct http_request *req, const char *tag);
+struct sockaddr_in * http_request_get_cli_addr(struct http_request *req);
+
+struct http_server * http_server_init(struct in_addr *addr, int port,
+				      void (*cb)(void *ctx,
+						 struct http_request *req),
+				      void *cb_ctx);
+void http_server_deinit(struct http_server *srv);
+int http_server_get_port(struct http_server *srv);
+
+#endif /* HTTP_SERVER_H */
diff --git a/contrib/wpa/src/wps/httpread.c b/contrib/wpa/src/wps/httpread.c
index 0d7165e9c227..40422e4651d3 100644
--- a/contrib/wpa/src/wps/httpread.c
+++ b/contrib/wpa/src/wps/httpread.c
@@ -1,4 +1,4 @@
-/**
+/*
  * httpread - Manage reading file(s) from HTTP/TCP socket
  * Author: Ted Merrill
  * Copyright 2008 Atheros Communications
diff --git a/contrib/wpa/src/wps/httpread.h b/contrib/wpa/src/wps/httpread.h
index fb1ecb7de36c..51aa21494665 100644
--- a/contrib/wpa/src/wps/httpread.h
+++ b/contrib/wpa/src/wps/httpread.h
@@ -1,4 +1,4 @@
-/**
+/*
  * httpread - Manage reading file(s) from HTTP/TCP socket
  * Author: Ted Merrill
  * Copyright 2008 Atheros Communications
diff --git a/contrib/wpa/src/wps/ndef.c b/contrib/wpa/src/wps/ndef.c
new file mode 100644
index 000000000000..9baec7f4b27c
--- /dev/null
+++ b/contrib/wpa/src/wps/ndef.c
@@ -0,0 +1,175 @@
+/*
+ * NDEF(NFC Data Exchange Format) routines for Wi-Fi Protected Setup
+ *   Reference is "NFCForum-TS-NDEF_1.0 2006-07-24".
+ * Copyright (c) 2009, Masashi Honma 
+ *
+ * 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 "wps/wps.h"
+#include "wps/wps_i.h"
+
+#define FLAG_MESSAGE_BEGIN (1 << 7)
+#define FLAG_MESSAGE_END (1 << 6)
+#define FLAG_CHUNK (1 << 5)
+#define FLAG_SHORT_RECORD (1 << 4)
+#define FLAG_ID_LENGTH_PRESENT (1 << 3)
+#define FLAG_TNF_RFC2046 (0x02)
+
+struct ndef_record {
+	u8 *type;
+	u8 *id;
+	u8 *payload;
+	u8 type_length;
+	u8 id_length;
+	u32 payload_length;
+	u32 total_length;
+};
+
+static char wifi_handover_type[] = "application/vnd.wfa.wsc";
+
+static int ndef_parse_record(u8 *data, u32 size, struct ndef_record *record)
+{
+	u8 *pos = data + 1;
+
+	if (size < 2)
+		return -1;
+	record->type_length = *pos++;
+	if (data[0] & FLAG_SHORT_RECORD) {
+		if (size < 3)
+			return -1;
+		record->payload_length = *pos++;
+	} else {
+		if (size < 6)
+			return -1;
+		record->payload_length = ntohl(*(u32 *)pos);
+		pos += sizeof(u32);
+	}
+
+	if (data[0] & FLAG_ID_LENGTH_PRESENT) {
+		if ((int) size < pos - data + 1)
+			return -1;
+		record->id_length = *pos++;
+	} else
+		record->id_length = 0;
+
+	record->type = record->type_length == 0 ? NULL : pos;
+	pos += record->type_length;
+
+	record->id = record->id_length == 0 ? NULL : pos;
+	pos += record->id_length;
+
+	record->payload = record->payload_length == 0 ? NULL : pos;
+	pos += record->payload_length;
+
+	record->total_length = pos - data;
+	if (record->total_length > size)
+		return -1;
+	return 0;
+}
+
+
+static struct wpabuf * ndef_parse_records(struct wpabuf *buf,
+					  int (*filter)(struct ndef_record *))
+{
+	struct ndef_record record;
+	int len = wpabuf_len(buf);
+	u8 *data = wpabuf_mhead(buf);
+
+	while (len > 0) {
+		if (ndef_parse_record(data, len, &record) < 0) {
+			wpa_printf(MSG_ERROR, "NDEF : Failed to parse");
+			return NULL;
+		}
+		if (filter == NULL || filter(&record))
+			return wpabuf_alloc_copy(record.payload,
+						 record.payload_length);
+		data += record.total_length;
+		len -= record.total_length;
+	}
+	wpa_printf(MSG_ERROR, "NDEF : Record not found");
+	return NULL;
+}
+
+
+static struct wpabuf * ndef_build_record(u8 flags, void *type,
+					 u8 type_length, void *id,
+					 u8 id_length, void *payload,
+					 u32 payload_length)
+{
+	struct wpabuf *record;
+	size_t total_len;
+	int short_record;
+	u8 local_flag;
+
+	short_record = payload_length < 256 ? 1 : 0;
+
+	total_len = 2; /* flag + type length */
+	/* payload length */
+	total_len += short_record ? sizeof(u8) : sizeof(u32);
+	if (id_length > 0)
+		total_len += 1;
+	total_len += type_length + id_length + payload_length;
+	record = wpabuf_alloc(total_len);
+	if (record == NULL) {
+		wpa_printf(MSG_ERROR, "NDEF : Failed to allocate "
+			   "record for build");
+		return NULL;
+	}
+
+	local_flag = flags;
+	if (id_length > 0)
+		local_flag |= FLAG_ID_LENGTH_PRESENT;
+	if (short_record)
+		local_flag |= FLAG_SHORT_RECORD;
+	wpabuf_put_u8(record, local_flag);
+
+	wpabuf_put_u8(record, type_length);
+
+	if (short_record)
+		wpabuf_put_u8(record, payload_length);
+	else
+		wpabuf_put_be32(record, payload_length);
+
+	if (id_length > 0)
+		wpabuf_put_u8(record, id_length);
+	wpabuf_put_data(record, type, type_length);
+	wpabuf_put_data(record, id, id_length);
+	wpabuf_put_data(record, payload, payload_length);
+	return record;
+}
+
+
+static int wifi_filter(struct ndef_record *record)
+{
+	if (record->type_length != os_strlen(wifi_handover_type))
+		return 0;
+	if (os_memcmp(record->type, wifi_handover_type,
+		      os_strlen(wifi_handover_type)) != 0)
+		return 0;
+	return 1;
+}
+
+
+struct wpabuf * ndef_parse_wifi(struct wpabuf *buf)
+{
+	return ndef_parse_records(buf, wifi_filter);
+}
+
+
+struct wpabuf * ndef_build_wifi(struct wpabuf *buf)
+{
+	return ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_MESSAGE_END |
+				 FLAG_TNF_RFC2046, wifi_handover_type,
+				 os_strlen(wifi_handover_type), NULL, 0,
+				 wpabuf_mhead(buf), wpabuf_len(buf));
+}
diff --git a/contrib/wpa/src/wps/upnp_xml.c b/contrib/wpa/src/wps/upnp_xml.c
new file mode 100644
index 000000000000..b1b1e2b165dd
--- /dev/null
+++ b/contrib/wpa/src/wps/upnp_xml.c
@@ -0,0 +1,252 @@
+/*
+ * UPnP XML helper routines
+ * Copyright (c) 2000-2003 Intel Corporation
+ * Copyright (c) 2006-2007 Sony Corporation
+ * Copyright (c) 2008-2009 Atheros Communications
+ * Copyright (c) 2009, Jouni Malinen 
+ *
+ * See wps_upnp.c for more details on licensing and code history.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "base64.h"
+#include "http.h"
+#include "upnp_xml.h"
+
+
+/*
+ * XML parsing and formatting
+ *
+ * XML is a markup language based on unicode; usually (and in our case,
+ * always!) based on utf-8. utf-8 uses a variable number of bytes per
+ * character. utf-8 has the advantage that all non-ASCII unicode characters are
+ * represented by sequences of non-ascii (high bit set) bytes, whereas ASCII
+ * characters are single ascii bytes, thus we can use typical text processing.
+ *
+ * (One other interesting thing about utf-8 is that it is possible to look at
+ * any random byte and determine if it is the first byte of a character as
+ * versus a continuation byte).
+ *
+ * The base syntax of XML uses a few ASCII punctionation characters; any
+ * characters that would appear in the payload data are rewritten using
+ * sequences, e.g., & for ampersand(&) and < for left angle bracket (<).
+ * Five such escapes total (more can be defined but that does not apply to our
+ * case). Thus we can safely parse for angle brackets etc.
+ *
+ * XML describes tree structures of tagged data, with each element beginning
+ * with an opening tag  with
+ * matching label. (There is also a self-closing tag