* 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:
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user