* Work in progress network API changes.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39147 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-10-25 20:20:09 +00:00
parent 44fe7b9f4f
commit 1d56eab029
4 changed files with 419 additions and 0 deletions
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright 2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _NETWORK_DEVICE_H
#define _NETWORK_DEVICE_H
#include <net/if.h>
#include <NetworkAddress.h>
class BNetworkAddress;
struct wireless_network {
char name[32];
BNetworkAddress address;
uint8 noise_level;
uint8 signal_strength;
};
class BNetworkDevice {
public:
BNetworkDevice();
BNetworkDevice(const char* name);
~BNetworkDevice();
void Unset();
void SetTo(const char* name);
const char* Name() const;
uint32 Flags() const;
bool HasLink() const;
int32 CountMedia() const;
int32 GetMediaAt(int32 index) const;
int32 Media() const;
status_t SetMedia(int32 media);
status_t GetHardwareAddress(BNetworkAddress& address);
bool IsEthernet();
bool IsWireless();
status_t Scan(bool wait = true,
bool forceRescan = true);
ssize_t CountScanResults();
status_t GetScanResultAt(int32 index,
wireless_network& network);
status_t JoinNetwork(const BNetworkAddress& address,
const char* password = NULL);
status_t LeaveNetwork();
status_t GetCurrentNetwork(wireless_network& network);
status_t GetCurrentNetwork(BNetworkAddress& address);
private:
char fName[IF_NAMESIZE];
};
#endif // _NETWORK_DEVICE_H
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright 2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _NETWORK_NOTIFICATIONS_H
#define _NETWORK_NOTIFICATIONS_H
#include <SupportDefs.h>
class BHandler;
class BLooper;
class BMessenger;
#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_WLAN_CHANGES = 0x0f00
};
#define B_NETWORK_MONITOR '_NTN'
#ifdef __cplusplus
status_t start_watching_network(uint32 flags, const BMessenger& target);
status_t start_watching_network(uint32 flags, const BHandler* handler,
const BLooper* looper = NULL);
status_t stop_watching_network(const BMessenger& target);
status_t stop_watching_network(const BHandler* handler,
const BLooper* looper = NULL);
#endif // __cplusplus
#endif // _NETWORK_NOTIFICATIONS_H
+1
View File
@@ -7,6 +7,7 @@
#include <Locker.h>
#include <NetworkNotifications.h>
class BMessenger;
@@ -0,0 +1,302 @@
/*
* Copyright 2010, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <NetworkDevice.h>
#include <errno.h>
#include <net/if.h>
#include <sys/sockio.h>
#include <AutoDeleter.h>
extern "C" {
#include <net80211/ieee80211_ioctl.h>
}
status_t
get_80211(const char* name, int32 type, void* data, int32& length)
{
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
if (socket < 0)
return errno;
FileDescriptorCloser closer(socket);
struct ieee80211req ireq;
strlcpy(ireq.i_name, name, IF_NAMESIZE);
ireq.i_type = type;
ireq.i_val = 0;
ireq.i_len = length;
ireq.i_data = data;
if (ioctl(socket, SIOCG80211, &ireq, sizeof(struct ieee80211req)) < 0)
return errno;
length = ireq.i_len;
return B_OK;
}
#if 0
static status_t
set_80211(const char* name, int32 type, void* data,
int32 length = 0, int32 value = 0)
{
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
if (socket < 0)
return errno;
FileDescriptorCloser closer(socket);
struct ieee80211req ireq;
strlcpy(ireq.i_name, name, IF_NAMESIZE);
ireq.i_type = type;
ireq.i_val = value;
ireq.i_len = length;
ireq.i_data = data;
if (ioctl(socket, SIOCS80211, &ireq, sizeof(struct ieee80211req)) < 0)
return errno;
return B_OK;
}
template<typename T> status_t
set_80211(const char* name, int32 type, T& data, int32 length = 0,
int32 value = 0)
{
if (length == 0)
length = sizeof(T);
return set_80211(name, &data, length, value);
}
#endif
template<typename T> status_t
do_request(T& request, const char* name, int option)
{
int socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
if (socket < 0)
return errno;
FileDescriptorCloser closer(socket);
strlcpy(((struct ifreq&)request).ifr_name, name, IF_NAMESIZE);
if (ioctl(socket, option, &request, sizeof(T)) < 0)
return errno;
return B_OK;
}
// #pragma mark -
BNetworkDevice::BNetworkDevice()
{
Unset();
}
BNetworkDevice::BNetworkDevice(const char* name)
{
SetTo(name);
}
BNetworkDevice::~BNetworkDevice()
{
}
void
BNetworkDevice::Unset()
{
fName[0] = '\0';
}
void
BNetworkDevice::SetTo(const char* name)
{
strlcpy(fName, name, IF_NAMESIZE);
}
const char*
BNetworkDevice::Name() const
{
return fName;
}
uint32
BNetworkDevice::Flags() const
{
ifreq request;
if (do_request(request, Name(), SIOCGIFFLAGS) != B_OK)
return 0;
return request.ifr_flags;
}
bool
BNetworkDevice::HasLink() const
{
return (Flags() & IFF_LINK) != 0;
}
int32
BNetworkDevice::CountMedia() const
{
ifmediareq request;
request.ifm_count = 0;
request.ifm_ulist = NULL;
if (do_request(request, Name(), SIOCGIFMEDIA) != B_OK)
return -1;
return request.ifm_count;
}
int32
BNetworkDevice::Media() const
{
ifmediareq request;
request.ifm_count = 0;
request.ifm_ulist = NULL;
if (do_request(request, Name(), SIOCGIFMEDIA) != B_OK)
return -1;
return request.ifm_current;
}
int32
BNetworkDevice::GetMediaAt(int32 index) const
{
// TODO: this could do some caching
return 0;
}
status_t
BNetworkDevice::SetMedia(int32 media)
{
ifreq request;
request.ifr_media = media;
return do_request(request, Name(), SIOCSIFMEDIA);
}
status_t
BNetworkDevice::GetHardwareAddress(BNetworkAddress& address)
{
ifreq request;
status_t status = do_request(request, Name(), SIOCSIFMEDIA);
if (status != B_OK)
return status;
address.SetTo(request.ifr_addr);
return B_OK;
}
ssize_t
BNetworkDevice::CountScanResults()
{
// TODO: this needs some caching!
const size_t kBufferSize = 32768;
uint8* buffer = (uint8*)malloc(kBufferSize);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter deleter(buffer);
int32 length = kBufferSize;
status_t status = get_80211(Name(), IEEE80211_IOC_SCAN_RESULTS,
buffer, length);
if (status < B_OK)
return status;
int32 bytesLeft = length;
uint8* entry = buffer;
int32 count = 0;
while (bytesLeft > (int32)sizeof(struct ieee80211req_scan_result)) {
ieee80211req_scan_result* result
= (ieee80211req_scan_result*)entry;
entry += result->isr_len;
bytesLeft -= result->isr_len;
count++;
}
return count;
}
status_t
BNetworkDevice::GetScanResultAt(int32 index, wireless_network& network)
{
#if 0
if (index == 0) {
struct ieee80211_scan_req request;
memset(&request, 0, sizeof(request));
request.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE
| IEEE80211_IOC_SCAN_NOJOIN;
request.sr_duration = IEEE80211_IOC_SCAN_FOREVER;
set_80211(Name(), IEEE80211_IOC_SCAN_REQ, NULL);
}
#endif
const size_t kBufferSize = 32768;
uint8* buffer = (uint8*)malloc(kBufferSize);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter deleter(buffer);
int32 length = kBufferSize;
status_t status = get_80211(Name(), IEEE80211_IOC_SCAN_RESULTS,
buffer, length);
if (status != B_OK)
return status;
int32 bytesLeft = length;
uint8* entry = buffer;
int32 count = 0;
while (bytesLeft > (int32)sizeof(struct ieee80211req_scan_result)) {
ieee80211req_scan_result* result
= (ieee80211req_scan_result*)entry;
if (count == index) {
// Fill wireless_network with scan result data
// TODO: add more fields
strlcpy(network.name, (char*)(result + 1),
min_c((int)sizeof(network.name), result->isr_ssid_len + 1));
network.address.SetToLinkLevel(result->isr_bssid,
IEEE80211_ADDR_LEN);
network.signal_strength = result->isr_rssi;
network.noise_level = result->isr_noise;
return B_OK;
}
entry += result->isr_len;
bytesLeft -= result->isr_len;
count++;
}
return B_BAD_INDEX;
}