Date: Wed, 27 Oct 2004 15:40:13 EDT From: "Rogier R. Mulhuijzen" <lists@bsdchicks.com> To: wpaul@freebsd.org Cc: freebsd-current@freebsd.org Subject: [PATCH] NDISulator fixed to work with wicontrol -L and dstumbler Message-ID: <BasiliX-1.1.0-1098906013417ff99debc6c@artemis.drwilco.net>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] Subject says it all. I did some poking around in net80211 and dev/if_ndis (shouldn't that be just dev/ndis, like all other if_ modules?) and extended if_ndis.c some so that it answers the ioctl that's used by wicontrol and other userland programs (like dstumbler, part of the net-mgmt/bsd-airtools package/port) to list found 802.11 APs. I do have a few things that made me scratch my head. 1) Currently if there's more APs then can fit in the wreq struct, they're just ignored. There's no way to get a continued list, nor is there any flag to show the requestor that there's more. The wreq struct is a fixed size, and can't be extended without recompiling both kernel and userland. 2) The wi_rates array can only fit 10 rates, but 802.11g has more than 10 rates. Again, this can't be extended without recompiling kernel & userland. Also the 10 is hardcoded in net80211/ieee80211_ioctl.c. (I went ahead and copied it, in a "if it's OK there, it's OK here" kinda mood. But I'll be happy to supply patches for both) 3) When trying to stumble without bringing up the interface at least once, I get a big fat panic. But it seems to not be related to my changes. Still investigating that bit. Patch is attached but can be found at http://www.bsdchicks.com/patches/if_ndis.c.patch too. I'm still a kernel-hacking newb, so please review thouroughly (I managed to trample over random kernel space with early versions... fun fun fun), and fire off any comments you might have. Also my whitespace use might not be standard, since I don't know what the standard is. Greetings, DocWilco [-- Attachment #2 --] --- sys/dev/if_ndis/if_ndis.c.orig Wed Oct 27 17:01:55 2004 +++ sys/dev/if_ndis/if_ndis.c Wed Oct 27 21:10:18 2004 @@ -2011,7 +2011,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; @@ -2070,6 +2072,69 @@ api++; wb = (ndis_wlan_bssid_ex *)((char *)wb + wb->nwbx_len); } + 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 */ + wreq.wi_len++; free(bl, M_DEVBUF); error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); break;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?BasiliX-1.1.0-1098906013417ff99debc6c>
