$NetBSD: patch-aa,v 1.1.1.1 2008/12/11 21:18:41 reed Exp $

--- src/drivers/driver_bsd.c.orig	2008-11-23 07:02:06.000000000 -0800
+++ src/drivers/driver_bsd.c	2008-12-11 12:30:26.000000000 -0800
@@ -21,7 +21,13 @@
 #include "ieee802_11_defs.h"
 
 #include <net/if.h>
+
+#ifdef __NetBSD__
+#include <net/if_ether.h>
+#define COMPAT_FREEBSD_NET80211
+#else
 #include <net/ethernet.h>
+#endif
 
 #include <net80211/ieee80211.h>
 #include <net80211/ieee80211_crypto.h>
@@ -32,6 +38,7 @@
 	int	route;			/* routing socket for events */
 	char	ifname[IFNAMSIZ+1];	/* interface name */
 	unsigned int ifindex;		/* interface index */
+	int flags;			/* interface flags */
 	void	*ctx;
 	int	prev_roaming;		/* roaming state to restore on deinit */
 	int	prev_privacy;		/* privacy state to restore on deinit */
@@ -145,9 +152,18 @@
 wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
 {
 	struct wpa_driver_bsd_data *drv = priv;
+#ifdef __NetBSD__
+	struct ieee80211_bssid bs;
 
+	strncpy(bs.i_name, drv->ifname, sizeof(bs.i_name));
+	if (ioctl(drv->sock, SIOCG80211BSSID, &bs) < 0)
+		return -1;
+	memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid));
+	return 0;
+#else
 	return get80211var(drv, IEEE80211_IOC_BSSID,
 		bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0;
+#endif
 }
 
 #if 0
@@ -155,6 +171,7 @@
 wpa_driver_bsd_set_bssid(void *priv, const char *bssid)
 {
 	struct wpa_driver_bsd_data *drv = priv;
+	struct ieee80211_bssid bs;
 
 	return set80211var(drv, IEEE80211_IOC_BSSID,
 		bssid, IEEE80211_ADDR_LEN);
@@ -165,9 +182,22 @@
 wpa_driver_bsd_get_ssid(void *priv, u8 *ssid)
 {
 	struct wpa_driver_bsd_data *drv = priv;
+#ifdef __NetBSD__
+	struct ieee80211_nwid nwid;
+	struct ifreq ifr;
 
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
+	ifr.ifr_data = (void *)&nwid;
+	if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 ||
+	    nwid.i_len > IEEE80211_NWID_LEN)
+		return -1;
+	memcpy(ssid, nwid.i_nwid, nwid.i_len);
+	return nwid.i_len;
+#else
 	return get80211var(drv, IEEE80211_IOC_SSID,
 		ssid, IEEE80211_NWID_LEN);
+#endif
 }
 
 static int
@@ -175,8 +205,19 @@
 			     size_t ssid_len)
 {
 	struct wpa_driver_bsd_data *drv = priv;
-
+#ifdef __NetBSD__
+	struct ieee80211_nwid nwid;
+	struct ifreq ifr;
+ 
+	memcpy(nwid.i_nwid, ssid, ssid_len);
+	nwid.i_len = ssid_len;
+	memset(&ifr, 0, sizeof(ifr));
+	(void)strncpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
+	ifr.ifr_data = (void *)&nwid;
+	return ioctl(drv->sock, SIOCS80211NWID, &ifr);
+#else
 	return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
+#endif
 }
 
 static int
@@ -301,13 +342,23 @@
 	if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) {
 		wk.ik_flags |= IEEE80211_KEY_GROUP;
 		wk.ik_keyix = key_idx;
+#ifdef __NetBSD__
+		if (set_tx)
+			wk.ik_flags |= IEEE80211_KEY_DEFAULT;
+	} else
+		wk.ik_keyix = IEEE80211_KEYIX_NONE;
+#else
 	} else {
 		wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx);
 	}
 	if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
 		wk.ik_flags |= IEEE80211_KEY_DEFAULT;
+#endif
 	wk.ik_keylen = key_len;
 	os_memcpy(&wk.ik_keyrsc, seq, seq_len);
+#ifdef __NetBSD__
+	wk.ik_keyrsc = le64toh(wk.ik_keyrsc);
+#endif
 	os_memcpy(wk.ik_keydata, key, key_len);
 
 	return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk));
@@ -380,10 +431,12 @@
 	/* XXX error handling is wrong but unclear what to do... */
 	if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
 		return -1;
+#ifndef __NetBSD
 #ifndef NEW_FREEBSD_MLME_ASSOC
 	if (wpa_driver_bsd_set_ssid(drv, params->ssid, params->ssid_len) < 0)
 		return -1;
 #endif
+#endif
 
 	privacy = !(params->pairwise_suite == CIPHER_NONE &&
 	    params->group_suite == CIPHER_NONE &&
@@ -449,7 +502,12 @@
 }
 
 #include <net/route.h>
+#if __FreeBSD__
 #include <net80211/ieee80211_freebsd.h>
