openbsd_wlan: Basic adaptations to the net80211 layer.

The stack now compiles and links. Combining this with adaptations to
the driver gets things to the point where it runs scans, but we do
not yet implement ioctls so they can be returned to userland.
This commit is contained in:
Augustin Cavalier 2022-05-12 23:05:26 -04:00
parent 27a20680c5
commit eb56146603
12 changed files with 355 additions and 3 deletions

View File

@ -3,3 +3,4 @@ SubDir HAIKU_TOP src libs compat ;
SubInclude HAIKU_TOP src libs compat freebsd_network ;
SubInclude HAIKU_TOP src libs compat freebsd_iflib ;
SubInclude HAIKU_TOP src libs compat freebsd_wlan ;
SubInclude HAIKU_TOP src libs compat openbsd_wlan ;

View File

@ -0,0 +1,3 @@
SubDir HAIKU_TOP src libs compat openbsd_wlan ;
SubInclude HAIKU_TOP src libs compat openbsd_wlan net80211 ;

View File

@ -0,0 +1,50 @@
SubDir HAIKU_TOP src libs compat openbsd_wlan net80211 ;
UseHeaders [ FDirName $(SUBDIR) .. ] : true ;
UseHeaders [ FDirName $(SUBDIR) .. .. openbsd_network compat ] : true ;
UseHeaders [ FDirName $(SUBDIR) .. .. freebsd_network ] : true ;
UseHeaders [ FDirName $(SUBDIR) .. .. freebsd_network compat ] : true ;
UsePrivateHeaders net system ;
UsePrivateKernelHeaders ;
SubDirCcFlags [ FDefines _KERNEL=1 ]
-Wno-format -Wno-unused -Wno-uninitialized -Wno-pointer-sign -Wno-sign-compare ;
SubDirC++Flags [ FDefines _KERNEL=1 ] -fpermissive ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) .. ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) .. crypto ] ;
KernelStaticLibrary openbsd_wlan.a :
ieee80211_haiku.cpp
ieee80211.c
ieee80211_amrr.c
ieee80211_crypto.c
ieee80211_crypto_bip.c
ieee80211_crypto_ccmp.c
ieee80211_crypto_tkip.c
ieee80211_crypto_wep.c
ieee80211_input.c
ieee80211_ioctl.c
ieee80211_node.c
ieee80211_output.c
ieee80211_pae_input.c
ieee80211_pae_output.c
ieee80211_proto.c
ieee80211_ra.c
ieee80211_ra_vht.c
ieee80211_regdomain.c
ieee80211_rssadapt.c
aes.c
arc4.c
cmac.c
hmac.c
key_wrap.c
md5.c
michael.c
sha1.c
sha2.c
subr_tree.c
;

View File

@ -0,0 +1 @@
/* nothing here */

View File

@ -0,0 +1 @@
/* nothing here */

View File

