* Adapted API as needed, and implemented most of the C++ API - it's completely
untested at this point, though. * Will port ifconfig, NetworkStatus, and the Network preferences application later in order to test the API. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37988 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <Archivable.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
class BNetworkAddress : public BArchivable {
|
||||
@@ -21,10 +22,12 @@ public:
|
||||
const char* address, uint16 port = 0);
|
||||
BNetworkAddress(const char* address,
|
||||
uint16 port = 0);
|
||||
BNetworkAddress(const sockaddr* address);
|
||||
BNetworkAddress(const sockaddr_in* address);
|
||||
BNetworkAddress(const sockaddr_in6* address);
|
||||
BNetworkAddress(const sockaddr_dl* address);
|
||||
BNetworkAddress(const sockaddr& address);
|
||||
BNetworkAddress(
|
||||
const sockaddr_storage& address);
|
||||
BNetworkAddress(const sockaddr_in& address);
|
||||
BNetworkAddress(const sockaddr_in6& address);
|
||||
BNetworkAddress(const sockaddr_dl& address);
|
||||
BNetworkAddress(const in_addr_t address);
|
||||
BNetworkAddress(const in6_addr* address);
|
||||
BNetworkAddress(const BNetworkAddress& other);
|
||||
@@ -38,10 +41,11 @@ public:
|
||||
status_t SetTo(int family, const char* address,
|
||||
uint16 port = 0);
|
||||
status_t SetTo(const char* address, uint16 port = 0);
|
||||
void SetTo(const sockaddr* address);
|
||||
void SetTo(const sockaddr_in* address);
|
||||
void SetTo(const sockaddr_in6* address);
|
||||
void SetTo(const sockaddr_dl* address);
|
||||
void SetTo(const sockaddr& address);
|
||||
void SetTo(const sockaddr_storage& address);
|
||||
void SetTo(const sockaddr_in& address);
|
||||
void SetTo(const sockaddr_in6& address);
|
||||
void SetTo(const sockaddr_dl& address);
|
||||
void SetTo(const in_addr_t address);
|
||||
void SetTo(const in6_addr* address);
|
||||
void SetTo(const BNetworkAddress& other);
|
||||
@@ -63,6 +67,7 @@ public:
|
||||
int Family() const;
|
||||
uint16 Port() const;
|
||||
size_t Length() const;
|
||||
const sockaddr& SockAddr() const;
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsWildcard() const;
|
||||
@@ -84,17 +89,20 @@ public:
|
||||
uint8* LinkLevelAddress() const;
|
||||
size_t LinkLevelAddressLength() const;
|
||||
|
||||
BNetworkAddress ResolvedForDestination(
|
||||
const BNetworkAddress& destination) const;
|
||||
void ResolveTo(const BNetworkAddress& address);
|
||||
status_t ResolveForDestination(
|
||||
const BNetworkAddress& destination);
|
||||
status_t ResolveTo(const BNetworkAddress& address);
|
||||
|
||||
BString ToString() const;
|
||||
BString ToString(bool includePort = true) const;
|
||||
BString HostName() const;
|
||||
BString PortName() const;
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
static BArchivable* Instantiate(BMessage* archive);
|
||||
|
||||
bool Equals(const BNetworkAddress& other,
|
||||
bool includePort = true) const;
|
||||
|
||||
BNetworkAddress& operator=(const BNetworkAddress& other);
|
||||
|
||||
bool operator==(const BNetworkAddress& other) const;
|
||||
|
||||
@@ -21,9 +21,12 @@ public:
|
||||
BNetworkInterfaceAddress();
|
||||
~BNetworkInterfaceAddress();
|
||||
|
||||
status_t SetTo(BNetworkInterface& interface,
|
||||
int32 index);
|
||||
|
||||
void SetAddress(BNetworkAddress& address);
|
||||
void SetMask(BNetworkAddress& mask);
|
||||
void SetBroadcast(BNetworkAddress& mask);
|
||||
void SetBroadcast(BNetworkAddress& broadcast);
|
||||
|
||||
BNetworkAddress& Address() { return fAddress; }
|
||||
BNetworkAddress& Mask() { return fMask; }
|
||||
@@ -36,9 +39,10 @@ public:
|
||||
void SetFlags(uint32 flags);
|
||||
uint32 Flags() const { return fFlags; }
|
||||
|
||||
int32 Index() const { return fIndex; }
|
||||
|
||||
private:
|
||||
BNetworkInterface* fInterface;
|
||||
uint32 fIndex;
|
||||
int32 fIndex;
|
||||
BNetworkAddress fAddress;
|
||||
BNetworkAddress fMask;
|
||||
BNetworkAddress fBroadcast;
|
||||
@@ -53,9 +57,14 @@ public:
|
||||
BNetworkInterface(uint32 index);
|
||||
~BNetworkInterface();
|
||||
|
||||
void Unset();
|
||||
void SetTo(const char* name);
|
||||
status_t SetTo(uint32 index);
|
||||
|
||||
bool Exists() const;
|
||||
|
||||
const char* Name() const;
|
||||
uint32 Index() const;
|
||||
uint32 Flags() const;
|
||||
uint32 MTU() const;
|
||||
uint32 Type() const;
|
||||
@@ -66,10 +75,13 @@ public:
|
||||
status_t SetMTU(uint32 mtu);
|
||||
|
||||
int32 CountAddresses() const;
|
||||
BNetworkInterfaceAddress* AddressAt(int32 index);
|
||||
status_t GetAddressAt(int32 index,
|
||||
BNetworkInterfaceAddress& address);
|
||||
|
||||
status_t AddAddress(
|
||||
const BNetworkInterfaceAddress& address);
|
||||
status_t SetAddress(
|
||||
const BNetworkInterfaceAddress& address);
|
||||
status_t RemoveAddress(
|
||||
const BNetworkInterfaceAddress& address);
|
||||
status_t RemoveAddressAt(int32 index);
|
||||
@@ -78,7 +90,6 @@ public:
|
||||
|
||||
private:
|
||||
char fName[IF_NAMESIZE];
|
||||
uint32 fIndex;
|
||||
BList fAddresses;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define _NETWORK_ROSTER_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <Locker.h>
|
||||
|
||||
|
||||
class BMessenger;
|
||||
@@ -17,14 +17,14 @@ class BNetworkRoster {
|
||||
public:
|
||||
static BNetworkRoster& Default();
|
||||
|
||||
int32 CountInterfaces();
|
||||
BNetworkInterface* InterfaceAt(int32 index);
|
||||
size_t CountInterfaces() const;
|
||||
status_t GetNextInterface(uint32* cookie,
|
||||
BNetworkInterface& interface) const;
|
||||
|
||||
status_t AddInterface(
|
||||
const BNetworkInterface& interface);
|
||||
status_t RemoveInterface(
|
||||
const BNetworkInterface& interface);
|
||||
status_t RemoveInterfaceAt(int32 index);
|
||||
|
||||
status_t StartWatching(const BMessenger& target,
|
||||
uint32 eventMask);
|
||||
@@ -33,6 +33,9 @@ public:
|
||||
private:
|
||||
BNetworkRoster();
|
||||
~BNetworkRoster();
|
||||
|
||||
private:
|
||||
static BNetworkRoster sDefault;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
SubDir HAIKU_TOP src kits network libnetapi ;
|
||||
|
||||
UsePrivateHeaders net ;
|
||||
UsePrivateHeaders net shared ;
|
||||
|
||||
SharedLibrary libbnetapi.so :
|
||||
init.cpp
|
||||
|
||||
@@ -6,3 +6,972 @@
|
||||
|
||||
#include <NetworkAddress.h>
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <NetworkInterface.h>
|
||||
#include <NetworkRoster.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
|
||||
static bool
|
||||
strip_port(BString& host, BString& port)
|
||||
{
|
||||
int32 separator = host.FindFirst(':');
|
||||
if (separator != -1) {
|
||||
// looks like there is a port
|
||||
host.CopyInto(port, separator + 1, -1);
|
||||
host.Truncate(separator);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
resolve_address(int family, const char* host, const char* port,
|
||||
int type, sockaddr_storage& address)
|
||||
{
|
||||
addrinfo hint = {0};
|
||||
hint.ai_family = family;
|
||||
hint.ai_socktype = type;
|
||||
hint.ai_protocol = 0;
|
||||
|
||||
if (host == NULL && port == NULL) {
|
||||
port = "0";
|
||||
hint.ai_flags = AI_PASSIVE;
|
||||
}
|
||||
|
||||
addrinfo* info;
|
||||
int status = getaddrinfo(host, port, &hint, &info);
|
||||
if (status != 0) {
|
||||
// TODO: improve error reporting
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
bool foundAddress = false;
|
||||
|
||||
if (family == AF_UNSPEC) {
|
||||
// Prefer IPv6 addresses over IPv4 addresses
|
||||
|
||||
for (const addrinfo* next = info; next != NULL; next = next->ai_next) {
|
||||
if (next->ai_family == AF_INET6) {
|
||||
memcpy(&address, next->ai_addr, next->ai_addrlen);
|
||||
foundAddress = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundAddress) {
|
||||
// No preferred, or no IPv6 address found, just take the first one
|
||||
// that works
|
||||
memcpy(&address, info->ai_addr, info->ai_addrlen);
|
||||
}
|
||||
|
||||
freeaddrinfo(info);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(int family, const char* host, uint16 port)
|
||||
{
|
||||
SetTo(family, host, port);
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(const char* host, uint16 port)
|
||||
{
|
||||
SetTo(host, port);
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(const sockaddr& address)
|
||||
{
|
||||
SetTo(address);
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(const sockaddr_storage& address)
|
||||
{
|
||||
SetTo(address);
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(const sockaddr_in& address)
|
||||
{
|
||||
SetTo(address);
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(const sockaddr_in6& address)
|
||||
{
|
||||
SetTo(address);
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(const sockaddr_dl& address)
|
||||
{
|
||||
SetTo(address);
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(const in_addr_t address)
|
||||
{
|
||||
SetTo(address);
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(const in6_addr* address)
|
||||
{
|
||||
SetTo(address);
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(const BNetworkAddress& other)
|
||||
:
|
||||
fAddress(other.fAddress),
|
||||
fStatus(other.fStatus)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress(BMessage* archive)
|
||||
{
|
||||
// TODO: implement me
|
||||
fStatus = B_NO_INIT;
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::BNetworkAddress()
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress::~BNetworkAddress()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::InitCheck() const
|
||||
{
|
||||
return fStatus;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::Unset()
|
||||
{
|
||||
fAddress.ss_family = AF_UNSPEC;
|
||||
fAddress.ss_len = 2;
|
||||
fStatus = B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::SetTo(int family, const char* host, uint16 port)
|
||||
{
|
||||
// Check if the address contains a port
|
||||
|
||||
BString hostAddress(host);
|
||||
|
||||
BString portString;
|
||||
if (strip_port(hostAddress, portString) && port == 0)
|
||||
port = strtoul(portString.String(), NULL, 0);
|
||||
|
||||
// Resolve address
|
||||
|
||||
memset(&fAddress, 0, sizeof(sockaddr_storage));
|
||||
fAddress.ss_family = family;
|
||||
|
||||
if (host != NULL) {
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
{
|
||||
hostent* server = gethostbyname(hostAddress.String());
|
||||
if (server == NULL)
|
||||
return errno;
|
||||
|
||||
struct sockaddr_in& address = (sockaddr_in&)fAddress;
|
||||
address.sin_port = htons(port);
|
||||
address.sin_addr.s_addr = *(in_addr_t*)server->h_addr_list[0];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
fStatus = resolve_address(family, host, "0", 0, fAddress);
|
||||
if (fStatus != B_OK)
|
||||
return fStatus;
|
||||
|
||||
if (family == AF_INET6) {
|
||||
struct sockaddr_in6& address = (sockaddr_in6&)fAddress;
|
||||
address.sin6_port = htons(port);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in& address = (sockaddr_in&)fAddress;
|
||||
address.sin_port = htons(port);
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
break;
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6& address = (sockaddr_in6&)fAddress;
|
||||
address.sin6_port = htons(port);
|
||||
address.sin6_addr = in6addr_any;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return fStatus = B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::SetTo(const char* host, uint16 port)
|
||||
{
|
||||
// Check if the address contains a port
|
||||
|
||||
BString hostAddress(host);
|
||||
|
||||
BString portString;
|
||||
strip_port(hostAddress, portString);
|
||||
|
||||
// Resolve address
|
||||
|
||||
memset(&fAddress, 0, sizeof(sockaddr_storage));
|
||||
|
||||
fStatus = resolve_address(AF_UNSPEC,
|
||||
host != NULL ? hostAddress.String() : NULL,
|
||||
portString.Length() == 0 ? NULL : portString.String(), 0, fAddress);
|
||||
if (fStatus != B_OK)
|
||||
return fStatus;
|
||||
|
||||
// Set port if specified separately
|
||||
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in& address = (sockaddr_in&)fAddress;
|
||||
if (address.sin_port == 0)
|
||||
address.sin_port = htons(port);
|
||||
break;
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6& address = (sockaddr_in6&)fAddress;
|
||||
if (address.sin6_port == 0)
|
||||
address.sin6_port = htons(port);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetTo(const sockaddr& address)
|
||||
{
|
||||
if (address.sa_family == AF_UNSPEC) {
|
||||
Unset();
|
||||
return;
|
||||
}
|
||||
|
||||
size_t length = min_c(sizeof(sockaddr_storage), address.sa_len);
|
||||
switch (address.sa_family) {
|
||||
case AF_INET:
|
||||
length = sizeof(sockaddr_in);
|
||||
break;
|
||||
case AF_INET6:
|
||||
length = sizeof(sockaddr_in6);
|
||||
break;
|
||||
case AF_LINK:
|
||||
length = sizeof(sockaddr_dl);
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(&fAddress, &address, length);
|
||||
fAddress.ss_len = length;
|
||||
fStatus = B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetTo(const sockaddr_storage& address)
|
||||
{
|
||||
SetTo((sockaddr&)address);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetTo(const sockaddr_in& address)
|
||||
{
|
||||
SetTo((sockaddr&)address);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetTo(const sockaddr_in6& address)
|
||||
{
|
||||
SetTo((sockaddr&)address);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetTo(const sockaddr_dl& address)
|
||||
{
|
||||
SetTo((sockaddr&)address);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetTo(const in_addr_t inetAddress)
|
||||
{
|
||||
sockaddr_in& address = (sockaddr_in&)fAddress;
|
||||
memset(&fAddress, 0, sizeof(sockaddr_storage));
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_len = sizeof(sockaddr_in);
|
||||
address.sin_addr.s_addr = inetAddress;
|
||||
fStatus = B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetTo(const in6_addr* inet6Address)
|
||||
{
|
||||
sockaddr_in6& address = (sockaddr_in6&)fAddress;
|
||||
memset(&fAddress, 0, sizeof(sockaddr_storage));
|
||||
|
||||
address.sin6_family = AF_INET6;
|
||||
address.sin6_len = sizeof(sockaddr_in6);
|
||||
memcpy(address.sin6_addr.s6_addr, inet6Address,
|
||||
sizeof(address.sin6_addr.s6_addr));
|
||||
fStatus = B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetTo(const BNetworkAddress& other)
|
||||
{
|
||||
fAddress = other.fAddress;
|
||||
fStatus = other.fStatus;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::SetToBroadcast(int family, uint16 port)
|
||||
{
|
||||
if (family != AF_INET)
|
||||
return fStatus = B_NOT_SUPPORTED;
|
||||
|
||||
memset(&fAddress, 0, sizeof(sockaddr_storage));
|
||||
fAddress.ss_family = family;
|
||||
((sockaddr_in&)fAddress).sin_addr.s_addr = INADDR_BROADCAST;
|
||||
|
||||
SetPort(port);
|
||||
return fStatus = B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::SetToLocal()
|
||||
{
|
||||
// TODO: choose a local address from the network interfaces
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::SetToLoopback()
|
||||
{
|
||||
return SetTo("localhost");
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::SetToMask(int family, uint32 prefixLength)
|
||||
{
|
||||
// TODO: implement SetToMask()
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::SetToWildcard(int family)
|
||||
{
|
||||
return SetTo(family, NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetPort(uint16 port)
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET:
|
||||
((sockaddr_in&)fAddress).sin_port = htons(port);
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
((sockaddr_in6&)fAddress).sin6_port = htons(port);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetToLinkLevel(uint8* address, size_t length)
|
||||
{
|
||||
// TODO: implement me!
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetToLinkLevel(const char* name)
|
||||
{
|
||||
// TODO: implement me!
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetToLinkLevel(uint32 index)
|
||||
{
|
||||
// TODO: implement me!
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetLinkLevelIndex(uint32 index)
|
||||
{
|
||||
// TODO: implement me!
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetLinkLevelType(uint32 type)
|
||||
{
|
||||
// TODO: implement me!
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkAddress::SetLinkLevelFrameType(uint32 frameType)
|
||||
{
|
||||
// TODO: implement me!
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
BNetworkAddress::Family() const
|
||||
{
|
||||
return fAddress.ss_family;
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
BNetworkAddress::Port() const
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET:
|
||||
return ntohs(((sockaddr_in&)fAddress).sin_port);
|
||||
|
||||
case AF_INET6:
|
||||
return ntohs(((sockaddr_in6&)fAddress).sin6_port);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
BNetworkAddress::Length() const
|
||||
{
|
||||
return fAddress.ss_len;
|
||||
}
|
||||
|
||||
|
||||
const sockaddr&
|
||||
BNetworkAddress::SockAddr() const
|
||||
{
|
||||
return (const sockaddr&)fAddress;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsEmpty() const
|
||||
{
|
||||
return fAddress.ss_len == 0 || fAddress.ss_family == AF_UNSPEC;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsWildcard() const
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET:
|
||||
return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_ANY;
|
||||
|
||||
case AF_INET6:
|
||||
return !memcmp(&((sockaddr_in6&)fAddress).sin6_addr, &in6addr_any,
|
||||
sizeof(in6_addr));
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsBroadcast() const
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET:
|
||||
return ((sockaddr_in&)fAddress).sin_addr.s_addr == INADDR_BROADCAST;
|
||||
|
||||
case AF_INET6:
|
||||
// There is no broadcast in IPv6, only multicast/anycast
|
||||
return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsMulticast() const
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET:
|
||||
return IN_MULTICAST(((sockaddr_in&)fAddress).sin_addr.s_addr);
|
||||
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_MULTICAST(&((sockaddr_in6&)fAddress).sin6_addr);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsMulticastGlobal() const
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_MC_GLOBAL(&((sockaddr_in6&)fAddress).sin6_addr);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsMulticastNodeLocal() const
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_MC_NODELOCAL(
|
||||
&((sockaddr_in6&)fAddress).sin6_addr);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsMulticastLinkLocal() const
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_MC_LINKLOCAL(
|
||||
&((sockaddr_in6&)fAddress).sin6_addr);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsMulticastSiteLocal() const
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_MC_SITELOCAL(
|
||||
&((sockaddr_in6&)fAddress).sin6_addr);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsMulticastOrgLocal() const
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_MC_ORGLOCAL(
|
||||
&((sockaddr_in6&)fAddress).sin6_addr);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsLinkLocal() const
|
||||
{
|
||||
// TODO: ipv4
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsSiteLocal() const
|
||||
{
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_SITELOCAL(&((sockaddr_in6&)fAddress).sin6_addr);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::IsLocal() const
|
||||
{
|
||||
BNetworkRoster& roster = BNetworkRoster::Default();
|
||||
|
||||
BNetworkInterface interface;
|
||||
uint32 cookie = 0;
|
||||
|
||||
while (roster.GetNextInterface(&cookie, interface) == B_OK) {
|
||||
int32 count = interface.CountAddresses();
|
||||
for (int32 j = 0; j < count; j++) {
|
||||
BNetworkInterfaceAddress address;
|
||||
if (interface.GetAddressAt(j, address) != B_OK)
|
||||
break;
|
||||
|
||||
if (Equals(address.Address(), false))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BNetworkAddress::LinkLevelIndex() const
|
||||
{
|
||||
return ((sockaddr_dl&)fAddress).sdl_index;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
BNetworkAddress::LinkLevelInterface() const
|
||||
{
|
||||
sockaddr_dl& address = (sockaddr_dl&)fAddress;
|
||||
if (address.sdl_nlen == 0)
|
||||
return "";
|
||||
|
||||
BString name;
|
||||
name.SetTo((const char*)address.sdl_data, address.sdl_nlen);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BNetworkAddress::LinkLevelType() const
|
||||
{
|
||||
return ((sockaddr_dl&)fAddress).sdl_type;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BNetworkAddress::LinkLevelFrameType() const
|
||||
{
|
||||
return ((sockaddr_dl&)fAddress).sdl_e_type;
|
||||
}
|
||||
|
||||
|
||||
uint8*
|
||||
BNetworkAddress::LinkLevelAddress() const
|
||||
{
|
||||
return LLADDR(&(sockaddr_dl&)fAddress);
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
BNetworkAddress::LinkLevelAddressLength() const
|
||||
{
|
||||
return ((sockaddr_dl&)fAddress).sdl_alen;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::ResolveForDestination(const BNetworkAddress& destination)
|
||||
{
|
||||
if (!IsWildcard())
|
||||
return B_OK;
|
||||
if (destination.fAddress.ss_family != fAddress.ss_family)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
char buffer[2048];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
route_entry* route = (route_entry*)buffer;
|
||||
route->destination = (sockaddr*)&destination.fAddress;
|
||||
|
||||
int socket = ::socket(fAddress.ss_family, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
return errno;
|
||||
|
||||
if (ioctl(socket, SIOCGETRT, route, sizeof(buffer)) != 0) {
|
||||
close(socket);
|
||||
return errno;
|
||||
}
|
||||
|
||||
uint16 port = Port();
|
||||
memcpy(&fAddress, route->source, sizeof(sockaddr_storage));
|
||||
SetPort(port);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::ResolveTo(const BNetworkAddress& address)
|
||||
{
|
||||
if (!IsWildcard())
|
||||
return B_OK;
|
||||
if (address.fAddress.ss_family != fAddress.ss_family)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
uint16 port = Port();
|
||||
*this = address;
|
||||
SetPort(port);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
BNetworkAddress::ToString(bool includePort) const
|
||||
{
|
||||
char buffer[128];
|
||||
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET:
|
||||
inet_ntop(AF_INET, &((sockaddr_in&)fAddress).sin_addr, buffer,
|
||||
sizeof(buffer));
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
inet_ntop(AF_INET6, &((sockaddr_in6&)fAddress).sin6_addr,
|
||||
buffer, sizeof(buffer));
|
||||
break;
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
BString address = buffer;
|
||||
if (includePort && Port() != 0) {
|
||||
if (fAddress.ss_family == AF_INET6) {
|
||||
address = "[";
|
||||
address += buffer;
|
||||
address += "]";
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), ":%u", Port());
|
||||
address += buffer;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
BNetworkAddress::HostName() const
|
||||
{
|
||||
// TODO: implement host name lookup
|
||||
return ToString(false);
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
BNetworkAddress::PortName() const
|
||||
{
|
||||
// TODO: implement service lookup
|
||||
BString portName;
|
||||
portName << Port();
|
||||
return portName;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkAddress::Archive(BMessage* into, bool deep = true) const
|
||||
{
|
||||
// TODO: implement me!
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ BArchivable*
|
||||
BNetworkAddress::Instantiate(BMessage* archive)
|
||||
{
|
||||
if (archive != NULL)
|
||||
return new BNetworkAddress(archive);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::Equals(const BNetworkAddress& other, bool includePort) const
|
||||
{
|
||||
if (IsEmpty() && other.IsEmpty())
|
||||
return true;
|
||||
|
||||
if (Family() != other.Family()
|
||||
|| (includePort && Port() != other.Port()))
|
||||
return false;
|
||||
|
||||
switch (fAddress.ss_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
sockaddr_in& address = (sockaddr_in&)fAddress;
|
||||
sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress;
|
||||
return memcmp(&address.sin_addr, &otherAddress.sin_addr,
|
||||
sizeof(address.sin_addr)) == 0;
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
sockaddr_in6& address = (sockaddr_in6&)fAddress;
|
||||
sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress;
|
||||
return memcmp(&address.sin6_addr, &otherAddress.sin6_addr,
|
||||
sizeof(address.sin6_addr)) == 0;
|
||||
}
|
||||
|
||||
default:
|
||||
if (fAddress.ss_len != other.fAddress.ss_len)
|
||||
return false;
|
||||
|
||||
return memcmp(&fAddress, &other.fAddress, fAddress.ss_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BNetworkAddress&
|
||||
BNetworkAddress::operator=(const BNetworkAddress& other)
|
||||
{
|
||||
memcpy(&fAddress, &other.fAddress, other.fAddress.ss_len);
|
||||
fStatus = other.fStatus;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::operator==(const BNetworkAddress& other) const
|
||||
{
|
||||
return Equals(other);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::operator!=(const BNetworkAddress& other) const
|
||||
{
|
||||
return !Equals(other);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkAddress::operator<(const BNetworkAddress& other) const
|
||||
{
|
||||
if (Family() < other.Family())
|
||||
return true;
|
||||
if (Family() > other.Family())
|
||||
return false;
|
||||
|
||||
int compare;
|
||||
|
||||
switch (fAddress.ss_family) {
|
||||
default:
|
||||
case AF_INET:
|
||||
{
|
||||
sockaddr_in& address = (sockaddr_in&)fAddress;
|
||||
sockaddr_in& otherAddress = (sockaddr_in&)other.fAddress;
|
||||
compare = memcmp(&address.sin_addr, &otherAddress.sin_addr,
|
||||
sizeof(address.sin_addr));
|
||||
break;
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
sockaddr_in6& address = (sockaddr_in6&)fAddress;
|
||||
sockaddr_in6& otherAddress = (sockaddr_in6&)other.fAddress;
|
||||
compare = memcmp(&address.sin6_addr, &otherAddress.sin6_addr,
|
||||
sizeof(address.sin6_addr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (compare < 0)
|
||||
return true;
|
||||
if (compare > 0)
|
||||
return false;
|
||||
|
||||
return Port() < other.Port();
|
||||
}
|
||||
|
||||
@@ -6,3 +6,339 @@
|
||||
|
||||
#include <NetworkInterface.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
|
||||
static status_t
|
||||
do_ifaliasreq(const char* name, int32 option, BNetworkInterfaceAddress& address,
|
||||
bool readBack = false)
|
||||
{
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
return errno;
|
||||
|
||||
DescriptorCloser closer(socket);
|
||||
|
||||
ifaliasreq request;
|
||||
strlcpy(request.ifra_name, name, IF_NAMESIZE);
|
||||
request.ifra_index = address.Index();
|
||||
request.ifra_flags = address.Flags();
|
||||
|
||||
memcpy(&request.ifra_addr, &address.Address().SockAddr(),
|
||||
address.Address().Length());
|
||||
memcpy(&request.ifra_mask, &address.Mask().SockAddr(),
|
||||
address.Mask().Length());
|
||||
memcpy(&request.ifra_broadaddr, &address.Broadcast().SockAddr(),
|
||||
address.Broadcast().Length());
|
||||
|
||||
if (ioctl(socket, option, &request, sizeof(struct ifaliasreq)) < 0)
|
||||
return errno;
|
||||
|
||||
if (readBack) {
|
||||
address.SetFlags(request.ifra_flags);
|
||||
address.Address().SetTo(request.ifra_addr);
|
||||
address.Mask().SetTo(request.ifra_mask);
|
||||
address.Broadcast().SetTo(request.ifra_broadaddr);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
do_ifaliasreq(const char* name, int32 option,
|
||||
const BNetworkInterfaceAddress& address)
|
||||
{
|
||||
return do_ifaliasreq(name, option,
|
||||
const_cast<BNetworkInterfaceAddress&>(address));
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
do_request(ifreq& request, const char* name, int option)
|
||||
{
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
return errno;
|
||||
|
||||
DescriptorCloser closer(socket);
|
||||
|
||||
strlcpy(request.ifr_name, name, IF_NAMESIZE);
|
||||
|
||||
if (ioctl(socket, option, &request, sizeof(struct ifreq)) < 0)
|
||||
return errno;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BNetworkInterfaceAddress::BNetworkInterfaceAddress()
|
||||
:
|
||||
fIndex(0),
|
||||
fFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BNetworkInterfaceAddress::~BNetworkInterfaceAddress()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterfaceAddress::SetTo(BNetworkInterface& interface, int32 index)
|
||||
{
|
||||
fIndex = index;
|
||||
return do_ifaliasreq(interface.Name(), B_SOCKET_GET_ALIAS, *this, true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkInterfaceAddress::SetAddress(BNetworkAddress& address)
|
||||
{
|
||||
fAddress = address;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkInterfaceAddress::SetMask(BNetworkAddress& mask)
|
||||
{
|
||||
fMask = mask;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkInterfaceAddress::SetBroadcast(BNetworkAddress& broadcast)
|
||||
{
|
||||
fBroadcast = broadcast;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkInterfaceAddress::SetFlags(uint32 flags)
|
||||
{
|
||||
fFlags = flags;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BNetworkInterface::BNetworkInterface()
|
||||
{
|
||||
Unset();
|
||||
}
|
||||
|
||||
|
||||
BNetworkInterface::BNetworkInterface(const char* name)
|
||||
{
|
||||
SetTo(name);
|
||||
}
|
||||
|
||||
|
||||
BNetworkInterface::BNetworkInterface(uint32 index)
|
||||
{
|
||||
SetTo(index);
|
||||
}
|
||||
|
||||
|
||||
BNetworkInterface::~BNetworkInterface()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkInterface::Unset()
|
||||
{
|
||||
fName[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkInterface::SetTo(const char* name)
|
||||
{
|
||||
strlcpy(fName, name, IF_NAMESIZE);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterface::SetTo(uint32 index)
|
||||
{
|
||||
ifreq request;
|
||||
request.ifr_index = index;
|
||||
|
||||
status_t status = do_request(request, "", SIOCGIFNAME);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
strlcpy(fName, request.ifr_name, IF_NAMESIZE);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkInterface::Exists() const
|
||||
{
|
||||
ifreq request;
|
||||
return do_request(request, Name(), SIOCGIFINDEX) == B_OK;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
BNetworkInterface::Name() const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BNetworkInterface::Flags() const
|
||||
{
|
||||
ifreq request;
|
||||
if (do_request(request, Name(), SIOCGIFFLAGS) != B_OK)
|
||||
return 0;
|
||||
|
||||
return request.ifr_flags;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BNetworkInterface::MTU() const
|
||||
{
|
||||
ifreq request;
|
||||
if (do_request(request, Name(), SIOCGIFMTU) != B_OK)
|
||||
return 0;
|
||||
|
||||
return request.ifr_mtu;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BNetworkInterface::Type() const
|
||||
{
|
||||
ifreq request;
|
||||
if (do_request(request, Name(), SIOCGIFTYPE) != B_OK)
|
||||
return 0;
|
||||
|
||||
return request.ifr_type;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterface::GetStats(ifreq_stats& stats)
|
||||
{
|
||||
ifreq request;
|
||||
status_t status = do_request(request, Name(), SIOCGIFSTATS);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
memcpy(&stats, &request.ifr_stats, sizeof(ifreq_stats));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BNetworkInterface::HasLink() const
|
||||
{
|
||||
return (Flags() & IFF_LINK) != 0;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterface::SetFlags(uint32 flags)
|
||||
{
|
||||
ifreq request;
|
||||
request.ifr_flags = flags;
|
||||
return do_request(request, Name(), SIOCSIFFLAGS);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterface::SetMTU(uint32 mtu)
|
||||
{
|
||||
ifreq request;
|
||||
request.ifr_mtu = mtu;
|
||||
return do_request(request, Name(), SIOCSIFMTU);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BNetworkInterface::CountAddresses() const
|
||||
{
|
||||
ifreq request;
|
||||
if (do_request(request, Name(), B_SOCKET_COUNT_ALIASES) != B_OK)
|
||||
return 0;
|
||||
|
||||
return request.ifr_count;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterface::GetAddressAt(int32 index, BNetworkInterfaceAddress& address)
|
||||
{
|
||||
return address.SetTo(*this, index);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterface::AddAddress(const BNetworkInterfaceAddress& address)
|
||||
{
|
||||
return do_ifaliasreq(Name(), B_SOCKET_ADD_ALIAS, address);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterface::SetAddress(const BNetworkInterfaceAddress& address)
|
||||
{
|
||||
return do_ifaliasreq(Name(), B_SOCKET_SET_ALIAS, address);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterface::RemoveAddress(const BNetworkInterfaceAddress& address)
|
||||
{
|
||||
ifreq request;
|
||||
memcpy(&request.ifr_addr, &address.Address().SockAddr(),
|
||||
address.Address().Length());
|
||||
|
||||
return do_request(request, Name(), B_SOCKET_REMOVE_ALIAS);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterface::RemoveAddressAt(int32 index)
|
||||
{
|
||||
BNetworkInterfaceAddress address;
|
||||
status_t status = GetAddressAt(index, address);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
return RemoveAddress(address);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkInterface::GetHardwareAddress(BNetworkAddress& address)
|
||||
{
|
||||
int socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
return errno;
|
||||
|
||||
DescriptorCloser closer(socket);
|
||||
|
||||
ifreq request;
|
||||
strlcpy(request.ifr_name, Name(), IF_NAMESIZE);
|
||||
|
||||
if (ioctl(socket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0)
|
||||
return errno;
|
||||
|
||||
address.SetTo(request.ifr_addr);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -6,3 +6,131 @@
|
||||
|
||||
#include <NetworkRoster.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
#include <NetworkInterface.h>
|
||||
|
||||
#include <net_notifications.h>
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
|
||||
BNetworkRoster BNetworkRoster::sDefault;
|
||||
|
||||
|
||||
/*static*/ BNetworkRoster&
|
||||
BNetworkRoster::Default()
|
||||
{
|
||||
return sDefault;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
BNetworkRoster::CountInterfaces() const
|
||||
{
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
return 0;
|
||||
|
||||
DescriptorCloser closer(socket);
|
||||
|
||||
ifconf config;
|
||||
config.ifc_len = sizeof(config.ifc_value);
|
||||
if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) != 0)
|
||||
return 0;
|
||||
|
||||
return (size_t)config.ifc_value;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkRoster::GetNextInterface(uint32* cookie,
|
||||
BNetworkInterface& interface) const
|
||||
{
|
||||
// TODO: think about caching the interfaces!
|
||||
|
||||
// get a list of all interfaces
|
||||
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
return errno;
|
||||
|
||||
DescriptorCloser closer(socket);
|
||||
|
||||
ifconf config;
|
||||
config.ifc_len = sizeof(config.ifc_value);
|
||||
if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
|
||||
return errno;
|
||||
|
||||
size_t count = (size_t)config.ifc_value;
|
||||
if (count == 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
char* buffer = (char*)malloc(count * sizeof(struct ifreq));
|
||||
if (buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
MemoryDeleter deleter(buffer);
|
||||
|
||||
config.ifc_len = count * sizeof(struct ifreq);
|
||||
config.ifc_buf = buffer;
|
||||
if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
|
||||
return errno;
|
||||
|
||||
ifreq* interfaces = (ifreq*)buffer;
|
||||
ifreq* end = (ifreq*)(buffer + config.ifc_len);
|
||||
|
||||
for (uint32 i = 0; interfaces < end; i++) {
|
||||
interface.SetTo(interfaces[0].ifr_name);
|
||||
if (i == *cookie)
|
||||
return B_OK;
|
||||
|
||||
interfaces = (ifreq*)((uint8*)interfaces
|
||||
+ _SIZEOF_ADDR_IFREQ(interfaces[0]));
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkRoster::AddInterface(const BNetworkInterface& interface)
|
||||
{
|
||||
// TODO: implement me
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkRoster::RemoveInterface(const BNetworkInterface& interface)
|
||||
{
|
||||
// TODO: implement me
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetworkRoster::StartWatching(const BMessenger& target, uint32 eventMask)
|
||||
{
|
||||
return start_watching_network(eventMask, target);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BNetworkRoster::StopWatching(const BMessenger& target)
|
||||
{
|
||||
stop_watching_network(target);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - private
|
||||
|
||||
|
||||
BNetworkRoster::BNetworkRoster()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BNetworkRoster::~BNetworkRoster()
|
||||
{
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user