+#endif
+#if __NetBSD__
+#include <net80211/ieee80211_netbsd.h>
+#endif
 
 static void
 wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
@@ -487,15 +545,23 @@
 		switch (ifan->ifan_what) {
 		case IFAN_DEPARTURE:
 			event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
+#ifdef __NetBSD__
+			break;
+#endif
 		default:
+#ifdef __NetBSD__
+			event.interface_status.ievent = EVENT_INTERFACE_ADDED;
+			break;
+#else
 			return;
+#endif
 		}
-		wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
+		wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s (%d)",
 			   event.interface_status.ifname,
 			   ifan->ifan_what == IFAN_DEPARTURE ?
-				"removed" : "added");
+				"removed" : "added", ifan->ifan_what);
 		wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
-		break;
+		return;
 	case RTM_IEEE80211:
 		ifan = (struct if_announcemsghdr *) rtm;
 		if (ifan->ifan_index != drv->ifindex)
@@ -503,15 +569,23 @@
 		switch (ifan->ifan_what) {
 		case RTM_IEEE80211_ASSOC:
 		case RTM_IEEE80211_REASSOC:
+			wpa_printf(MSG_DEBUG, "RTM_IEEE80211: (re)assoc (%d)",
+			    ifan->ifan_what);
 			wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
 			break;
 		case RTM_IEEE80211_DISASSOC:
+			wpa_printf(MSG_DEBUG, "RTM_IEEE80211: disassoc (%d)",
+			    ifan->ifan_what);
 			wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
 			break;
 		case RTM_IEEE80211_SCAN:
+			wpa_printf(MSG_DEBUG, "RTM_IEEE80211: scan result (%d)",
+			    ifan->ifan_what);
 			wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
 			break;
 		case RTM_IEEE80211_REPLAY:
+			wpa_printf(MSG_DEBUG, "RTM_IEEE80211: replay (%d)",
+			    ifan->ifan_what);
 			/* ignore */
 			break;
 		case RTM_IEEE80211_MICHAEL:
@@ -527,20 +601,48 @@
 			wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
 				&event);
 			break;
+		default:
+			wpa_printf(MSG_DEBUG, "RTM_IEEE80211: ??? (%d)",
+			    ifan->ifan_what);
+			break;
 		}
 		break;
 	case RTM_IFINFO:
 		ifm = (struct if_msghdr *) rtm;
 		if (ifm->ifm_index != drv->ifindex)
 			break;
-		if ((rtm->rtm_flags & RTF_UP) == 0) {
+		if ((ifm->ifm_flags & IFF_UP) == 0 &&
+		    (drv->flags & IFF_UP) != 0) {
 			strlcpy(event.interface_status.ifname, drv->ifname,
 				sizeof(event.interface_status.ifname));
 			event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
 			wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
 				   event.interface_status.ifname);
 			wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
+#ifdef __NetBSD__
+		} else if ((ifm->ifm_flags & IFF_UP) != 0 &&
+		    (drv->flags & IFF_UP) == 0) {
+			strlcpy(event.interface_status.ifname, drv->ifname,
+				sizeof(event.interface_status.ifname));
+			event.interface_status.ievent = EVENT_INTERFACE_ADDED;
+			wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
+				   event.interface_status.ifname);
+			wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
+		} else {
+			wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' "
+			    "if=%x drv=%x", event.interface_status.ifname,
+			     ifm->ifm_flags, drv->flags);
+#endif
 		}
+#ifdef __NetBSD__
+		drv->flags = ifm->ifm_flags;
+		break;
+	case RTM_LOSING:
+		wpa_printf(MSG_DEBUG, "RTM_LOSING: %d", rtm->rtm_type);
+		break;
+	default:
+		wpa_printf(MSG_DEBUG, "RTM_???: %d", rtm->rtm_type);
+#endif
 		break;
 	}
 }
@@ -632,8 +734,8 @@
 		wsr->ssid_len = sr->isr_ssid_len;
 		wsr->freq = sr->isr_freq;
 		wsr->noise = sr->isr_noise;
-		wsr->qual = sr->isr_rssi;
-		wsr->level = 0;		/* XXX? */
+		wsr->qual = 0;
+		wsr->level = sr->isr_rssi;
 		wsr->caps = sr->isr_capinfo;
 		wsr->maxrate = getmaxrate(sr->isr_rates, sr->isr_nrates);
 		vp = (u_int8_t *)(sr+1);
@@ -691,6 +793,7 @@
 	 *     This implies we do not support having wpa_supplicant
 	 *     wait for an interface to appear.  This seems ok; that
 	 *     doesn't belong here; it's really the job of devd.
+	 *     XXXSCW: devd is FreeBSD-specific.
 	 */
 	drv->ifindex = if_nametoindex(ifname);
 	if (drv->ifindex == 0) {
@@ -752,7 +855,9 @@
 	struct wpa_driver_bsd_data *drv = priv;
 	int flags;
 
+#ifndef __NetBSD__
 	eloop_unregister_read_sock(drv->route);
+#endif
 
 	/* NB: mark interface down */
 	if (getifflags(drv, &flags) == 0)