@ -44,6 +44,9 @@
#include <sys/endian.h>
#include <sys/errno.h>
#include <sys/sysctl.h>
#ifdef __HAIKU__
#include <sys/task.h>
#endif
#include <net/if.h>
#include <net/if_dl.h>
@ -162,9 +165,13 @@ ieee80211_ifattach(struct ifnet *ifp)
{
struct ieee80211com *ic = (void *)ifp;
#ifdef __FreeBSD_version
ether_ifattach(ifp, ic->ic_myaddr);
#else
memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,
ETHER_ADDR_LEN);
ether_ifattach(ifp);
#endif
ifp->if_output = ieee80211_output;
@ -190,8 +197,10 @@ ieee80211_ifattach(struct ifnet *ifp)
ieee80211_node_attach(ifp);
ieee80211_proto_attach(ifp);
#ifndef __FreeBSD_version
if_addgroup(ifp, "wlan");
ifp->if_priority = IF_WIRELESS_DEFAULT_PRIORITY;
#endif
task_set(&ic->ic_rtm_80211info_task, ieee80211_rtm_80211info_task, ic);
ieee80211_set_link_state(ic, LINK_STATE_DOWN);
@ -207,17 +216,21 @@ ieee80211_ifdetach(struct ifnet *ifp)
task_del(systq, &ic->ic_rtm_80211info_task);
timeout_del(&ic->ic_bgscan_timeout);
#ifndef __HAIKU__
/*
* Undo pseudo-driver changes. Pseudo-driver detach hooks could
* call back into the driver, e.g. via ioctl. So deactivate the
* interface before freeing net80211-specific data structures.
*/
if_deactivate(ifp);
#endif
ieee80211_proto_detach(ifp);
ieee80211_crypto_detach(ifp);
ieee80211_node_detach(ifp);
#ifndef __HAIKU__
ifmedia_delete_instance(&ic->ic_media, IFM_INST_ANY);
#endif
ether_ifdetach(ifp);
}
@ -412,7 +425,12 @@ ieee80211_media_init(struct ifnet *ifp,
}
if (ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) {
#ifdef __FreeBSD_version
// TODO: this probably isn't correct!
mopt = IFM_IEEE80211_11NA | IFM_IEEE80211_11NG;
#else
mopt = IFM_IEEE80211_11N;
#endif
ADD(ic, IFM_AUTO, mopt);
#ifndef IEEE80211_STA_ONLY
if (ic->ic_caps & IEEE80211_C_IBSS)
@ -425,6 +443,9 @@ ieee80211_media_init(struct ifnet *ifp,
for (i = 0; i < IEEE80211_HT_NUM_MCS; i++) {
if (!isset(ic->ic_sup_mcs, i))
continue;
#ifdef __FreeBSD_version
ADD(ic, IFM_IEEE80211_MCS, mopt);
#else
ADD(ic, IFM_IEEE80211_HT_MCS0 + i, mopt);
#ifndef IEEE80211_STA_ONLY
if (ic->ic_caps & IEEE80211_C_IBSS)
@ -437,13 +458,19 @@ ieee80211_media_init(struct ifnet *ifp,
if (ic->ic_caps & IEEE80211_C_MONITOR)
ADD(ic, IFM_IEEE80211_HT_MCS0 + i,
mopt | IFM_IEEE80211_MONITOR);
#endif
}
ic->ic_flags |= IEEE80211_F_HTON; /* enable 11n by default */
ieee80211_configure_ampdu_tx(ic, 1);
}
if (ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) {
#ifdef __FreeBSD_version
// TODO: this probably isn't correct!
mopt = IFM_IEEE80211_VHT2G | IFM_IEEE80211_VHT5G;
#else
mopt = IFM_IEEE80211_11AC;
#endif
ADD(ic, IFM_AUTO, mopt);
#ifndef IEEE80211_STA_ONLY
if (ic->ic_caps & IEEE80211_C_IBSS)
@ -459,6 +486,9 @@ ieee80211_media_init(struct ifnet *ifp,
if (!vht_mcs_supported)
continue;
#endif
#ifdef __FreeBSD_version
ADD(ic, IFM_IEEE80211_VHT, mopt);
#else
ADD(ic, IFM_IEEE80211_VHT_MCS0 + i, mopt);
#ifndef IEEE80211_STA_ONLY
if (ic->ic_caps & IEEE80211_C_IBSS)
@ -471,6 +501,7 @@ ieee80211_media_init(struct ifnet *ifp,
if (ic->ic_caps & IEEE80211_C_MONITOR)
ADD(ic, IFM_IEEE80211_VHT_MCS0 + i,
mopt | IFM_IEEE80211_MONITOR);
#endif
}
ic->ic_flags |= IEEE80211_F_VHTON; /* enable 11ac by default */
ic->ic_flags |= IEEE80211_F_HTON; /* 11ac implies 11n */
@ -527,10 +558,20 @@ ieee80211_media_change(struct ifnet *ifp)
case IFM_IEEE80211_11G:
newphymode = IEEE80211_MODE_11G;
break;
#ifdef __FreeBSD_version
case IFM_IEEE80211_11NA:
case IFM_IEEE80211_11NG:
#else
case IFM_IEEE80211_11N:
#endif
newphymode = IEEE80211_MODE_11N;
break;
#ifdef __FreeBSD_version
case IFM_IEEE80211_VHT5G:
case IFM_IEEE80211_VHT2G:
#else
case IFM_IEEE80211_11AC:
#endif
newphymode = IEEE80211_MODE_11AC;
break;
case IFM_AUTO:
@ -550,8 +591,12 @@ ieee80211_media_change(struct ifnet *ifp)
* Next, the fixed/variable rate.
*/
i = -1;
#ifdef __FreeBSD_version
if (IFM_SUBTYPE(ime->ifm_media) == IFM_IEEE80211_VHT) {
#else
if (IFM_SUBTYPE(ime->ifm_media) >= IFM_IEEE80211_VHT_MCS0 &&
IFM_SUBTYPE(ime->ifm_media) <= IFM_IEEE80211_VHT_MCS9) {
#endif
if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) == 0)
return EINVAL;
if (newphymode != IEEE80211_MODE_AUTO &&
@ -561,8 +606,12 @@ ieee80211_media_change(struct ifnet *ifp)
/* TODO: Obtain VHT MCS information from VHT CAP IE. */
if (i == -1 /* || !vht_mcs_supported */)
return EINVAL;
#ifdef __FreeBSD_version
} else if (IFM_SUBTYPE(ime->ifm_media) == IFM_IEEE80211_MCS) {
#else
} else if (IFM_SUBTYPE(ime->ifm_media) >= IFM_IEEE80211_HT_MCS0 &&
IFM_SUBTYPE(ime->ifm_media) <= IFM_IEEE80211_HT_MCS76) {
#endif
if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) == 0)
return EINVAL;
if (newphymode != IEEE80211_MODE_AUTO &&
@ -778,10 +827,18 @@ ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
imr->ifm_active |= IFM_IEEE80211_11G;
break;
case IEEE80211_MODE_11N:
#ifdef __FreeBSD_version
imr->ifm_active |= IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? IFM_IEEE80211_11NA : IFM_IEEE80211_11NG;
#else
imr->ifm_active |= IFM_IEEE80211_11N;
#endif
break;
case IEEE80211_MODE_11AC:
#ifdef __FreeBSD_version
imr->ifm_active |= IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? IFM_IEEE80211_VHT5G : IFM_IEEE80211_VHT2G;
#else
imr->ifm_active |= IFM_IEEE80211_11AC;
#endif
break;
}
}
@ -1236,6 +1293,7 @@ ieee80211_mcs2media(struct ieee80211com *ic, int mcs,
/* these modes use rates, not MCS */
panic("%s: unexpected mode %d", __func__, mode);
break;
#ifndef __FreeBSD_version /* can't be converted to FreeBSD IFM */
case IEEE80211_MODE_11N:
if (mcs >= 0 && mcs < IEEE80211_HT_NUM_MCS)
return (IFM_IEEE80211_11N |
@ -1246,6 +1304,7 @@ ieee80211_mcs2media(struct ieee80211com *ic, int mcs,
return (IFM_IEEE80211_11AC |
(IFM_IEEE80211_VHT_MCS0 + mcs));
break;
#endif
case IEEE80211_MODE_AUTO:
break;
}
@ -1268,6 +1327,7 @@ ieee80211_media2mcs(uint64_t mword)
else if (subtype == IFM_MANUAL || subtype == IFM_NONE)
return 0;
#ifndef __FreeBSD_version
if (subtype >= IFM_IEEE80211_HT_MCS0 &&
subtype <= IFM_IEEE80211_HT_MCS76)
return (int)(subtype - IFM_IEEE80211_HT_MCS0);
@ -1275,6 +1335,7 @@ ieee80211_media2mcs(uint64_t mword)
if (subtype >= IFM_IEEE80211_VHT_MCS0 &&
subtype <= IFM_IEEE80211_VHT_MCS9)
return (int)(subtype - IFM_IEEE80211_VHT_MCS0);
#endif
return -1;
}

View File

@ -0,0 +1,206 @@
/*
* Copyright 2022, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
extern "C" {
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/endian.h>
#include <sys/errno.h>
#include <sys/task.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <net80211/ieee80211_var.h>
}
#include <shared.h>
#include <util/KMessage.h>
#include <ether_driver.h>
#include <net_notifications.h>
#define TRACE_WLAN
#ifdef TRACE_WLAN
# define TRACE(x...) dprintf(x);
#else
# define TRACE(x...) ;
#endif
static net_notifications_module_info* sNotificationModule;
static struct ifnet*
get_ifnet(device_t device, int& i)
{
void* softc = device_get_softc(device);
for (i = 0; i < MAX_DEVICES; i++) {
if (gDevices[i] != NULL && gDevices[i]->if_softc == softc)
return gDevices[i];
}
return NULL;
}
status_t
init_wlan_stack(void)
{
get_module(NET_NOTIFICATIONS_MODULE_NAME,
(module_info**)&sNotificationModule);
return B_OK;
}
void
uninit_wlan_stack(void)
{
if (sNotificationModule != NULL)
put_module(NET_NOTIFICATIONS_MODULE_NAME);
}
static void
ieee80211_init()
{
}
status_t
start_wlan(device_t device)
{
int i;
struct ifnet* ifp = get_ifnet(device, i);
if (ifp == NULL)
return B_BAD_VALUE;
struct ieee80211com* ic = (ieee80211com*)ifp;
if (ifp->if_init == NULL)
ifp->if_init = ieee80211_init;
ifp->if_flags |= IFF_NEEDSGIANT;
if_initname(ifp, device_get_name(device), i);
dprintf("%s: wlan started.\n", __func__);
return B_OK;
}
status_t
stop_wlan(device_t device)
{
int i;
struct ifnet* ifp = get_ifnet(device, i);
if (ifp == NULL)
return B_BAD_VALUE;
struct ieee80211com* ic = (ieee80211com*)ifp;
return B_OK;
}
status_t
wlan_close(void* cookie)
{
dprintf("wlan_close(%p)\n", cookie);
struct ifnet* ifp = (struct ifnet*)cookie;
ifp->if_flags &= ~IFF_UP;
ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL);
return B_OK;
}
status_t
wlan_control(void* cookie, uint32 op, void* arg, size_t length)
{
struct ifnet* ifp = (struct ifnet*)cookie;
#if 0
switch (op) {
case SIOCG80211:
case SIOCS80211:
{
// FreeBSD drivers assume that the request structure has already
// been copied into kernel space
struct ieee80211req request;
if (user_memcpy(&request, arg, sizeof(struct ieee80211req)) != B_OK)
return B_BAD_ADDRESS;
TRACE("wlan_control: %" B_PRIu32 ", %d\n", op, request.i_type);
status_t status = ifp->if_ioctl(ifp, op, (caddr_t)&request);
if (status != B_OK)
return status;
if (op == SIOCG80211 && user_memcpy(arg, &request,
sizeof(struct ieee80211req)) != B_OK)
return B_BAD_ADDRESS;
return B_OK;
}
}
#endif
return B_BAD_VALUE;
}
void
ieee80211_rtm_80211info_task(void* arg)
{
struct ieee80211com *ic = arg;
struct ifnet *ifp = &ic->ic_if;
if (sNotificationModule != NULL) {
char messageBuffer[512];
KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
if (ifp->if_link_state == LINK_STATE_UP)
message.AddInt32("opcode", B_NETWORK_WLAN_JOINED);
else
message.AddInt32("opcode", B_NETWORK_WLAN_LEFT);
message.AddString("interface", ifp->device_name);
// TODO: add data about the node
sNotificationModule->send_notification(&message);
}
}
#if 0
void
ieee80211_notify_scan_done(struct ieee80211vap* vap)
{
release_sem_etc(vap->iv_ifp->scan_done_sem, 1,
B_DO_NOT_RESCHEDULE | B_RELEASE_ALL);
TRACE("%s\n", __FUNCTION__);
if (sNotificationModule != NULL) {
char messageBuffer[512];
KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_WLAN_SCANNED);
message.AddString("interface", vap->iv_ifp->device_name);
sNotificationModule->send_notification(&message);
}
}
#endif

View File

@ -40,6 +40,9 @@
#include <sys/systm.h>
#include <sys/endian.h>
#include <sys/tree.h>
#ifdef __HAIKU__
#include <sys/ucred.h>
#endif
#include <net/if.h>
#include <net/if_media.h>
@ -968,6 +971,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ic->ic_userflags = flags;
error = ENETRESET;
break;
#ifndef __HAIKU__
case SIOCADDMULTI:
case SIOCDELMULTI:
error = (cmd == SIOCADDMULTI) ?
@ -976,8 +980,13 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
if (error == ENETRESET)
error = 0;
break;
#endif
default:
#ifdef __FreeBSD_version
error = ether_ioctl(ifp, cmd, data);
#else
error = ether_ioctl(ifp, &ic->ic_ac, cmd, data);
#endif
}
return error;

View File

@ -123,6 +123,7 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
goto bad;
}
#ifdef PACKET_TAG_DLT
/* Try to get the DLT from a mbuf tag */
if ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) {
struct ieee80211com *ic = (void *)ifp;
@ -145,6 +146,7 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
return (if_enqueue(ifp, m));
}
#endif
fallback:
return (ether_output(ifp, m, dst, rt));
@ -456,6 +458,7 @@ ieee80211_classify(struct ieee80211com *ic, struct mbuf *m)
* Preserves backward compatibility with IP Precedence field.
*/
switch (ds_field & 0xfc) {
#ifdef IPTOS_PREC_PRIORITY
case IPTOS_PREC_PRIORITY:
return EDCA_AC_VI;
case IPTOS_PREC_IMMEDIATE:
@ -466,6 +469,7 @@ ieee80211_classify(struct ieee80211com *ic, struct mbuf *m)
case IPTOS_PREC_INTERNETCONTROL:
case IPTOS_PREC_NETCONTROL:
return EDCA_AC_VO;
#endif
default:
return EDCA_AC_BE;
}
@ -531,6 +535,7 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni)
u_int dlt, hdrlen;
int addqos, tid;
#ifdef PACKET_TAG_DLT
/* Handle raw frames if mbuf is tagged as 802.11 */
if ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) {
dlt = *(u_int *)(mtag + 1);
@ -567,6 +572,7 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni)
*pni = ni;
return (m);
}
#endif
fallback:
if (m->m_len < sizeof(struct ether_header)) {

View File

@ -43,6 +43,9 @@
#include <sys/endian.h>
#include <sys/errno.h>
#include <sys/sysctl.h>
#ifdef __HAIKU__
#include <sys/task.h>
#endif
#include <net/if.h>
#include <net/if_dl.h>
@ -1342,6 +1345,7 @@ justcleanup:
return 0;
}
#ifndef __FreeBSD_version
void
ieee80211_rtm_80211info_task(void *arg)
{
@ -1366,6 +1370,7 @@ ieee80211_rtm_80211info_task(void *arg)
splx(s);
}
#endif
void
ieee80211_set_link_state(struct ieee80211com *ic, int nstate)
@ -1386,9 +1391,14 @@ ieee80211_set_link_state(struct ieee80211com *ic, int nstate)
break;
}
if (nstate != ifp->if_link_state) {
#ifdef __FreeBSD_version
if_link_state_change(ifp, nstate);
task_add(systq, &ic->ic_rtm_80211info_task);
#else
ifp->if_link_state = nstate;
if (LINK_STATE_IS_UP(nstate))
task_add(systq, &ic->ic_rtm_80211info_task);
if_link_state_change(ifp);
#endif
}
}

View File

@ -37,9 +37,9 @@
* Definitions for IEEE 802.11 drivers.
*/
#ifdef SMALL_KERNEL
//#ifdef SMALL_KERNEL
#define IEEE80211_STA_ONLY 1
#endif
//#endif
#include <sys/timeout.h>
@ -229,7 +229,10 @@ struct ieee80211_defrag {
struct ieee80211_node_switch_bss_arg;
struct ieee80211com {
struct arpcom ic_ac;
struct {
struct ifnet ac_if;
u_char ac_enaddr[6];
} ic_ac;
LIST_ENTRY(ieee80211com) ic_list; /* chain of all ieee80211com */
void (*ic_recv_mgmt)(struct ieee80211com *,
struct mbuf *, struct ieee80211_node *,

View File

@ -0,0 +1 @@
/* nothing here */