--- sys/dev/if_ndis/if_ndis.c.orig Wed Oct 27 17:01:55 2004 +++ sys/dev/if_ndis/if_ndis.c Thu Oct 28 19:41:03 2004 @@ -107,6 +107,7 @@ static int ndis_ioctl (struct ifnet *, u_long, caddr_t); static int ndis_wi_ioctl_get (struct ifnet *, u_long, caddr_t); static int ndis_wi_ioctl_set (struct ifnet *, u_long, caddr_t); +static int ndis_ioctl_authmode (struct ifnet *, u_long, caddr_t); static void ndis_init (void *); static void ndis_stop (struct ndis_softc *); static void ndis_watchdog (struct ifnet *); @@ -1554,7 +1555,14 @@ ic->ic_wep_mode = IEEE80211_WEP_8021X; } #endif - arg = NDIS_80211_AUTHMODE_OPEN; + switch (sc->ndis_80211_authmode) { + case IEEE80211_AUTH_SHARED: + arg = NDIS_80211_AUTHMODE_SHARED; + break; + case IEEE80211_AUTH_OPEN: + default: + arg = NDIS_80211_AUTHMODE_OPEN; + } } else { arg = NDIS_80211_WEPSTAT_DISABLED; len = sizeof(arg); @@ -1565,10 +1573,8 @@ len = sizeof(arg); rval = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len); -#ifdef notyet if (rval) device_printf (sc->ndis_dev, "set auth failed: %d\n", rval); -#endif #ifdef notyet /* Set network type. */ @@ -1911,6 +1917,7 @@ struct ndis_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; int i, error = 0; + struct ieee80211req *ireq; /*NDIS_LOCK(sc);*/ @@ -1980,6 +1987,15 @@ error = ENOTTY; if (error != ENOTTY) break; + case SIOCG80211: + case SIOCS80211: + if (sc->ndis_80211 && NDIS_INITIALIZED(sc)) { + ireq = (struct ieee80211req *) data; + if (ireq->i_type == IEEE80211_IOC_AUTHMODE) { + error = ndis_ioctl_authmode(ifp, command, data); + break; + } + } default: sc->ndis_skip = 1; if (sc->ndis_80211) { @@ -2011,7 +2027,9 @@ ndis_80211_bssid_list_ex *bl; ndis_wlan_bssid_ex *wb; struct wi_apinfo *api; - int error, i, j, len, maxaps; + struct wi_scan_p2_hdr *p2; + struct wi_scan_res *res; + int error, i, j, k, len, maxaps; sc = ifp->if_softc; ifr = (struct ifreq *)data; @@ -2073,6 +2091,75 @@ free(bl, M_DEVBUF); error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); break; + case WI_RID_SCAN_RES: + len = 0; + error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN, + NULL, &len); + if (error == 0) + tsleep(&error, PPAUSE|PCATCH, "ssidscan", hz * 2); + len = 0; + error = ndis_get_info(sc, OID_802_11_BSSID_LIST, NULL, &len); + if (error != ENOSPC) + break; + bl = malloc(len, M_DEVBUF, M_WAITOK|M_ZERO); + error = ndis_get_info(sc, OID_802_11_BSSID_LIST, bl, &len); + if (error) { + free(bl, M_DEVBUF); + break; + } + + k = 0; + p2 = (struct wi_scan_p2_hdr *)wreq.wi_val; + res = (void *)&p2[1]; + wb = bl->nblx_bssid; + while ((caddr_t)(res + 1) < (caddr_t)(&wreq + 1) && + k < bl->nblx_items) { + bzero(res, sizeof(*res)); + bcopy(&wb->nwbx_macaddr, &res->wi_bssid, + sizeof(res->wi_bssid)); + res->wi_ssid_len = wb->nwbx_ssid.ns_ssidlen; + bcopy(&wb->nwbx_ssid.ns_ssid, &res->wi_ssid, + res->wi_ssid_len); + if (wb->nwbx_privacy) { + res->wi_capinfo |= IEEE80211_CAPINFO_PRIVACY; + } + /* XXX Where can we get noise information? */ + res->wi_signal = wb->nwbx_rssi + 149; /* XXX */ + res->wi_chan = + ieee80211_mhz2ieee(wb->nwbx_config.nc_dsconfig / + 1000, 0); + /* In "auto" infrastructure mode, this is useless. */ + if (wb->nwbx_netinfra == NDIS_80211_NET_INFRA_IBSS) + res->wi_capinfo |= IEEE80211_CAPINFO_IBSS; + if (wb->nwbx_len > sizeof(ndis_wlan_bssid)) { + j = sizeof(ndis_80211_rates_ex); + /* handle other extended things */ + } else + j = sizeof(ndis_80211_rates); + for (i = res->wi_rate = 0; i < j; i++) + res->wi_rate = MAX(res->wi_rate, + wb->nwbx_supportedrates[i]); + memcpy(res->wi_srates, wb->nwbx_supportedrates, + MIN(j, 10)); + if (j < 10) + res->wi_srates[j] = 0; + res->wi_rsvd = 0; + res++; + wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len); + k++; + } + p2->wi_rsvd = 0; + p2->wi_reason = k; + wreq.wi_len = (sizeof(*p2) + sizeof(*res) * k) / 2; + /* + * XXX: this is _so_ hackish, should probably be fixed in + * wicontrol. That uses a < to compare wi_len to the record + * length. It should probably use <= and be sensible. + */ + wreq.wi_len++; + free(bl, M_DEVBUF); + error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); + break; default: error = ENOTTY; break; @@ -2115,6 +2202,32 @@ break; } return (error); +} + +static int +ndis_ioctl_authmode(ifp, command, data) + struct ifnet *ifp; + u_long command; + caddr_t data; +{ + struct ndis_softc *sc = ifp->if_softc; + struct ieee80211req *ireq; + + ireq = (struct ieee80211req *) data; + if (command == SIOCG80211) { + ireq->i_val = sc->ndis_80211_authmode; + return 0; + } else { + switch (ireq->i_val) { + case IEEE80211_AUTH_OPEN: + case IEEE80211_AUTH_SHARED: + sc->ndis_80211_authmode = ireq->i_val; + ndis_setstate_80211(sc); + return 0; + default: + return EINVAL; + } + } } static void --- sys/dev/if_ndis/if_ndisvar.h.orig Thu Oct 28 20:16:10 2004 +++ sys/dev/if_ndis/if_ndisvar.h Thu Oct 28 19:23:52 2004 @@ -116,6 +116,7 @@ uint32_t ndis_filter; int ndis_if_flags; int ndis_skip; + uint16_t ndis_80211_authmode; #if __FreeBSD_version < 502113 struct sysctl_ctx_list ndis_ctx;