diff --git a/src/libs/compat/Jamfile b/src/libs/compat/Jamfile index 006118f092..02aeb92452 100644 --- a/src/libs/compat/Jamfile +++ b/src/libs/compat/Jamfile @@ -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 ; diff --git a/src/libs/compat/openbsd_wlan/Jamfile b/src/libs/compat/openbsd_wlan/Jamfile new file mode 100644 index 0000000000..982b073de0 --- /dev/null +++ b/src/libs/compat/openbsd_wlan/Jamfile @@ -0,0 +1,3 @@ +SubDir HAIKU_TOP src libs compat openbsd_wlan ; + +SubInclude HAIKU_TOP src libs compat openbsd_wlan net80211 ; diff --git a/src/libs/compat/openbsd_wlan/net80211/Jamfile b/src/libs/compat/openbsd_wlan/net80211/Jamfile new file mode 100644 index 0000000000..ae532db9ca --- /dev/null +++ b/src/libs/compat/openbsd_wlan/net80211/Jamfile @@ -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 +; diff --git a/src/libs/compat/openbsd_wlan/net80211/bpfilter.h b/src/libs/compat/openbsd_wlan/net80211/bpfilter.h new file mode 100644 index 0000000000..3053583c76 --- /dev/null +++ b/src/libs/compat/openbsd_wlan/net80211/bpfilter.h @@ -0,0 +1 @@ +/* nothing here */ diff --git a/src/libs/compat/openbsd_wlan/net80211/bridge.h b/src/libs/compat/openbsd_wlan/net80211/bridge.h new file mode 100644 index 0000000000..3053583c76 --- /dev/null +++ b/src/libs/compat/openbsd_wlan/net80211/bridge.h @@ -0,0 +1 @@ +/* nothing here */ diff --git a/src/libs/compat/openbsd_wlan/net80211/ieee80211.c b/src/libs/compat/openbsd_wlan/net80211/ieee80211.c index d2e876c03a..61ea33d768 100644 --- a/src/libs/compat/openbsd_wlan/net80211/ieee80211.c +++ b/src/libs/compat/openbsd_wlan/net80211/ieee80211.c @@ -44,6 +44,9 @@ #include #include #include +#ifdef __HAIKU__ +#include +#endif #include #include @@ -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; } diff --git a/src/libs/compat/openbsd_wlan/net80211/ieee80211_haiku.cpp b/src/libs/compat/openbsd_wlan/net80211/ieee80211_haiku.cpp new file mode 100644 index 0000000000..89a8f7a342 --- /dev/null +++ b/src/libs/compat/openbsd_wlan/net80211/ieee80211_haiku.cpp @@ -0,0 +1,206 @@ +/* + * Copyright 2022, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +} + +#include + +#include + +#include +#include + + +#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 diff --git a/src/libs/compat/openbsd_wlan/net80211/ieee80211_ioctl.c b/src/libs/compat/openbsd_wlan/net80211/ieee80211_ioctl.c index 85d795d745..5f4ae04d38 100644 --- a/src/libs/compat/openbsd_wlan/net80211/ieee80211_ioctl.c +++ b/src/libs/compat/openbsd_wlan/net80211/ieee80211_ioctl.c @@ -40,6 +40,9 @@ #include #include #include +#ifdef __HAIKU__ +#include +#endif #include #include @@ -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; diff --git a/src/libs/compat/openbsd_wlan/net80211/ieee80211_output.c b/src/libs/compat/openbsd_wlan/net80211/ieee80211_output.c index a89ac8c915..b0f67a6489 100644 --- a/src/libs/compat/openbsd_wlan/net80211/ieee80211_output.c +++ b/src/libs/compat/openbsd_wlan/net80211/ieee80211_output.c @@ -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)) { diff --git a/src/libs/compat/openbsd_wlan/net80211/ieee80211_proto.c b/src/libs/compat/openbsd_wlan/net80211/ieee80211_proto.c index 7f8175d157..bc63829994 100644 --- a/src/libs/compat/openbsd_wlan/net80211/ieee80211_proto.c +++ b/src/libs/compat/openbsd_wlan/net80211/ieee80211_proto.c @@ -43,6 +43,9 @@ #include #include #include +#ifdef __HAIKU__ +#include +#endif #include #include @@ -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 } } diff --git a/src/libs/compat/openbsd_wlan/net80211/ieee80211_var.h b/src/libs/compat/openbsd_wlan/net80211/ieee80211_var.h index 3cb1ec9293..1288a6c389 100644 --- a/src/libs/compat/openbsd_wlan/net80211/ieee80211_var.h +++ b/src/libs/compat/openbsd_wlan/net80211/ieee80211_var.h @@ -37,9 +37,9 @@ * Definitions for IEEE 802.11 drivers. */ -#ifdef SMALL_KERNEL +//#ifdef SMALL_KERNEL #define IEEE80211_STA_ONLY 1 -#endif +//#endif #include @@ -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 *, diff --git a/src/libs/compat/openbsd_wlan/net80211/vlan.h b/src/libs/compat/openbsd_wlan/net80211/vlan.h new file mode 100644 index 0000000000..3053583c76 --- /dev/null +++ b/src/libs/compat/openbsd_wlan/net80211/vlan.h @@ -0,0 +1 @@ +/* nothing here */