* Work in progress of reworking the net80211 stack a bit, implementing some of

the missing notifications.
* Renamed ieee80211_haiku.c to .cpp, and made it compile (this part requires
  the updated GCC2, as it uses the ISO-C varargs macros).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38378 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-08-26 14:35:03 +00:00
parent 93e784a576
commit db4015a5f8
6 changed files with 149 additions and 74 deletions
+11 -5
View File
@@ -35,15 +35,21 @@ struct net_notifications_control {
// TODO: the following part of this header should end up in a public header
// some day!
#define B_NETWORK_INTERFACE_ADDED 0x01
#define B_NETWORK_INTERFACE_REMOVED 0x02
#define B_NETWORK_INTERFACE_CHANGED 0x03
#define B_NETWORK_DEVICE_LINK_CHANGED 0x10
#define B_NETWORK_INTERFACE_ADDED 0x0001
#define B_NETWORK_INTERFACE_REMOVED 0x0002
#define B_NETWORK_INTERFACE_CHANGED 0x0003
#define B_NETWORK_DEVICE_LINK_CHANGED 0x0010
#define B_NETWORK_WLAN_JOINED 0x0100
#define B_NETWORK_WLAN_LEFT 0x0200
#define B_NETWORK_WLAN_SCANNED 0x0300
#define B_NETWORK_WLAN_MESSAGE_INTEGRITY_FAILED 0x0400
// TODO: add routes, stack unloaded/loaded, ... events
enum {
B_WATCH_NETWORK_INTERFACE_CHANGES = 0x000f,
B_WATCH_NETWORK_LINK_CHANGES = 0x00f0
B_WATCH_NETWORK_LINK_CHANGES = 0x00f0,
B_WATCH_NETWORK_WLAN_CHANGES = 0x0f00
};
#define B_NETWORK_MONITOR '_NTN'
@@ -11,10 +11,10 @@ UsePrivateKernelHeaders ;
Includes [ FGristFiles kernel_c++_structs.h ]
: <src!system!kernel>kernel_c++_struct_sizes.h ;
SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ]
-Wno-format
-Wno-unused
-Wno-uninitialized ;
SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ]
-Wno-format -Wno-unused -Wno-uninitialized ;
SubDirC++Flags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ]
-Wno-format -Wno-unused -Wno-uninitialized ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) .. crypto rijndael ] ;
@@ -30,7 +30,7 @@ KernelStaticLibrary libfreebsd_wlan.a :
ieee80211_crypto_tkip.c
ieee80211_crypto_wep.c
ieee80211_dfs.c
ieee80211_haiku.c
ieee80211_haiku.cpp
ieee80211_ht.c
ieee80211_input.c
ieee80211_ioctl.c
@@ -60,5 +60,4 @@ KernelStaticLibrary libfreebsd_wlan.a :
# NOT SUPPORTED YET ieee80211_superg.c
# NOT SUPPORTED YET ieee80211_tdma.c
# NOT SUPPORTED YET ieee80211_xauth.c
;
;
@@ -35,12 +35,12 @@
*/
#include <SupportDefs.h>
#include "ieee80211_haiku.h"
extern "C" {
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/bus.h>
#include <sys/haiku-module.h>
#include <sys/sockio.h>
#include <net/if.h>
@@ -48,10 +48,16 @@
#include <net/if_types.h>
#include <net/if_var.h>
#include <ieee80211_var.h>
#include "ieee80211_var.h"
};
#include <SupportDefs.h>
#include <util/KMessage.h>
#include <ether_driver.h>
#include <bosii_driver.h>
#include <net_notifications.h>
#include <shared.h>
@@ -62,21 +68,42 @@ do { \
} while (/* CONSTCOND */ 0)
static net_notifications_module_info* sNotificationModule;
static struct ifnet*
get_ifnet(device_t device, int& i)
{
int unit = device_get_unit(device);
for (i = 0; i < MAX_DEVICES; i++) {
if (gDevices[i] != NULL && gDevices[i]->if_dunit == unit)
return gDevices[i];
}
return NULL;
}
status_t
init_wlan_stack()
init_wlan_stack(void)
{
ieee80211_phy_init();
ieee80211_auth_setup();
ieee80211_ht_init();
get_module(NET_NOTIFICATIONS_MODULE_NAME,
(module_info**)&sNotificationModule);
return B_OK;
}
void
uninit_wlan_stack()
uninit_wlan_stack(void)
{
if (sNotificationModule != NULL)
put_module(NET_NOTIFICATIONS_MODULE_NAME);
}
@@ -84,21 +111,11 @@ status_t
start_wlan(device_t device)
{
int i;
int unit = device_get_unit(device);
struct ifnet* ifp;
struct ieee80211com* ic;
struct ieee80211vap* vap;
for (i = 0; i < MAX_DEVICES; i++) {
if (gDevices[i] != NULL && gDevices[i]->if_dunit == unit)
break;
}
if (i == MAX_DEVICES)
return B_ERROR;
ifp = gDevices[i];
struct ifnet* ifp = get_ifnet(device, i);
if (ifp == NULL)
return B_BAD_VALUE;
// TODO: review this and find a cleaner solution!
// This ensures that the cloned device gets
// the same index assigned as the base device
// Resulting in the same device name
@@ -106,11 +123,10 @@ start_wlan(device_t device)
// /dev/net/atheros/1
gDevices[i] = NULL;
ic = ifp->if_l2com;
struct ieee80211com* ic = (ieee80211com*)ifp->if_l2com;
vap = ic->ic_vap_create(ic,
"wlan",
unit,
struct ieee80211vap* vap = ic->ic_vap_create(ic, "wlan",
device_get_unit(device),
IEEE80211_M_STA, // mode
0, // flags
NULL, // BSSID
@@ -140,30 +156,21 @@ status_t
stop_wlan(device_t device)
{
int i;
int unit = device_get_unit(device);
struct ifnet* ifp;
struct ieee80211com* ic;
struct ieee80211vap* vap;
struct ifnet* ifp = get_ifnet(device, i);
if (ifp == NULL)
return B_BAD_VALUE;
for (i = 0; i < MAX_DEVICES; i++) {
if (gDevices[i] != NULL && gDevices[i]->if_dunit == unit)
break;
if (ifp->if_type == IFT_IEEE80211) {
// This happens when there was an error in starting the wlan before,
// resulting in never creating a clone device
return B_OK;
}
if (i == MAX_DEVICES)
return B_ERROR;
ifp = gDevices[i];
if (ifp->if_type == IFT_IEEE80211)
// This happens when there was an error
// in starting the wlan before, resulting
// in never creating a clone device
return B_OK;
delete_sem(ifp->scan_done_sem);
vap = ifp->if_softc;
ic = vap->iv_ic;
struct ieee80211vap* vap = (ieee80211vap*)ifp->if_softc;
struct ieee80211com* ic = vap->iv_ic;
ic->ic_vap_delete(vap);
// ic_vap_delete freed gDevices[i]
@@ -179,7 +186,7 @@ stop_wlan(device_t device)
status_t
wlan_control(void* cookie, uint32 op, void* arg, size_t length)
{
struct ifnet* ifp = cookie;
struct ifnet* ifp = (struct ifnet*)cookie;
switch (op) {
case BOSII_DEVICE:
@@ -237,7 +244,7 @@ wlan_control(void* cookie, uint32 op, void* arg, size_t length)
// Tell the user space how much data was copied
networkRequest->mtu = request.i_len;
if (user_memcpy(arg + offsetof(struct ifreq, ifr_route.mtu),
if (user_memcpy(&((struct ifreq*)arg)->ifr_route.mtu,
&networkRequest->mtu, sizeof(networkRequest->mtu)) < B_OK)
return B_BAD_ADDRESS;
@@ -256,19 +263,17 @@ wlan_control(void* cookie, uint32 op, void* arg, size_t length)
if (length < sizeof(struct ifreq))
return B_BAD_VALUE;
if (user_memcpy(&ifRequest, arg, sizeof(ifRequest)) < B_OK)
if (user_memcpy(&ifRequest, arg, sizeof(ifRequest)) != B_OK
|| user_memcpy(&network, networkRequest->source,
sizeof(ieee80211req_scan_result)) != B_OK)
return B_BAD_ADDRESS;
if (user_memcpy(&network, networkRequest->source,
sizeof(network)) < B_OK)
return B_BAD_ADDRESS;
memset(&request, 0, sizeof(request));
memset(&request, 0, sizeof(ieee80211req));
request.i_type = IEEE80211_IOC_SSID;
request.i_val = 0;
request.i_len = network.isr_ssid_len;
request.i_data = ((void*) networkRequest->source)
request.i_data = (uint8*)networkRequest->source
+ network.isr_ie_off;
if (ifp->if_ioctl(ifp, SIOCS80211, (caddr_t)&request) < B_OK)
return B_ERROR;
@@ -312,8 +317,8 @@ wlan_control(void* cookie, uint32 op, void* arg, size_t length)
// Tell the user space how much data was copied
networkRequest->mtu = request.i_len;
if (user_memcpy(arg + offsetof(struct ifreq, ifr_route.mtu),
&networkRequest->mtu, sizeof(networkRequest->mtu)) < B_OK)
if (user_memcpy(&((struct ifreq*)arg)->ifr_route.mtu,
&networkRequest->mtu, sizeof(networkRequest->mtu)) != B_OK)
return B_BAD_ADDRESS;
return B_OK;
@@ -321,9 +326,25 @@ wlan_control(void* cookie, uint32 op, void* arg, size_t length)
case SIOCG80211:
case SIOCS80211:
{
// Allowing FreeBSD based WLAN ioctls to pass, as those will become
// the future Haiku WLAN ioctls anyway.
return ifp->if_ioctl(ifp, op, (caddr_t)arg);
// 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;
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;
}
}
return B_BAD_VALUE;
@@ -333,7 +354,7 @@ wlan_control(void* cookie, uint32 op, void* arg, size_t length)
status_t
wlan_close(void* cookie)
{
struct ifnet* ifp = cookie;
struct ifnet* ifp = (struct ifnet*)cookie;
ifp->if_flags &= ~IFF_UP;
ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL);
@@ -345,7 +366,7 @@ wlan_close(void* cookie)
status_t
wlan_if_l2com_alloc(void* data)
{
struct ifnet* ifp = data;
struct ifnet* ifp = (struct ifnet*)data;
ifp->if_l2com = _kernel_malloc(sizeof(struct ieee80211com), M_ZERO);
((struct ieee80211com*)(ifp->if_l2com))->ic_ifp = ifp;
@@ -358,7 +379,7 @@ wlan_if_l2com_alloc(void* data)
void
get_random_bytes(void* p, size_t n)
{
uint8_t* dp = p;
uint8_t* dp = (uint8_t*)p;
while (n > 0) {
uint32_t v = arc4random();
@@ -388,7 +409,7 @@ ieee80211_getmgtframe(uint8_t** frm, int headroom, int pktlen)
}
if (m != NULL) {
m->m_data += headroom;
*frm = m->m_data;
*frm = (uint8_t*)m->m_data;
}
return m;
}
@@ -546,6 +567,17 @@ ieee80211_notify_node_join(struct ieee80211_node* ni, int newassoc)
if (ni == vap->iv_bss)
if_link_state_change(ifp, LINK_STATE_UP);
if (sNotificationModule != NULL) {
char messageBuffer[512];
KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_WLAN_JOINED);
message.AddString("interface", ifp->if_xname);
// TODO: add data about the node
sNotificationModule->send_notification(&message);
}
}
@@ -557,6 +589,17 @@ ieee80211_notify_node_leave(struct ieee80211_node* ni)
if (ni == vap->iv_bss)
if_link_state_change(ifp, LINK_STATE_DOWN);
if (sNotificationModule != NULL) {
char messageBuffer[512];
KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_NETWORK_MONITOR);
message.AddInt32("opcode", B_NETWORK_WLAN_LEFT);
message.AddString("interface", ifp->if_xname);
// TODO: add data about the node
sNotificationModule->send_notification(&message);
}
}
@@ -565,6 +608,16 @@ ieee80211_notify_scan_done(struct ieee80211vap* vap)
{
release_sem_etc(vap->iv_ifp->scan_done_sem, 1,
B_DO_NOT_RESCHEDULE | B_RELEASE_ALL);
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->if_xname);
sNotificationModule->send_notification(&message);
}
}
@@ -27,8 +27,21 @@
#ifndef _FBSD_COMPAT_NET80211_IEEE80211_HAIKU_H_
#define _FBSD_COMPAT_NET80211_IEEE80211_HAIKU_H_
#include <stdint.h>
#ifdef _KERNEL
# ifdef __cplusplus
// Those includes are needed to avoid C/C++ function export clashes
# include <new>
# include <thread.h>
extern "C" {
# endif
#include <sys/kernel.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
@@ -291,6 +304,10 @@ typedef int ieee80211_ioctl_setfunc(struct ieee80211vap *,
struct ieee80211req *);
SET_DECLARE(ieee80211_ioctl_setset, ieee80211_ioctl_setfunc);
#define IEEE80211_IOCTL_SET(_name, _set) TEXT_SET(ieee80211_ioctl_setset, _set)
#ifdef __cplusplus
}
#endif
#endif /* _KERNEL */
/*
@@ -103,7 +103,7 @@ ieee80211_rate2phytype(const struct ieee80211_rate_table *rt, uint8_t rate)
{
uint8_t rix = rt->rateCodeToIndex[rate];
KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
return rt->info[rix].phy;
return (enum ieee80211_phytype)rt->info[rix].phy;
}
static __inline__ int
@@ -126,7 +126,7 @@ void ieee80211_addbasicrates(struct ieee80211_rateset *,
static __inline int
ieee80211_hdrsize(const void *data)
{
const struct ieee80211_frame *wh = data;
const struct ieee80211_frame *wh = (const struct ieee80211_frame *)data;
int size = sizeof(struct ieee80211_frame);
/* NB: we don't handle control frames */
@@ -145,7 +145,7 @@ ieee80211_hdrsize(const void *data)
static __inline int
ieee80211_anyhdrsize(const void *data)
{
const struct ieee80211_frame *wh = data;
const struct ieee80211_frame *wh = (const struct ieee80211_frame *)data;
if ((wh->i_fc[0]&IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) {
switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {