Browse Source

Change Linux driver wrappers to use shared netlink receive code

Jouni Malinen 15 years ago
parent
commit
a6fc4f3c82

+ 18 - 96
src/drivers/driver_atheros.c

@@ -63,6 +63,7 @@
 #include "priv_netlink.h"
 #include "priv_netlink.h"
 #include "l2_packet/l2_packet.h"
 #include "l2_packet/l2_packet.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_defs.h"
+#include "netlink.h"
 
 
 
 
 struct madwifi_driver_data {
 struct madwifi_driver_data {
@@ -73,7 +74,7 @@ struct madwifi_driver_data {
 	struct l2_packet_data *sock_xmit;	/* raw packet xmit socket */
 	struct l2_packet_data *sock_xmit;	/* raw packet xmit socket */
 	struct l2_packet_data *sock_recv;	/* raw packet recv socket */
 	struct l2_packet_data *sock_recv;	/* raw packet recv socket */
 	int	ioctl_sock;			/* socket for ioctl() use */
 	int	ioctl_sock;			/* socket for ioctl() use */
-	int	wext_sock;			/* socket for wireless events */
+	struct netlink_data *netlink;
 	int	we_version;
 	int	we_version;
 	u8	acct_mac[ETH_ALEN];
 	u8	acct_mac[ETH_ALEN];
 	struct hostap_sta_driver_data acct_data;
 	struct hostap_sta_driver_data acct_data;
@@ -935,28 +936,18 @@ madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
 
 
 
 
 static void
 static void
-madwifi_wireless_event_rtm_newlink(struct madwifi_driver_data *drv,
-					       struct nlmsghdr *h, int len)
+madwifi_wireless_event_rtm_newlink(void *ctx,
+				   struct ifinfomsg *ifi, u8 *buf, size_t len)
 {
 {
-	struct ifinfomsg *ifi;
-	int attrlen, nlmsg_len, rta_len;
-	struct rtattr * attr;
-
-	if (len < (int) sizeof(*ifi))
-		return;
-
-	ifi = NLMSG_DATA(h);
+	struct madwifi_driver_data *drv = ctx;
+	int attrlen, rta_len;
+	struct rtattr *attr;
 
 
 	if (ifi->ifi_index != drv->ifindex)
 	if (ifi->ifi_index != drv->ifindex)
 		return;
 		return;
 
 
-	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
-	attrlen = NLMSG_PAYLOAD(h, sizeof(struct ifinfomsg));
-	if (attrlen < 0)
-		return;
-
-	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
+	attrlen = len;
+	attr = (struct rtattr *) buf;
 
 
 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
 	while (RTA_OK(attr, attrlen)) {
 	while (RTA_OK(attr, attrlen)) {
@@ -970,55 +961,6 @@ madwifi_wireless_event_rtm_newlink(struct madwifi_driver_data *drv,
 }
 }
 
 
 
 
-static void
-madwifi_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 madwifi_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:
-			madwifi_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
 static int
 madwifi_get_we_version(struct madwifi_driver_data *drv)
 madwifi_get_we_version(struct madwifi_driver_data *drv)
 {
 {
@@ -1068,45 +1010,25 @@ madwifi_get_we_version(struct madwifi_driver_data *drv)
 static int
 static int
 madwifi_wireless_event_init(struct madwifi_driver_data *drv)
 madwifi_wireless_event_init(struct madwifi_driver_data *drv)
 {
 {
-	int s;
-	struct sockaddr_nl local;
+	struct netlink_config *cfg;
 
 
 	madwifi_get_we_version(drv);
 	madwifi_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)");
+	cfg = os_zalloc(sizeof(*cfg));
+	if (cfg == NULL)
 		return -1;
 		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);
+	cfg->ctx = drv;
+	cfg->newlink_cb = madwifi_wireless_event_rtm_newlink;
+	drv->netlink = netlink_init(cfg);
+	if (drv->netlink == NULL) {
+		os_free(cfg);
 		return -1;
 		return -1;
 	}
 	}
 
 
-	eloop_register_read_sock(s, madwifi_wireless_event_receive, drv, NULL);
-	drv->wext_sock = s;
-
 	return 0;
 	return 0;
 }
 }
 
 
 
 
-static void
-madwifi_wireless_event_deinit(struct madwifi_driver_data *drv)
-{
-	if (drv->wext_sock < 0)
-		return;
-	eloop_unregister_read_sock(drv->wext_sock);
-	close(drv->wext_sock);
-}
-
-
 static int
 static int
 madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
 madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
 		   int encrypt, const u8 *own_addr)
 		   int encrypt, const u8 *own_addr)
@@ -1239,7 +1161,7 @@ madwifi_deinit(void *priv)
 {
 {
 	struct madwifi_driver_data *drv = priv;
 	struct madwifi_driver_data *drv = priv;
 
 
-	madwifi_wireless_event_deinit(drv);
+	netlink_deinit(drv->netlink);
 	(void) madwifi_set_iface_flags(drv, 0);
 	(void) madwifi_set_iface_flags(drv, 0);
 	if (drv->ioctl_sock >= 0)
 	if (drv->ioctl_sock >= 0)
 		close(drv->ioctl_sock);
 		close(drv->ioctl_sock);

+ 19 - 96
src/drivers/driver_hostap.c

@@ -29,6 +29,7 @@
 #include <netpacket/packet.h>
 #include <netpacket/packet.h>
 
 
 #include "priv_netlink.h"
 #include "priv_netlink.h"
+#include "netlink.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_defs.h"
 
 
 
 
@@ -45,7 +46,7 @@ struct hostap_driver_data {
 	char iface[IFNAMSIZ + 1];
 	char iface[IFNAMSIZ + 1];
 	int sock; /* raw packet socket for driver access */
 	int sock; /* raw packet socket for driver access */
 	int ioctl_sock; /* socket for ioctl() use */
 	int ioctl_sock; /* socket for ioctl() use */
-	int wext_sock; /* socket for wireless events */
+	struct netlink_data *netlink;
 
 
 	int we_version;
 	int we_version;
 
 
@@ -905,28 +906,19 @@ static void hostapd_wireless_event_wireless(struct hostap_driver_data *drv,
 }
 }
 
 
 
 
-static void hostapd_wireless_event_rtm_newlink(struct hostap_driver_data *drv,
-					       struct nlmsghdr *h, int len)
+static void hostapd_wireless_event_rtm_newlink(void *ctx,
+					       struct ifinfomsg *ifi,
+					       u8 *buf, size_t len)
 {
 {
-	struct ifinfomsg *ifi;
-	int attrlen, nlmsg_len, rta_len;
-	struct rtattr * attr;
-
-	if (len < (int) sizeof(*ifi))
-		return;
-
-	ifi = NLMSG_DATA(h);
+	struct hostap_driver_data *drv = ctx;
+	int attrlen, rta_len;
+	struct rtattr *attr;
 
 
 	/* TODO: use ifi->ifi_index to filter out wireless events from other
 	/* TODO: use ifi->ifi_index to filter out wireless events from other
 	 * interfaces */
 	 * interfaces */
 
 
-	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
-	attrlen = NLMSG_PAYLOAD(h, sizeof(struct ifinfomsg));
-	if (attrlen < 0)
-		return;
-
-	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
+	attrlen = len;
+	attr = (struct rtattr *) buf;
 
 
 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
 	while (RTA_OK(attr, attrlen)) {
 	while (RTA_OK(attr, attrlen)) {
@@ -940,55 +932,6 @@ static void hostapd_wireless_event_rtm_newlink(struct hostap_driver_data *drv,
 }
 }
 
 
 
 
-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)
 static int hostap_get_we_version(struct hostap_driver_data *drv)
 {
 {
 	struct iw_range *range;
 	struct iw_range *range;
@@ -1036,45 +979,25 @@ static int hostap_get_we_version(struct hostap_driver_data *drv)
 
 
 static int hostap_wireless_event_init(struct hostap_driver_data *drv)
 static int hostap_wireless_event_init(struct hostap_driver_data *drv)
 {
 {
-	int s;
-	struct sockaddr_nl local;
+	struct netlink_config *cfg;
 
 
 	hostap_get_we_version(drv);
 	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)");
+	cfg = os_zalloc(sizeof(*cfg));
+	if (cfg == NULL)
 		return -1;
 		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);
+	cfg->ctx = drv;
+	cfg->newlink_cb = hostapd_wireless_event_rtm_newlink;
+	drv->netlink = netlink_init(cfg);
+	if (drv->netlink == NULL) {
+		os_free(cfg);
 		return -1;
 		return -1;
 	}
 	}
 
 
-	eloop_register_read_sock(s, hostapd_wireless_event_receive, drv,
-				 NULL);
-	drv->wext_sock = s;
-
 	return 0;
 	return 0;
 }
 }
 
 
 
 
-static void hostap_wireless_event_deinit(struct hostap_driver_data *drv)
-{
-	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,
 static void * hostap_init(struct hostapd_data *hapd,
 			  struct wpa_init_params *params)
 			  struct wpa_init_params *params)
 {
 {
@@ -1120,7 +1043,7 @@ static void hostap_driver_deinit(void *priv)
 {
 {
 	struct hostap_driver_data *drv = priv;
 	struct hostap_driver_data *drv = priv;
 
 
-	hostap_wireless_event_deinit(drv);
+	netlink_deinit(drv->netlink);
 	(void) hostap_set_iface_flags(drv, 0);
 	(void) hostap_set_iface_flags(drv, 0);
 	(void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0);
 	(void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0);
 	(void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0);
 	(void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0);

+ 18 - 96
src/drivers/driver_madwifi.c

@@ -73,6 +73,7 @@
 #ifdef HOSTAPD
 #ifdef HOSTAPD
 
 
 #include "priv_netlink.h"
 #include "priv_netlink.h"
+#include "netlink.h"
 #include "l2_packet/l2_packet.h"
 #include "l2_packet/l2_packet.h"
 
 
 
 
@@ -84,7 +85,7 @@ struct madwifi_driver_data {
 	struct l2_packet_data *sock_xmit;	/* raw packet xmit socket */
 	struct l2_packet_data *sock_xmit;	/* raw packet xmit socket */
 	struct l2_packet_data *sock_recv;	/* raw packet recv socket */
 	struct l2_packet_data *sock_recv;	/* raw packet recv socket */
 	int	ioctl_sock;			/* socket for ioctl() use */
 	int	ioctl_sock;			/* socket for ioctl() use */
-	int	wext_sock;			/* socket for wireless events */
+	struct netlink_data *netlink;
 	int	we_version;
 	int	we_version;
 	u8	acct_mac[ETH_ALEN];
 	u8	acct_mac[ETH_ALEN];
 	struct hostap_sta_driver_data acct_data;
 	struct hostap_sta_driver_data acct_data;
@@ -1005,28 +1006,18 @@ madwifi_wireless_event_wireless(struct madwifi_driver_data *drv,
 
 
 
 
 static void
 static void
-madwifi_wireless_event_rtm_newlink(struct madwifi_driver_data *drv,
-					       struct nlmsghdr *h, int len)
+madwifi_wireless_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
+				   u8 *buf, size_t len)
 {
 {
-	struct ifinfomsg *ifi;
-	int attrlen, nlmsg_len, rta_len;
-	struct rtattr * attr;
-
-	if (len < (int) sizeof(*ifi))
-		return;
-
-	ifi = NLMSG_DATA(h);
+	struct madwifi_driver_data *drv = ctx;
+	int attrlen, rta_len;
+	struct rtattr *attr;
 
 
 	if (ifi->ifi_index != drv->ifindex)
 	if (ifi->ifi_index != drv->ifindex)
 		return;
 		return;
 
 
-	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
-	attrlen = NLMSG_PAYLOAD(h, sizeof(struct ifinfomsg));
-	if (attrlen < 0)
-		return;
-
-	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
+	attrlen = len;
+	attr = (struct rtattr *) buf;
 
 
 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
 	while (RTA_OK(attr, attrlen)) {
 	while (RTA_OK(attr, attrlen)) {
@@ -1040,55 +1031,6 @@ madwifi_wireless_event_rtm_newlink(struct madwifi_driver_data *drv,
 }
 }
 
 
 
 
-static void
-madwifi_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 madwifi_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:
-			madwifi_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
 static int
 madwifi_get_we_version(struct madwifi_driver_data *drv)
 madwifi_get_we_version(struct madwifi_driver_data *drv)
 {
 {
@@ -1138,45 +1080,25 @@ madwifi_get_we_version(struct madwifi_driver_data *drv)
 static int
 static int
 madwifi_wireless_event_init(struct madwifi_driver_data *drv)
 madwifi_wireless_event_init(struct madwifi_driver_data *drv)
 {
 {
-	int s;
-	struct sockaddr_nl local;
+	struct netlink_config *cfg;
 
 
 	madwifi_get_we_version(drv);
 	madwifi_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)");
+	cfg = os_zalloc(sizeof(*cfg));
+	if (cfg == NULL)
 		return -1;
 		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);
+	cfg->ctx = drv;
+	cfg->newlink_cb = madwifi_wireless_event_rtm_newlink;
+	drv->netlink = netlink_init(cfg);
+	if (drv->netlink == NULL) {
+		os_free(cfg);
 		return -1;
 		return -1;
 	}
 	}
 
 
-	eloop_register_read_sock(s, madwifi_wireless_event_receive, drv, NULL);
-	drv->wext_sock = s;
-
 	return 0;
 	return 0;
 }
 }
 
 
 
 
-static void
-madwifi_wireless_event_deinit(struct madwifi_driver_data *drv)
-{
-	if (drv->wext_sock < 0)
-		return;
-	eloop_unregister_read_sock(drv->wext_sock);
-	close(drv->wext_sock);
-}
-
-
 static int
 static int
 madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
 madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len,
 		   int encrypt, const u8 *own_addr)
 		   int encrypt, const u8 *own_addr)
@@ -1309,7 +1231,7 @@ madwifi_deinit(void *priv)
 {
 {
 	struct madwifi_driver_data *drv = priv;
 	struct madwifi_driver_data *drv = priv;
 
 
-	madwifi_wireless_event_deinit(drv);
+	netlink_deinit(drv->netlink);
 	(void) madwifi_set_iface_flags(drv, 0);
 	(void) madwifi_set_iface_flags(drv, 0);
 	if (drv->ioctl_sock >= 0)
 	if (drv->ioctl_sock >= 0)
 		close(drv->ioctl_sock);
 		close(drv->ioctl_sock);

+ 18 - 87
src/drivers/driver_ralink.c

@@ -24,6 +24,7 @@
 #include "eloop.h"
 #include "eloop.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_defs.h"
 #include "priv_netlink.h"
 #include "priv_netlink.h"
+#include "netlink.h"
 #include "driver_ralink.h"
 #include "driver_ralink.h"
 
 
 static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx);
 static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx);
@@ -33,7 +34,7 @@ static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx);
 struct wpa_driver_ralink_data {
 struct wpa_driver_ralink_data {
 	void *ctx;
 	void *ctx;
 	int ioctl_sock;
 	int ioctl_sock;
-	int event_sock;
+	struct netlink_data *netlink;
 	char ifname[IFNAMSIZ + 1];
 	char ifname[IFNAMSIZ + 1];
 	u8 *assoc_req_ies;
 	u8 *assoc_req_ies;
 	size_t assoc_req_ies_len;
 	size_t assoc_req_ies_len;
@@ -747,29 +748,20 @@ wpa_driver_ralink_event_wireless(struct wpa_driver_ralink_data *drv,
 }
 }
 
 
 static void
 static void
-wpa_driver_ralink_event_rtm_newlink(struct wpa_driver_ralink_data *drv,
-				    void *ctx, struct nlmsghdr *h, int len)
+wpa_driver_ralink_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, 
+				    u8 *buf, size_t len)
 {
 {
-	struct ifinfomsg *ifi;
-	int attrlen, nlmsg_len, rta_len;
-	struct rtattr * attr;
+	struct wpa_driver_ralink_data *drv = ctx;
+	int attrlen, rta_len;
+	struct rtattr *attr;
 
 
 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 
 
-	if (len < (int) sizeof(*ifi))
-		return;
-
-	ifi = NLMSG_DATA(h);
 	wpa_hexdump(MSG_DEBUG, "ifi: ", (u8 *) ifi, sizeof(struct ifinfomsg));
 	wpa_hexdump(MSG_DEBUG, "ifi: ", (u8 *) ifi, sizeof(struct ifinfomsg));
 
 
-	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
-	attrlen = NLMSG_PAYLOAD(h, sizeof(struct ifinfomsg));
+	attrlen = len;
 	wpa_printf(MSG_DEBUG, "attrlen=%d", attrlen);
 	wpa_printf(MSG_DEBUG, "attrlen=%d", attrlen);
-	if (attrlen < 0)
-		return;
-
-	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
+	attr = (struct rtattr *) buf;
 	wpa_hexdump(MSG_DEBUG, "attr1: ", (u8 *) attr, sizeof(struct rtattr));
 	wpa_hexdump(MSG_DEBUG, "attr1: ", (u8 *) attr, sizeof(struct rtattr));
 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
 	wpa_hexdump(MSG_DEBUG, "attr2: ", (u8 *)attr,rta_len);
 	wpa_hexdump(MSG_DEBUG, "attr2: ", (u8 *)attr,rta_len);
@@ -787,60 +779,6 @@ wpa_driver_ralink_event_rtm_newlink(struct wpa_driver_ralink_data *drv,
 	}
 	}
 }
 }
 
 
-static void wpa_driver_ralink_event_receive(int sock, void *ctx,
-					    void *sock_ctx)
-{
-	char buf[8192];
-	int left;
-	struct sockaddr_nl from;
-	socklen_t fromlen;
-	struct nlmsghdr *h;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	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;
-	wpa_hexdump(MSG_DEBUG, "h: ", (u8 *)h, h->nlmsg_len);
-
-	while (left >= (int) sizeof(*h)) {
-		int len, plen;
-
-		len = h->nlmsg_len;
-		plen = len - sizeof(*h);
-		if (len > left || plen < 0) {
-			wpa_printf(MSG_DEBUG, "Malformed netlink message: "
-				   "len=%d left=%d plen=%d", len, left, plen);
-			break;
-		}
-
-		switch (h->nlmsg_type) {
-		case RTM_NEWLINK:
-			wpa_driver_ralink_event_rtm_newlink(ctx, sock_ctx, h,
-							    plen);
-			break;
-		}
-
-		len = NLMSG_ALIGN(len);
-		left -= len;
-		h = (struct nlmsghdr *) ((char *) h + len);
-	}
-
-	if (left > 0) {
-		wpa_printf(MSG_DEBUG, "%d extra bytes in the end of netlink "
-			   "message", left);
-	}
-
-}
-
 static int
 static int
 ralink_get_we_version_compiled(struct wpa_driver_ralink_data *drv)
 ralink_get_we_version_compiled(struct wpa_driver_ralink_data *drv)
 {
 {
@@ -899,8 +837,8 @@ static void * wpa_driver_ralink_init(void *ctx, const char *ifname)
 	int s;
 	int s;
 	struct wpa_driver_ralink_data *drv;
 	struct wpa_driver_ralink_data *drv;
 	struct ifreq ifr;
 	struct ifreq ifr;
-	struct sockaddr_nl local;
 	UCHAR enable_wpa_supplicant = 0;
 	UCHAR enable_wpa_supplicant = 0;
+	struct netlink_config *cfg;
 
 
 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
 
 
@@ -928,28 +866,22 @@ static void * wpa_driver_ralink_init(void *ctx, const char *ifname)
 	drv->ioctl_sock = s;
 	drv->ioctl_sock = s;
 	drv->g_driver_down = 0;
 	drv->g_driver_down = 0;
 
 
-	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-	if (s < 0) {
-		perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
+	cfg = os_zalloc(sizeof(*cfg));
+	if (cfg == NULL) {
 		close(drv->ioctl_sock);
 		close(drv->ioctl_sock);
 		os_free(drv);
 		os_free(drv);
 		return NULL;
 		return NULL;
 	}
 	}
-
-	os_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);
+	cfg->ctx = drv;
+	cfg->newlink_cb = wpa_driver_ralink_event_rtm_newlink;
+	drv->netlink = netlink_init(cfg);
+	if (drv->netlink == NULL) {
+		os_free(cfg);
 		close(drv->ioctl_sock);
 		close(drv->ioctl_sock);
 		os_free(drv);
 		os_free(drv);
 		return NULL;
 		return NULL;
 	}
 	}
 
 
-	eloop_register_read_sock(s, wpa_driver_ralink_event_receive, drv, ctx);
-	drv->event_sock = s;
 	drv->no_of_pmkid = 4; /* Number of PMKID saved supported */
 	drv->no_of_pmkid = 4; /* Number of PMKID saved supported */
 
 
 	ralink_set_iface_flags(drv, 1);	/* mark up during setup */
 	ralink_set_iface_flags(drv, 1);	/* mark up during setup */
@@ -1007,8 +939,7 @@ static void wpa_driver_ralink_deinit(void *priv)
 	}
 	}
 
 
 	eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx);
 	eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx);
-	eloop_unregister_read_sock(drv->event_sock);
-	close(drv->event_sock);
+	netlink_deinit(drv->netlink);
 	close(drv->ioctl_sock);
 	close(drv->ioctl_sock);
 	os_free(drv);
 	os_free(drv);
 }
 }

+ 4 - 0
src/drivers/drivers.mak

@@ -5,6 +5,7 @@ DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP
 DRV_OBJS += ../src/drivers/driver_hostap.o
 DRV_OBJS += ../src/drivers/driver_hostap.o
 CONFIG_WIRELESS_EXTENSION=y
 CONFIG_WIRELESS_EXTENSION=y
 NEED_AP_MLME=y
 NEED_AP_MLME=y
+NEED_NETLINK=y
 endif
 endif
 
 
 ifdef CONFIG_DRIVER_WIRED
 ifdef CONFIG_DRIVER_WIRED
@@ -17,6 +18,7 @@ DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI
 DRV_OBJS += ../src/drivers/driver_madwifi.o
 DRV_OBJS += ../src/drivers/driver_madwifi.o
 CONFIG_WIRELESS_EXTENSION=y
 CONFIG_WIRELESS_EXTENSION=y
 CONFIG_L2_PACKET=linux
 CONFIG_L2_PACKET=linux
+NEED_NETLINK=y
 endif
 endif
 
 
 ifdef CONFIG_DRIVER_NL80211
 ifdef CONFIG_DRIVER_NL80211
@@ -61,6 +63,7 @@ ifdef CONFIG_DRIVER_ATHEROS
 DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS
 DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS
 DRV_AP_OBJS += ../src/drivers/driver_atheros.o
 DRV_AP_OBJS += ../src/drivers/driver_atheros.o
 CONFIG_L2_PACKET=linux
 CONFIG_L2_PACKET=linux
+NEED_NETLINK=y
 endif
 endif
 
 
 ##### PURE CLIENT DRIVERS
 ##### PURE CLIENT DRIVERS
@@ -92,6 +95,7 @@ endif
 ifdef CONFIG_DRIVER_RALINK
 ifdef CONFIG_DRIVER_RALINK
 DRV_WPA_CFLAGS += -DCONFIG_DRIVER_RALINK
 DRV_WPA_CFLAGS += -DCONFIG_DRIVER_RALINK
 DRV_WPA_OBJS += ../src/drivers/driver_ralink.o
 DRV_WPA_OBJS += ../src/drivers/driver_ralink.o
+NEED_NETLINK=y
 endif
 endif
 
 
 ifdef CONFIG_DRIVER_BROADCOM
 ifdef CONFIG_DRIVER_BROADCOM