diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 7e23ef4..79f739c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -35,6 +35,7 @@
 #include "radiotap_iter.h"
 #include "rfkill.h"
 #include "driver_nl80211.h"
+#include "linux_wext.h"
 
 
 #ifndef NETLINK_CAP_ACK
@@ -1175,6 +1176,409 @@ static void nl80211_refresh_mac(struct wpa_driver_nl80211_data *drv,
 	}
 }
 
+#define OID_802_11_WNM_PROXY_ARP	0x093b
+#define ETH_P_ARP			0x0806
+
+struct proxy_arp_entry {
+	u32 ifindex;
+	u8 ip_type;
+	u8 from_ds;
+	u8 IsDAD;
+	char source_mac_addr[6];
+	char target_mac_addr[6];
+	char ip_addr[0];
+};
+
+struct _ipv6_addr {
+	union {
+		u8 ipv6Addr8[16];
+		u16 ipv6Addr16[8];
+		u32 ipv6Addr32[4];
+	}addr;
+#define ipv6_addr addr.ipv6Addr8
+#define ipv6_addr16 addr.ipv6Addr16
+#define ipv6_addr32 addr.ipv6Addr32
+};
+
+
+enum {
+	IPV4,
+	IPV6,
+};
+
+#define cpu2be16 host_to_be16
+
+static u16 icmpv6_csum(const char *saddr,
+		const char *daddr,
+		u16 len,
+		u8 proto,
+		const char *icmp_msg)
+{
+	struct _ipv6_addr *sa_ipv6_addr = (struct _ipv6_addr *)saddr;
+	struct _ipv6_addr *da_ipv6_addr = (struct _ipv6_addr *)daddr;
+	u32 carry, ulen, uproto;
+	u32 i;
+	u32 csum = 0x00;
+	u16 chksum;
+
+	if (len % 4)
+		return 0;
+
+	for(i = 0; i < 4; i++) {
+		csum += sa_ipv6_addr->ipv6_addr32[i];
+		carry = (csum < sa_ipv6_addr->ipv6_addr32[i]);
+		csum += carry;
+	}
+
+	for(i = 0; i < 4; i++) {
+		csum += da_ipv6_addr->ipv6_addr32[i];
+		carry = (csum < da_ipv6_addr->ipv6_addr32[i]);
+		csum += carry;
+	}
+
+	ulen = htonl((u32)len);
+	csum += ulen;
+	carry = (csum < ulen);
+	csum += carry;
+
+	uproto = htonl((u32)proto);
+	csum += uproto;
+	carry = (csum < uproto);
+	csum += carry;
+
+	for (i = 0; i < len; i += 4) {
+		csum += *((u32 *)(&icmp_msg[i]));
+		carry = (csum < (*((u32 *)(&icmp_msg[i]))));
+		csum += carry;
+	}
+
+	while (csum>>16)
+		csum = (csum & 0xffff) + (csum >> 16);
+
+	chksum = ~csum;
+
+	return chksum;
+}
+
+static void hotspot_proxy_arp_ipv6(char *buf,
+		const char *source_mac_addr,
+		const char *source_ip_addr,
+		const char *target_mac_addr,
+		const char *target_ip_addr,
+		unsigned char IsDAD)
+{
+
+	char *pos, *pcsum, *icmpv6hdr;
+	char DadDestAddr[16]={0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
+	u16 protocol_type = cpu2be16(0x86dd);
+	u16 payload_len = cpu2be16(0x0020);
+	u16     checksum = 0;
+	u32 icmpmsglen = 0x20;
+
+	pos = buf;
+
+	/* DA */
+	os_memcpy(pos, source_mac_addr, 6);
+	pos += 6;
+
+	/* SA */
+	os_memcpy(pos, target_mac_addr, 6);
+	pos += 6;
+
+	/* Protocol type */
+	os_memcpy(pos, &protocol_type, 2);
+	pos += 2;
+
+	/* Version, Traffic Class, Flow label */
+	*pos = 0x60;
+	pos++;
+
+	*pos = 0x00;
+	pos++;
+
+	*pos = 0x00;
+	pos++;
+
+	*pos = 0x00;
+	pos++;
+
+	/* payload length */
+	os_memcpy(pos, &payload_len, 2);
+	pos += 2;
+
+	/* Next header */
+	*pos = 0x3a;
+	pos++;
+
+	/* Hop limit */
+	*pos = 0xff;
+	pos++;
+
+	/* source ip address */
+	os_memcpy(pos, target_ip_addr, 16);
+	pos += 16;
+
+	/* destination ip address */
+	if (IsDAD == 1) {
+		*pos = 0xff;pos++;
+		*pos = 0x02;pos++;
+		pos = pos + 13;
+		*pos = 0x01;pos++;
+	} else {
+		os_memcpy(pos, source_ip_addr, 16);
+		pos += 16;
+	}
+
+	/* ICMP field */
+	icmpv6hdr = pos;
+	/* Type */
+	*pos = 0x88;
+	pos++;
+
+	/* Code */
+	*pos = 0x00;
+	pos++;
+
+	/* Checksum */
+	pcsum = pos;
+	os_memcpy(pos, &checksum, 2);
+	pos += 2;
+
+	/* flags */
+	*pos = 0x60;
+	pos++;
+
+	*pos = 0x00;
+	pos++;
+
+	*pos = 0x00;
+	pos++;
+
+	*pos = 0x00;
+	pos++;
+
+	/* targer address */
+	os_memcpy(pos, target_ip_addr, 16);
+	pos += 16;
+
+	/* Possible options */
+	/* target linker-layerr address type */
+	*pos = 0x02;
+	pos++;
+
+	/* length */
+	*pos = 0x01;
+	pos++;
+
+	/* target link-layer address */
+	os_memcpy(pos, target_mac_addr, 6);
+	pos += 6;
+
+	/* re-calculate checksum */
+	if (IsDAD == 1)
+		checksum = icmpv6_csum(target_ip_addr, DadDestAddr, icmpmsglen, 0x3a, icmpv6hdr);
+	else
+		checksum = icmpv6_csum(target_ip_addr, source_ip_addr, icmpmsglen, 0x3a, icmpv6hdr);
+	os_memcpy(pcsum, &checksum, 2);
+}
+
+static void hotspot_proxy_arp_ipv4(char *buf,
+		const char *source_mac_addr,
+		const char *source_ip_addr,
+		const char *target_mac_addr,
+		const char *target_ip_addr,
+		unsigned char        IsDAD)
+{
+	char *pos;
+	u16 protocol_type = cpu2be16(0x0806);
+	u16 hw_address_type = cpu2be16(0x0001);
+	u16 protocol_address_type;
+	u16 arp_operation = cpu2be16(0x0002);;
+
+	pos = buf;
+
+	/* DA */
+	os_memcpy(pos, source_mac_addr, 6);
+	pos += 6;
+
+	/* SA */
+	os_memcpy(pos, target_mac_addr, 6);
+	pos += 6;
+
+	/* Protocol type */
+	os_memcpy(pos, &protocol_type, 2);
+	pos += 2;
+
+	/* HW address yype */
+	os_memcpy(pos, &hw_address_type, 2);
+	pos += 2;
+
+	/* Protocol address type */
+	protocol_address_type = cpu2be16(0x0800);
+	os_memcpy(pos, &protocol_address_type, 2);
+	pos += 2;
+
+	/* HW address size */
+	*pos = 0x06;
+	pos++;
+
+	/* Protocol address size */
+	*pos = 0x04;
+	pos++;
+
+	/* arp operation */
+	os_memcpy(pos, &arp_operation, 2);
+	pos += 2;
+
+	/* Sender MAC address */
+	os_memcpy(pos, target_mac_addr, 6);
+	pos += 6;
+
+	/* Sender IP address */
+	os_memcpy(pos, target_ip_addr, 4);
+	pos += 4;
+
+	/* Target MAC address */
+	os_memcpy(pos, source_mac_addr, 6);
+	pos += 6;
+
+	/* Target IP address */
+	os_memcpy(pos, source_ip_addr, 4);
+	pos += 4;
+}
+
+static int hotspot_event_proxy_arp(struct nl80211_global *global,
+		const int ifindex,
+		u8 ip_type,
+		u8 from_ds,
+		const char *source_mac_addr,
+		const char *source_ip_addr,
+		const char *target_mac_addr,
+		const char *target_ip_addr,
+		unsigned char IsDAD)
+{
+	int sock;
+	struct sockaddr_ll sll;
+	char *buf;
+	u8 bufsize;
+
+	/* send arp response on behalf of target */
+	sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
+	memset(&sll, 0, sizeof(sll));
+
+	if (from_ds) {
+		/* Send proxy arp packet to br-lan so that packet is sent to
+		 * that eth interface which is present at br-lan.
+		 */
+		sll.sll_ifindex = if_nametoindex("eth0");
+
+	} else {
+		sll.sll_ifindex = ifindex;
+	}
+
+	if (ip_type == IPV4)
+		bufsize = 60;
+	else
+		bufsize = 86;
+
+	buf = os_zalloc(bufsize);
+
+	if (ip_type == IPV4) {
+		hotspot_proxy_arp_ipv4(buf, source_mac_addr, source_ip_addr,
+				target_mac_addr, target_ip_addr, IsDAD);
+	} else {
+		hotspot_proxy_arp_ipv6(buf, source_mac_addr, source_ip_addr,
+				target_mac_addr, target_ip_addr, IsDAD);
+	}
+
+	if (sendto(sock, buf, bufsize, 0, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
+		return -1;
+	}
+
+	close(sock);
+
+	os_free(buf);
+	return 0;
+}
+
+
+static void event_proxy_arp(struct nl80211_global *global, char *buf)
+{
+	struct proxy_arp_entry *arp_entry = (struct proxy_arp_entry *)buf;
+	char ifname[IFNAMSIZ];
+
+	if_indextoname(arp_entry->ifindex, ifname);
+
+	if (arp_entry->ip_type == IPV4) {
+		hotspot_event_proxy_arp(global,
+				arp_entry->ifindex,
+				arp_entry->ip_type,
+				arp_entry->from_ds,
+				arp_entry->source_mac_addr,
+				arp_entry->ip_addr,
+				arp_entry->target_mac_addr,
+				arp_entry->ip_addr + 4,
+				arp_entry->IsDAD);
+	} else {
+		hotspot_event_proxy_arp(global,
+				arp_entry->ifindex,
+				arp_entry->ip_type,
+				arp_entry->from_ds,
+				arp_entry->source_mac_addr,
+				arp_entry->ip_addr,
+				arp_entry->target_mac_addr,
+				arp_entry->ip_addr + 16,
+				arp_entry->IsDAD);
+	}
+}
+
+static void driver_wext_event_wireless(struct nl80211_global *global,
+		char *data, int len)
+{
+	struct iw_event iwe_buf, *iwe = &iwe_buf;
+	char *pos, *end, *custom, *buf /*,*assoc_info_buf, *info_pos */;
+
+	pos = data;
+	end = data + len;
+
+	while (pos + IW_EV_LCP_LEN <= end) {
+		os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
+
+		if (iwe->len <= IW_EV_LCP_LEN)
+			return;
+
+		custom = pos + IW_EV_POINT_LEN;
+
+		char *dpos = (char *) &iwe_buf.u.data.length;
+		int dlen = dpos - (char *) &iwe_buf;
+		os_memcpy(dpos, pos + IW_EV_LCP_LEN,
+				sizeof(struct iw_event) - dlen);
+
+		switch (iwe->cmd) {
+			case IWEVCUSTOM:
+				if (custom + iwe->u.data.length > end)
+					return;
+				buf = os_malloc(iwe->u.data.length + 1);
+				if (buf == NULL)
+					return;
+				os_memcpy(buf, custom, iwe->u.data.length);
+				buf[iwe->u.data.length] = '\0';
+
+				switch (iwe->u.data.flags) {
+					case OID_802_11_WNM_PROXY_ARP:
+						event_proxy_arp(global, buf);
+						break;
+					default:
+						break;
+				}
+
+				os_free(buf);
+				break;
+		}
+
+		pos += iwe->len;
+	}
+}
 
 static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
 						 struct ifinfomsg *ifi,
@@ -1210,7 +1614,14 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
 			pos += os_snprintf(pos, end - pos, " master=%u", brid);
 			break;
 		case IFLA_WIRELESS:
+		{
+			int rta_len = RTA_ALIGN(sizeof(struct rtattr));
+			driver_wext_event_wireless(
+					global,
+					((char *) attr) + rta_len,
+					attr->rta_len - rta_len);
 			pos += os_snprintf(pos, end - pos, " wext");
+		}
 			break;
 		case IFLA_OPERSTATE:
 			pos += os_snprintf(pos, end - pos, " operstate=%u",
