* Now uses the new network API instead of directly using socket ioctls.
This makes the code much cleaner and simpler. * Completely untested, though (will do that next). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39595 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
01308f219b
commit
af0745618f
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@ -17,7 +17,8 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
#include <net_notifications.h>
|
||||
#include <NetworkInterface.h>
|
||||
#include <NetworkNotifications.h>
|
||||
|
||||
#include "DHCPClient.h"
|
||||
#include "NetServer.h"
|
||||
@ -57,20 +58,11 @@ AutoconfigLooper::_RemoveClient()
|
||||
void
|
||||
AutoconfigLooper::_Configure()
|
||||
{
|
||||
ifreq request;
|
||||
if (!prepare_request(request, fDevice.String()))
|
||||
return;
|
||||
|
||||
// set IFF_CONFIGURING flag on interface
|
||||
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
return;
|
||||
|
||||
if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0) {
|
||||
request.ifr_flags |= IFF_CONFIGURING;
|
||||
ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq));
|
||||
}
|
||||
BNetworkInterface interface(fDevice.String());
|
||||
int32 flags = interface.Flags() & ~IFF_AUTO_CONFIGURED;
|
||||
interface.SetFlags(flags | IFF_CONFIGURING);
|
||||
|
||||
// remove current handler
|
||||
|
||||
@ -81,10 +73,8 @@ AutoconfigLooper::_Configure()
|
||||
fCurrentClient = new DHCPClient(fTarget, fDevice.String());
|
||||
AddHandler(fCurrentClient);
|
||||
|
||||
if (fCurrentClient->Initialize() == B_OK) {
|
||||
close(socket);
|
||||
if (fCurrentClient->Initialize() == B_OK)
|
||||
return;
|
||||
}
|
||||
|
||||
_RemoveClient();
|
||||
|
||||
@ -94,23 +84,20 @@ AutoconfigLooper::_Configure()
|
||||
// TODO: have a look at zeroconf
|
||||
// TODO: this could also be done add-on based
|
||||
|
||||
if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0
|
||||
&& (request.ifr_flags & IFF_CONFIGURING) == 0) {
|
||||
if ((interface.Flags() & IFF_CONFIGURING) == 0) {
|
||||
// Someone else configured the interface in the mean time
|
||||
close(socket);
|
||||
return;
|
||||
}
|
||||
|
||||
close(socket);
|
||||
BMessage message(kMsgConfigureInterface);
|
||||
message.AddString("device", fDevice.String());
|
||||
message.AddBool("auto", true);
|
||||
|
||||
BMessage interface(kMsgConfigureInterface);
|
||||
interface.AddString("device", fDevice.String());
|
||||
interface.AddBool("auto", true);
|
||||
|
||||
uint8 mac[6];
|
||||
BNetworkAddress link;
|
||||
uint8 last = 56;
|
||||
if (get_mac_address(fDevice.String(), mac) == B_OK) {
|
||||
if (interface.GetHardwareAddress(link) == B_OK) {
|
||||
// choose IP address depending on the MAC address, if available
|
||||
uint8* mac = link.LinkLevelAddress();
|
||||
last = mac[0] ^ mac[1] ^ mac[2] ^ mac[3] ^ mac[4] ^ mac[5];
|
||||
if (last > 253)
|
||||
last = 253;
|
||||
@ -126,11 +113,11 @@ AutoconfigLooper::_Configure()
|
||||
snprintf(string, sizeof(string), "169.254.0.%u", last);
|
||||
|
||||
BMessage address;
|
||||
address.AddString("family", "inet");
|
||||
address.AddInt32("family", AF_INET);
|
||||
address.AddString("address", string);
|
||||
interface.AddMessage("address", &address);
|
||||
message.AddMessage("address", &address);
|
||||
|
||||
fTarget.SendMessage(&interface);
|
||||
fTarget.SendMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
#include <Message.h>
|
||||
#include <MessageRunner.h>
|
||||
#include <NetworkDevice.h>
|
||||
#include <NetworkInterface.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
@ -332,23 +334,24 @@ dhcp_message::FinishOptions(uint8* options)
|
||||
|
||||
|
||||
DHCPClient::DHCPClient(BMessenger target, const char* device)
|
||||
: AutoconfigClient("dhcp", target, device),
|
||||
:
|
||||
AutoconfigClient("dhcp", target, device),
|
||||
fConfiguration(kMsgConfigureInterface),
|
||||
fResolverConfiguration(kMsgConfigureResolver),
|
||||
fRunner(NULL),
|
||||
fServer(AF_INET, NULL, DHCP_SERVER_PORT),
|
||||
fLeaseTime(0)
|
||||
{
|
||||
fStartTime = system_time();
|
||||
fTransactionID = (uint32)fStartTime;
|
||||
|
||||
fStatus = get_mac_address(device, fMAC);
|
||||
if (fStatus < B_OK)
|
||||
BNetworkAddress link;
|
||||
BNetworkInterface interface(device);
|
||||
fStatus = interface.GetHardwareAddress(link);
|
||||
if (fStatus != B_OK)
|
||||
return;
|
||||
|
||||
memset(&fServer, 0, sizeof(struct sockaddr_in));
|
||||
fServer.sin_family = AF_INET;
|
||||
fServer.sin_len = sizeof(struct sockaddr_in);
|
||||
fServer.sin_port = htons(DHCP_SERVER_PORT);
|
||||
memcpy(fMAC, link.LinkLevelAddress(), sizeof(fMAC));
|
||||
|
||||
openlog_thread("DHCP", 0, LOG_DAEMON);
|
||||
}
|
||||
@ -393,12 +396,7 @@ DHCPClient::_Negotiate(dhcp_state state)
|
||||
if (socket < 0)
|
||||
return errno;
|
||||
|
||||
sockaddr_in local;
|
||||
memset(&local, 0, sizeof(struct sockaddr_in));
|
||||
local.sin_family = AF_INET;
|
||||
local.sin_len = sizeof(struct sockaddr_in);
|
||||
local.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
local.sin_addr.s_addr = INADDR_ANY;
|
||||
BNetworkAddress local(AF_INET, NULL, DHCP_CLIENT_PORT);
|
||||
|
||||
// Enable reusing the port . This is needed in case there is more
|
||||
// than 1 interface that needs to be configured. Note that the only reason
|
||||
@ -407,17 +405,13 @@ DHCPClient::_Negotiate(dhcp_state state)
|
||||
int option = 1;
|
||||
setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &option, sizeof(option));
|
||||
|
||||
if (bind(socket, (struct sockaddr*)&local, sizeof(local)) < 0) {
|
||||
if (bind(socket, local, local.Length()) < 0) {
|
||||
close(socket);
|
||||
return errno;
|
||||
}
|
||||
|
||||
sockaddr_in broadcast;
|
||||
memset(&broadcast, 0, sizeof(struct sockaddr_in));
|
||||
broadcast.sin_family = AF_INET;
|
||||
broadcast.sin_len = sizeof(struct sockaddr_in);
|
||||
broadcast.sin_port = htons(DHCP_SERVER_PORT);
|
||||
broadcast.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
BNetworkAddress broadcast;
|
||||
broadcast.SetToBroadcast(AF_INET, DHCP_SERVER_PORT);
|
||||
|
||||
option = 1;
|
||||
setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &option, sizeof(option));
|
||||
@ -425,19 +419,10 @@ DHCPClient::_Negotiate(dhcp_state state)
|
||||
if (state == INIT) {
|
||||
// The local interface does not have an address yet, bind the socket
|
||||
// to the device directly.
|
||||
int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
|
||||
if (linkSocket >= 0) {
|
||||
// we need to know the index of the device to be able to bind to it
|
||||
ifreq request;
|
||||
prepare_request(request, Device());
|
||||
if (ioctl(linkSocket, SIOCGIFINDEX, &request, sizeof(struct ifreq))
|
||||
== 0) {
|
||||
setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE,
|
||||
&request.ifr_index, sizeof(int));
|
||||
}
|
||||
BNetworkDevice device(Device());
|
||||
int index = device.Index();
|
||||
|
||||
close(linkSocket);
|
||||
}
|
||||
setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, &index, sizeof(int));
|
||||
}
|
||||
|
||||
bigtime_t previousLeaseTime = fLeaseTime;
|
||||
@ -558,7 +543,7 @@ DHCPClient::_Negotiate(dhcp_state state)
|
||||
status = Target().SendMessage(&fConfiguration, &reply);
|
||||
if (status == B_OK)
|
||||
status = reply.FindInt32("status", &fStatus);
|
||||
|
||||
|
||||
// configure resolver
|
||||
reply.MakeEmpty();
|
||||
status = Target().SendMessage(&fResolverConfiguration, &reply);
|
||||
@ -653,7 +638,7 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address,
|
||||
break;
|
||||
}
|
||||
case OPTION_SERVER_ADDRESS:
|
||||
fServer.sin_addr.s_addr = *(in_addr_t*)data;
|
||||
fServer.SetAddress(*(in_addr_t*)data);
|
||||
break;
|
||||
|
||||
case OPTION_ADDRESS_LEASE_TIME:
|
||||
@ -684,8 +669,8 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address,
|
||||
min_c(size + 1, sizeof(domain)));
|
||||
|
||||
syslog(LOG_INFO, "DHCP domain name: \"%s\"\n", domain);
|
||||
|
||||
resolverConfiguration.AddString("domain", domain);
|
||||
|
||||
resolverConfiguration.AddString("domain", domain);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -718,9 +703,10 @@ DHCPClient::_PrepareMessage(dhcp_message& message, dhcp_state state)
|
||||
case DHCP_RELEASE:
|
||||
{
|
||||
// add server identifier option
|
||||
const sockaddr_in& server = (sockaddr_in&)fServer.SockAddr();
|
||||
uint8* next = message.PrepareMessage(type);
|
||||
next = message.PutOption(next, OPTION_SERVER_ADDRESS,
|
||||
(uint32)fServer.sin_addr.s_addr);
|
||||
(uint32)server.sin_addr.s_addr);
|
||||
|
||||
// In RENEWAL or REBINDING state, we must set the client_address field, and not
|
||||
// use OPTION_REQUEST_IP_ADDRESS for DHCP_REQUEST messages
|
||||
@ -805,14 +791,13 @@ DHCPClient::_ToString(in_addr_t address) const
|
||||
|
||||
status_t
|
||||
DHCPClient::_SendMessage(int socket, dhcp_message& message,
|
||||
sockaddr_in& address) const
|
||||
const BNetworkAddress& address) const
|
||||
{
|
||||
syslog(LOG_DEBUG, "DHCP send message %u for %s\n", message.Type(),
|
||||
Device());
|
||||
|
||||
ssize_t bytesSent = sendto(socket, &message, message.Size(),
|
||||
address.sin_addr.s_addr == INADDR_BROADCAST ? MSG_BCAST : 0,
|
||||
(struct sockaddr*)&address, sizeof(sockaddr_in));
|
||||
address.IsBroadcast() ? MSG_BCAST : 0, address, address.Length());
|
||||
if (bytesSent < 0)
|
||||
return errno;
|
||||
|
||||
|
@ -13,9 +13,13 @@
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <NetworkAddress.h>
|
||||
|
||||
|
||||
class BMessageRunner;
|
||||
class dhcp_message;
|
||||
|
||||
|
||||
enum dhcp_state {
|
||||
INIT,
|
||||
REQUESTING,
|
||||
@ -44,7 +48,7 @@ private:
|
||||
void _PrepareMessage(dhcp_message& message,
|
||||
dhcp_state state);
|
||||
status_t _SendMessage(int socket, dhcp_message& message,
|
||||
sockaddr_in& address) const;
|
||||
const BNetworkAddress& address) const;
|
||||
dhcp_state _CurrentState() const;
|
||||
void _ResetTimeout(int socket, time_t& timeout,
|
||||
uint32& tries);
|
||||
@ -61,7 +65,7 @@ private:
|
||||
uint8 fMAC[6];
|
||||
uint32 fTransactionID;
|
||||
in_addr_t fAssignedAddress;
|
||||
sockaddr_in fServer;
|
||||
BNetworkAddress fServer;
|
||||
bigtime_t fStartTime;
|
||||
bigtime_t fRenewalTime;
|
||||
bigtime_t fRebindingTime;
|
||||
|
@ -16,7 +16,7 @@ Server net_server :
|
||||
DHCPClient.cpp
|
||||
Services.cpp
|
||||
|
||||
: be libnetwork.so $(TARGET_LIBSTDC++)
|
||||
: be network bnetapi $(TARGET_LIBSTDC++)
|
||||
# for PPP
|
||||
#libppp.a
|
||||
;
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include <Deskbar.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <NetworkInterface.h>
|
||||
#include <NetworkRoster.h>
|
||||
#include <Path.h>
|
||||
#include <PathMonitor.h>
|
||||
#include <Roster.h>
|
||||
@ -54,27 +56,24 @@ public:
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
bool _IsValidInterface(int socket, const char* name);
|
||||
void _RemoveInvalidInterfaces(int socket);
|
||||
status_t _RemoveInterface(int socket, const char* name);
|
||||
status_t _DisableInterface(int socket, const char* name);
|
||||
bool _TestForInterface(int socket, const char* name);
|
||||
status_t _ConfigureInterface(int socket,
|
||||
BMessage& interface,
|
||||
bool fromMessage = false);
|
||||
bool _IsValidInterface(BNetworkInterface& interface);
|
||||
void _RemoveInvalidInterfaces();
|
||||
status_t _RemoveInterface(const char* name);
|
||||
status_t _DisableInterface(const char* name);
|
||||
bool _TestForInterface(const char* name);
|
||||
status_t _ConfigureInterface(BMessage& interface);
|
||||
status_t _ConfigureResolver(
|
||||
BMessage& resolverConfiguration);
|
||||
bool _QuitLooperForDevice(const char* device);
|
||||
AutoconfigLooper* _LooperForDevice(const char* device);
|
||||
status_t _ConfigureDevice(int socket, const char* path);
|
||||
void _ConfigureDevices(int socket, const char* path,
|
||||
status_t _ConfigureDevice(const char* path);
|
||||
void _ConfigureDevices(const char* path,
|
||||
BMessage* suggestedInterface = NULL);
|
||||
void _ConfigureInterfaces(int socket,
|
||||
void _ConfigureInterfaces(
|
||||
BMessage* _missingDevice = NULL);
|
||||
void _BringUpInterfaces();
|
||||
void _StartServices();
|
||||
void _HandleDeviceMonitor(int socket,
|
||||
BMessage* message);
|
||||
void _HandleDeviceMonitor(BMessage* message);
|
||||
|
||||
private:
|
||||
Settings fSettings;
|
||||
@ -87,179 +86,89 @@ struct address_family {
|
||||
int family;
|
||||
const char* name;
|
||||
const char* identifiers[4];
|
||||
bool (*parse_address)(const char* string, sockaddr* _address);
|
||||
void (*set_any_address)(sockaddr* address);
|
||||
void (*set_port)(sockaddr* address, int32 port);
|
||||
};
|
||||
|
||||
|
||||
// AF_INET family
|
||||
static bool inet_parse_address(const char* string, sockaddr* address);
|
||||
static void inet_set_any_address(sockaddr* address);
|
||||
static void inet_set_port(sockaddr* address, int32 port);
|
||||
|
||||
static const address_family kFamilies[] = {
|
||||
{
|
||||
AF_INET,
|
||||
"inet",
|
||||
{"AF_INET", "inet", "ipv4", NULL},
|
||||
inet_parse_address,
|
||||
inet_set_any_address,
|
||||
inet_set_port
|
||||
},
|
||||
{ -1, NULL, {NULL}, NULL }
|
||||
{
|
||||
AF_INET6,
|
||||
"inet6",
|
||||
{"AF_INET6", "inet6", "ipv6", NULL},
|
||||
},
|
||||
{ -1, NULL, {NULL} }
|
||||
};
|
||||
|
||||
|
||||
static bool
|
||||
inet_parse_address(const char* string, sockaddr* _address)
|
||||
{
|
||||
in_addr inetAddress;
|
||||
|
||||
if (inet_aton(string, &inetAddress) != 1)
|
||||
return false;
|
||||
|
||||
sockaddr_in& address = *(sockaddr_in *)_address;
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_len = sizeof(struct sockaddr_in);
|
||||
address.sin_port = 0;
|
||||
address.sin_addr = inetAddress;
|
||||
memset(&address.sin_zero[0], 0, sizeof(address.sin_zero));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
inet_set_any_address(sockaddr* _address)
|
||||
{
|
||||
sockaddr_in& address = *(sockaddr_in*)_address;
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_len = sizeof(struct sockaddr_in);
|
||||
address.sin_port = 0;
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(&address.sin_zero[0], 0, sizeof(address.sin_zero));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
inet_set_port(sockaddr* _address, int32 port)
|
||||
{
|
||||
sockaddr_in& address = *(sockaddr_in*)_address;
|
||||
address.sin_port = port;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
bool
|
||||
get_family_index(const char* name, int32& familyIndex)
|
||||
int
|
||||
get_address_family(const char* argument)
|
||||
{
|
||||
for (int32 i = 0; kFamilies[i].family >= 0; i++) {
|
||||
for (int32 j = 0; kFamilies[i].identifiers[j]; j++) {
|
||||
if (!strcmp(name, kFamilies[i].identifiers[j])) {
|
||||
if (!strcmp(argument, kFamilies[i].identifiers[j])) {
|
||||
// found a match
|
||||
familyIndex = i;
|
||||
return true;
|
||||
return kFamilies[i].family;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// defaults to AF_INET
|
||||
familyIndex = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
family_at_index(int32 index)
|
||||
{
|
||||
return kFamilies[index].family;
|
||||
return AF_UNSPEC;
|
||||
}
|
||||
|
||||
|
||||
/*! Parses the \a argument as network \a address for the specified \a family.
|
||||
If \a family is \c AF_UNSPEC, \a family will be overwritten with the family
|
||||
of the successfully parsed address.
|
||||
*/
|
||||
bool
|
||||
parse_address(int32 familyIndex, const char* argument, struct sockaddr& address)
|
||||
parse_address(int32& family, const char* argument, BNetworkAddress& address)
|
||||
{
|
||||
if (argument == NULL)
|
||||
return false;
|
||||
|
||||
return kFamilies[familyIndex].parse_address(argument, &address);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
set_any_address(int32 familyIndex, struct sockaddr& address)
|
||||
{
|
||||
kFamilies[familyIndex].set_any_address(&address);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
set_port(int32 familyIndex, struct sockaddr& address, int32 port)
|
||||
{
|
||||
kFamilies[familyIndex].set_port(&address, port);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
prepare_request(ifreq& request, const char* name)
|
||||
{
|
||||
if (strlen(name) >= IF_NAMESIZE)
|
||||
status_t status = address.SetTo(family, argument, (uint16)0,
|
||||
B_NO_ADDRESS_RESOLUTION);
|
||||
if (status != B_OK)
|
||||
return false;
|
||||
|
||||
strcpy(request.ifr_name, name);
|
||||
if (family == AF_UNSPEC) {
|
||||
// Test if we support the resulting address family
|
||||
bool supported = false;
|
||||
|
||||
for (int32 i = 0; kFamilies[i].family >= 0; i++) {
|
||||
if (kFamilies[i].family == address.Family()) {
|
||||
supported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!supported)
|
||||
return false;
|
||||
|
||||
// Take over family from address
|
||||
family = address.Family();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
get_mac_address(const char* device, uint8* address)
|
||||
{
|
||||
int socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
return errno;
|
||||
|
||||
ifreq request;
|
||||
if (!prepare_request(request, device)) {
|
||||
close(socket);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (ioctl(socket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
|
||||
close(socket);
|
||||
return errno;
|
||||
}
|
||||
|
||||
close(socket);
|
||||
|
||||
sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr;
|
||||
if (link.sdl_type != IFT_ETHER)
|
||||
return B_BAD_TYPE;
|
||||
|
||||
if (link.sdl_alen == 0)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
uint8 *mac = (uint8 *)LLADDR(&link);
|
||||
memcpy(address, mac, 6);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
NetServer::NetServer(status_t& error)
|
||||
: BServer(kNetServerSignature, false, &error)
|
||||
:
|
||||
BServer(kNetServerSignature, false, &error)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
NetServer::~NetServer()
|
||||
{
|
||||
BPrivate::BPathMonitor::StopWatching("/dev/net", this);
|
||||
BPrivate::BPathMonitor::StopWatching("/dev/net", this);
|
||||
}
|
||||
|
||||
|
||||
@ -288,7 +197,7 @@ NetServer::ReadyToRun()
|
||||
fSettings.StartMonitoring(this);
|
||||
_BringUpInterfaces();
|
||||
_StartServices();
|
||||
|
||||
|
||||
BPrivate::BPathMonitor::StartWatching("/dev/net", B_ENTRY_CREATED
|
||||
| B_ENTRY_REMOVED | B_WATCH_FILES_ONLY | B_WATCH_RECURSIVELY, this);
|
||||
}
|
||||
@ -301,25 +210,13 @@ NetServer::MessageReceived(BMessage* message)
|
||||
case B_PATH_MONITOR:
|
||||
{
|
||||
fSettings.Update(message);
|
||||
|
||||
// we need a socket to talk to the networking stack
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
break;
|
||||
_HandleDeviceMonitor(socket, message);
|
||||
close(socket);
|
||||
_HandleDeviceMonitor(message);
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgInterfaceSettingsUpdated:
|
||||
{
|
||||
// we need a socket to talk to the networking stack
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
break;
|
||||
|
||||
_ConfigureInterfaces(socket);
|
||||
close(socket);
|
||||
_ConfigureInterfaces();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -334,32 +231,18 @@ NetServer::MessageReceived(BMessage* message)
|
||||
|
||||
case kMsgConfigureInterface:
|
||||
{
|
||||
#if 0
|
||||
if (!message->ReturnAddress().IsTargetLocal()) {
|
||||
// for now, we only accept this message from add-ons
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// we need a socket to talk to the networking stack
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
break;
|
||||
|
||||
status_t status = _ConfigureInterface(socket, *message, true);
|
||||
status_t status = _ConfigureInterface(*message);
|
||||
|
||||
BMessage reply(B_REPLY);
|
||||
reply.AddInt32("status", status);
|
||||
message->SendReply(&reply);
|
||||
|
||||
close(socket);
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgConfigureResolver:
|
||||
{
|
||||
status_t status = _ConfigureResolver(*message);
|
||||
|
||||
|
||||
BMessage reply(B_REPLY);
|
||||
reply.AddInt32("status", status);
|
||||
message->SendReply(&reply);
|
||||
@ -373,52 +256,24 @@ NetServer::MessageReceived(BMessage* message)
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Checks if an interface is valid, that is, if it has an address in any
|
||||
/*! Checks if an interface is valid, that is, if it has an address in any
|
||||
family, and, in case of ethernet, a hardware MAC address.
|
||||
*/
|
||||
bool
|
||||
NetServer::_IsValidInterface(int socket, const char* name)
|
||||
NetServer::_IsValidInterface(BNetworkInterface& interface)
|
||||
{
|
||||
ifreq request;
|
||||
if (!prepare_request(request, name))
|
||||
return B_ERROR;
|
||||
|
||||
// check if it has an address
|
||||
|
||||
int32 addresses = 0;
|
||||
|
||||
for (int32 i = 0; kFamilies[i].family >= 0; i++) {
|
||||
int familySocket = ::socket(kFamilies[i].family, SOCK_DGRAM, 0);
|
||||
if (familySocket < 0)
|
||||
continue;
|
||||
|
||||
if (ioctl(familySocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) == 0) {
|
||||
if (request.ifr_addr.sa_family == kFamilies[i].family)
|
||||
addresses++;
|
||||
}
|
||||
|
||||
close(familySocket);
|
||||
}
|
||||
|
||||
if (addresses == 0)
|
||||
if (interface.CountAddresses() == 0)
|
||||
return false;
|
||||
|
||||
// check if it has a hardware address, too, in case of ethernet
|
||||
|
||||
int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
|
||||
if (linkSocket < 0)
|
||||
BNetworkAddress link;
|
||||
if (interface.GetHardwareAddress(link) != B_OK)
|
||||
return false;
|
||||
|
||||
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
|
||||
close(linkSocket);
|
||||
return false;
|
||||
}
|
||||
|
||||
close(linkSocket);
|
||||
|
||||
sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr;
|
||||
if (link.sdl_type == IFT_ETHER && link.sdl_alen < 6)
|
||||
if (link.LinkLevelType() == IFT_ETHER && link.LinkLevelAddressLength() != 6)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -426,154 +281,82 @@ NetServer::_IsValidInterface(int socket, const char* name)
|
||||
|
||||
|
||||
void
|
||||
NetServer::_RemoveInvalidInterfaces(int socket)
|
||||
NetServer::_RemoveInvalidInterfaces()
|
||||
{
|
||||
// get a list of all interfaces
|
||||
BNetworkRoster& roster = BNetworkRoster::Default();
|
||||
BNetworkInterface interface;
|
||||
uint32 cookie = 0;
|
||||
|
||||
ifconf config;
|
||||
config.ifc_len = sizeof(config.ifc_value);
|
||||
if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
|
||||
return;
|
||||
|
||||
uint32 count = (uint32)config.ifc_value;
|
||||
if (count == 0) {
|
||||
// there are no interfaces yet
|
||||
return;
|
||||
}
|
||||
|
||||
void *buffer = malloc(count * sizeof(struct ifreq));
|
||||
if (buffer == NULL) {
|
||||
fprintf(stderr, "%s: Out of memory.\n", Name());
|
||||
return;
|
||||
}
|
||||
|
||||
config.ifc_len = count * sizeof(struct ifreq);
|
||||
config.ifc_buf = buffer;
|
||||
if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
ifreq *interface = (ifreq *)buffer;
|
||||
|
||||
for (uint32 i = 0; i < count; i++) {
|
||||
if (!_IsValidInterface(socket, interface->ifr_name)) {
|
||||
while (roster.GetNextInterface(&cookie, interface) == B_OK) {
|
||||
if (!_IsValidInterface(interface)) {
|
||||
// remove invalid interface
|
||||
_RemoveInterface(socket, interface->ifr_name);
|
||||
_RemoveInterface(interface.Name());
|
||||
}
|
||||
|
||||
interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
|
||||
+ interface->ifr_addr.sa_len);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NetServer::_TestForInterface(int socket, const char* name)
|
||||
NetServer::_TestForInterface(const char* name)
|
||||
{
|
||||
// get a list of all interfaces
|
||||
|
||||
ifconf config;
|
||||
config.ifc_len = sizeof(config.ifc_value);
|
||||
if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
|
||||
return false;
|
||||
|
||||
uint32 count = (uint32)config.ifc_value;
|
||||
if (count == 0) {
|
||||
// there are no interfaces yet
|
||||
return false;
|
||||
}
|
||||
|
||||
void *buffer = malloc(count * sizeof(struct ifreq));
|
||||
if (buffer == NULL) {
|
||||
fprintf(stderr, "%s: Out of memory.\n", Name());
|
||||
return false;
|
||||
}
|
||||
|
||||
config.ifc_len = count * sizeof(struct ifreq);
|
||||
config.ifc_buf = buffer;
|
||||
if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) {
|
||||
free(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
ifreq *interface = (ifreq *)buffer;
|
||||
BNetworkRoster& roster = BNetworkRoster::Default();
|
||||
int32 nameLength = strlen(name);
|
||||
bool success = false;
|
||||
BNetworkInterface interface;
|
||||
uint32 cookie = 0;
|
||||
|
||||
for (uint32 i = 0; i < count; i++) {
|
||||
if (!strncmp(interface->ifr_name, name, nameLength)) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
|
||||
+ interface->ifr_addr.sa_len);
|
||||
while (roster.GetNextInterface(&cookie, interface) == B_OK) {
|
||||
if (!strncmp(interface.Name(), name, nameLength))
|
||||
return true;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
return success;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NetServer::_RemoveInterface(int socket, const char* name)
|
||||
NetServer::_RemoveInterface(const char* name)
|
||||
{
|
||||
ifreq request;
|
||||
if (!prepare_request(request, name))
|
||||
return B_ERROR;
|
||||
|
||||
if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
|
||||
BNetworkRoster& roster = BNetworkRoster::Default();
|
||||
status_t status = roster.RemoveInterface(name);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "%s: Could not delete interface %s: %s\n",
|
||||
Name(), name, strerror(errno));
|
||||
return B_ERROR;
|
||||
Name(), name, strerror(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NetServer::_DisableInterface(int socket, const char* name)
|
||||
NetServer::_DisableInterface(const char* name)
|
||||
{
|
||||
ifreq request;
|
||||
if (!prepare_request(request, name))
|
||||
return B_ERROR;
|
||||
BNetworkInterface interface(name);
|
||||
int32 flags = interface.Flags();
|
||||
|
||||
if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
|
||||
fprintf(stderr, "%s: Getting flags failed: %s\n", Name(),
|
||||
strerror(errno));
|
||||
return B_ERROR;
|
||||
}
|
||||
// Set interface down
|
||||
request.ifr_flags &= ~(IFF_UP | IFF_AUTO_CONFIGURED | IFF_CONFIGURING);
|
||||
flags &= ~(IFF_UP | IFF_AUTO_CONFIGURED | IFF_CONFIGURING);
|
||||
|
||||
if (ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
|
||||
fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
|
||||
strerror(errno));
|
||||
return B_ERROR;
|
||||
status_t status = interface.SetFlags(flags);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
|
||||
strerror(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: set %s interface down...\n", Name(), name);
|
||||
|
||||
fprintf(stderr, "%s: set %s interface down...\n", Name(), name);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NetServer::_ConfigureInterface(int socket, BMessage& interface,
|
||||
bool fromMessage)
|
||||
NetServer::_ConfigureInterface(BMessage& interface)
|
||||
{
|
||||
const char *device;
|
||||
const char* device;
|
||||
if (interface.FindString("device", &device) != B_OK)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
ifreq request;
|
||||
if (!prepare_request(request, device))
|
||||
return B_ERROR;
|
||||
|
||||
bool startAutoConfig = false;
|
||||
|
||||
int32 flags;
|
||||
@ -595,41 +378,28 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface,
|
||||
BMessage addressMessage;
|
||||
for (int32 index = 0; interface.FindMessage("address", index,
|
||||
&addressMessage) == B_OK; index++) {
|
||||
const char* family;
|
||||
if (addressMessage.FindString("family", &family) < B_OK)
|
||||
continue;
|
||||
int32 family;
|
||||
if (addressMessage.FindInt32("family", &family) != B_OK) {
|
||||
const char* familyString;
|
||||
if (addressMessage.FindString("family", &familyString) == B_OK) {
|
||||
if (get_address_family(familyString) == AF_UNSPEC) {
|
||||
// we don't support this family
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else
|
||||
family = AF_UNSPEC;
|
||||
|
||||
int32 familyIndex;
|
||||
if (!get_family_index(family, familyIndex)) {
|
||||
// we don't support this family
|
||||
continue;
|
||||
}
|
||||
BNetworkInterface interface(device);
|
||||
if (!interface.Exists()) {
|
||||
// the interface does not exist yet, we have to add it first
|
||||
BNetworkRoster& roster = BNetworkRoster::Default();
|
||||
|
||||
int familySocket = socket;
|
||||
if (family_at_index(familyIndex) != AF_INET)
|
||||
socket = ::socket(family_at_index(familyIndex), SOCK_DGRAM, 0);
|
||||
if (socket < 0) {
|
||||
// the family is not available in this environment
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32 interfaceIndex = 0;
|
||||
if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 0)
|
||||
interfaceIndex = request.ifr_index;
|
||||
|
||||
if (interfaceIndex == 0) {
|
||||
// we need to create the interface first
|
||||
ifaliasreq request;
|
||||
strlcpy(request.ifra_name, device, IF_NAMESIZE);
|
||||
|
||||
request.ifra_addr.ss_family = AF_UNSPEC;
|
||||
request.ifra_mask.ss_family = AF_UNSPEC;
|
||||
request.ifra_broadaddr.ss_family = AF_UNSPEC;
|
||||
|
||||
if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) {
|
||||
status_t status = roster.AddInterface(interface);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "%s: Could not add interface: %s\n", Name(),
|
||||
strerror(errno));
|
||||
return errno;
|
||||
strerror(status));
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@ -638,129 +408,97 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface,
|
||||
bool autoConfig;
|
||||
if (addressMessage.FindBool("auto_config", &autoConfig) != B_OK)
|
||||
autoConfig = false;
|
||||
#if 0
|
||||
if (autoConfig && fromMessage) {
|
||||
// we don't accept auto-config messages this way
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool hasAddress = false, hasMask = false, hasPeer = false;
|
||||
bool hasBroadcast = false;
|
||||
struct sockaddr address, mask, peer, broadcast, gateway;
|
||||
BNetworkAddress address;
|
||||
BNetworkAddress mask;
|
||||
BNetworkAddress broadcast;
|
||||
BNetworkAddress peer;
|
||||
BNetworkAddress gateway;
|
||||
|
||||
const char* string;
|
||||
|
||||
if (!autoConfig) {
|
||||
if (addressMessage.FindString("address", &string) == B_OK
|
||||
&& parse_address(familyIndex, string, address)) {
|
||||
hasAddress = true;
|
||||
if (addressMessage.FindString("address", &string) == B_OK) {
|
||||
parse_address(family, string, address);
|
||||
|
||||
if (addressMessage.FindString("mask", &string) == B_OK
|
||||
&& parse_address(familyIndex, string, mask))
|
||||
hasMask = true;
|
||||
if (addressMessage.FindString("mask", &string) == B_OK)
|
||||
parse_address(family, string, mask);
|
||||
}
|
||||
if (addressMessage.FindString("peer", &string) == B_OK
|
||||
&& parse_address(familyIndex, string, peer))
|
||||
hasPeer = true;
|
||||
if (addressMessage.FindString("broadcast", &string) == B_OK
|
||||
&& parse_address(familyIndex, string, broadcast))
|
||||
hasBroadcast = true;
|
||||
|
||||
if (addressMessage.FindString("peer", &string) == B_OK)
|
||||
parse_address(family, string, peer);
|
||||
|
||||
if (addressMessage.FindString("broadcast", &string) == B_OK)
|
||||
parse_address(family, string, broadcast);
|
||||
}
|
||||
|
||||
route_entry route;
|
||||
memset(&route, 0, sizeof(route_entry));
|
||||
route.flags = RTF_STATIC | RTF_DEFAULT;
|
||||
|
||||
request.ifr_route = route;
|
||||
|
||||
if (autoConfig) {
|
||||
_QuitLooperForDevice(device);
|
||||
startAutoConfig = true;
|
||||
} else if (addressMessage.FindString("gateway", &string) == B_OK
|
||||
&& parse_address(familyIndex, string, gateway)) {
|
||||
&& parse_address(family, string, gateway)) {
|
||||
// add gateway route, if we're asked for it
|
||||
|
||||
ioctl(socket, SIOCDELRT, &request, sizeof(request));
|
||||
interface.RemoveDefaultRoute(family);
|
||||
// Try to remove a previous default route, doesn't matter
|
||||
// if it fails.
|
||||
|
||||
route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY;
|
||||
route.gateway = &gateway;
|
||||
|
||||
request.ifr_route = route;
|
||||
if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) {
|
||||
status_t status = interface.AddDefaultRoute(gateway);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "%s: Could not add route for %s: %s\n",
|
||||
Name(), device, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
// set addresses
|
||||
// set address/mask/broadcast/peer
|
||||
|
||||
if (hasAddress) {
|
||||
memcpy(&request.ifr_addr, &address, address.sa_len);
|
||||
if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) {
|
||||
BNetworkInterfaceAddress interfaceAddress;
|
||||
interfaceAddress.SetAddress(address);
|
||||
interfaceAddress.SetMask(mask);
|
||||
if (!broadcast.IsEmpty())
|
||||
interfaceAddress.SetBroadcast(broadcast);
|
||||
else if (!peer.IsEmpty())
|
||||
interfaceAddress.SetDestination(peer);
|
||||
|
||||
if (ioctl(familySocket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0) {
|
||||
fprintf(stderr, "%s: Setting address failed: %s\n", Name(), strerror(errno));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl(familySocket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
|
||||
fprintf(stderr, "%s: Getting flags failed: %s\n", Name(), strerror(errno));
|
||||
continue;
|
||||
}
|
||||
int32 currentFlags = request.ifr_flags;
|
||||
|
||||
if (hasMask) {
|
||||
memcpy(&request.ifr_mask, &mask, mask.sa_len);
|
||||
|
||||
if (ioctl(familySocket, SIOCSIFNETMASK, &request, sizeof(struct ifreq)) < 0) {
|
||||
fprintf(stderr, "%s: Setting subnet mask failed: %s\n", Name(), strerror(errno));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasBroadcast) {
|
||||
memcpy(&request.ifr_broadaddr, &broadcast, broadcast.sa_len);
|
||||
|
||||
if (ioctl(familySocket, SIOCSIFBRDADDR, &request, sizeof(struct ifreq)) < 0) {
|
||||
fprintf(stderr, "%s: Setting broadcast address failed: %s\n", Name(), strerror(errno));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasPeer) {
|
||||
memcpy(&request.ifr_dstaddr, &peer, peer.sa_len);
|
||||
|
||||
if (ioctl(familySocket, SIOCSIFDSTADDR, &request, sizeof(struct ifreq)) < 0) {
|
||||
fprintf(stderr, "%s: Setting peer address failed: %s\n", Name(), strerror(errno));
|
||||
continue;
|
||||
status_t status = interface.SetAddress(interfaceAddress);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "%s: Setting address failed: %s\n", Name(),
|
||||
strerror(status));
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// set flags
|
||||
|
||||
if (flags != 0) {
|
||||
request.ifr_flags = (currentFlags & ~IFF_CONFIGURING) | flags;
|
||||
int32 newFlags = interface.Flags();
|
||||
newFlags = (newFlags & ~IFF_CONFIGURING) | flags;
|
||||
if (!autoConfigured)
|
||||
request.ifr_flags = request.ifr_flags & ~IFF_AUTO_CONFIGURED;
|
||||
newFlags &= ~IFF_AUTO_CONFIGURED;
|
||||
|
||||
if (ioctl(familySocket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0)
|
||||
fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), strerror(errno));
|
||||
status_t status = interface.SetFlags(newFlags);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
|
||||
strerror(status));
|
||||
}
|
||||
}
|
||||
|
||||
// set options
|
||||
|
||||
if (mtu != -1) {
|
||||
request.ifr_mtu = mtu;
|
||||
if (ioctl(familySocket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0)
|
||||
fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), strerror(errno));
|
||||
status_t status = interface.SetMTU(mtu);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(),
|
||||
strerror(status));
|
||||
}
|
||||
}
|
||||
|
||||
if (metric != -1) {
|
||||
request.ifr_metric = metric;
|
||||
if (ioctl(familySocket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0)
|
||||
fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), strerror(errno));
|
||||
status_t status = interface.SetMetric(metric);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "%s: Setting metric failed: %s\n", Name(),
|
||||
strerror(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -800,7 +538,7 @@ NetServer::_ConfigureResolver(BMessage& resolverConfiguration)
|
||||
const char* domain;
|
||||
if (resolverConfiguration.FindString("domain", &domain) == B_OK)
|
||||
fprintf(file, "domain %s\n", domain);
|
||||
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
return B_OK;
|
||||
@ -835,22 +573,22 @@ NetServer::_LooperForDevice(const char* device)
|
||||
|
||||
|
||||
status_t
|
||||
NetServer::_ConfigureDevice(int socket, const char* path)
|
||||
NetServer::_ConfigureDevice(const char* device)
|
||||
{
|
||||
// bring interface up, but don't configure it just yet
|
||||
BMessage interface;
|
||||
interface.AddString("device", path);
|
||||
interface.AddString("device", device);
|
||||
BMessage address;
|
||||
address.AddString("family", "inet");
|
||||
address.AddBool("auto_config", true);
|
||||
interface.AddMessage("address", &address);
|
||||
|
||||
return _ConfigureInterface(socket, interface);
|
||||
return _ConfigureInterface(interface);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NetServer::_ConfigureDevices(int socket, const char* startPath,
|
||||
NetServer::_ConfigureDevices(const char* startPath,
|
||||
BMessage* suggestedInterface)
|
||||
{
|
||||
BDirectory directory(startPath);
|
||||
@ -868,18 +606,18 @@ NetServer::_ConfigureDevices(int socket, const char* startPath,
|
||||
if (suggestedInterface != NULL
|
||||
&& suggestedInterface->RemoveName("device") == B_OK
|
||||
&& suggestedInterface->AddString("device", path.Path()) == B_OK
|
||||
&& _ConfigureInterface(socket, *suggestedInterface) == B_OK)
|
||||
&& _ConfigureInterface(*suggestedInterface) == B_OK)
|
||||
suggestedInterface = NULL;
|
||||
else
|
||||
_ConfigureDevice(socket, path.Path());
|
||||
_ConfigureDevice(path.Path());
|
||||
} else if (entry.IsDirectory())
|
||||
_ConfigureDevices(socket, path.Path(), suggestedInterface);
|
||||
_ConfigureDevices(path.Path(), suggestedInterface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice)
|
||||
NetServer::_ConfigureInterfaces(BMessage* _missingDevice)
|
||||
{
|
||||
BMessage interface;
|
||||
uint32 cookie = 0;
|
||||
@ -888,11 +626,11 @@ NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice)
|
||||
const char *device;
|
||||
if (interface.FindString("device", &device) != B_OK)
|
||||
continue;
|
||||
|
||||
|
||||
bool disabled = false;
|
||||
if (interface.FindBool("disabled", &disabled) == B_OK && disabled) {
|
||||
// disabled by user request
|
||||
_DisableInterface(socket, device);
|
||||
_DisableInterface(device);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -908,7 +646,7 @@ NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice)
|
||||
}
|
||||
}
|
||||
|
||||
_ConfigureInterface(socket, interface);
|
||||
_ConfigureInterface(interface);
|
||||
}
|
||||
}
|
||||
|
||||
@ -924,17 +662,18 @@ NetServer::_BringUpInterfaces()
|
||||
Quit();
|
||||
return;
|
||||
}
|
||||
close(socket);
|
||||
|
||||
_RemoveInvalidInterfaces(socket);
|
||||
_RemoveInvalidInterfaces();
|
||||
|
||||
// First, we look into the settings, and try to bring everything up from there
|
||||
|
||||
BMessage missingDevice;
|
||||
_ConfigureInterfaces(socket, &missingDevice);
|
||||
_ConfigureInterfaces(&missingDevice);
|
||||
|
||||
// check configuration
|
||||
|
||||
if (!_TestForInterface(socket, "loop")) {
|
||||
if (!_TestForInterface("loop")) {
|
||||
// there is no loopback interface, create one
|
||||
BMessage interface;
|
||||
interface.AddString("device", "loop");
|
||||
@ -943,19 +682,17 @@ NetServer::_BringUpInterfaces()
|
||||
address.AddString("address", "127.0.0.1");
|
||||
interface.AddMessage("address", &address);
|
||||
|
||||
_ConfigureInterface(socket, interface);
|
||||
_ConfigureInterface(interface);
|
||||
}
|
||||
|
||||
// TODO: also check if the networking driver is correctly initialized!
|
||||
// (and check for other devices to take over its configuration)
|
||||
|
||||
if (!_TestForInterface(socket, "/dev/net/")) {
|
||||
if (!_TestForInterface("/dev/net/")) {
|
||||
// there is no driver configured - see if there is one and try to use it
|
||||
_ConfigureDevices(socket, "/dev/net",
|
||||
_ConfigureDevices("/dev/net",
|
||||
missingDevice.HasString("device") ? &missingDevice : NULL);
|
||||
}
|
||||
|
||||
close(socket);
|
||||
}
|
||||
|
||||
|
||||
@ -971,7 +708,7 @@ NetServer::_StartServices()
|
||||
|
||||
|
||||
void
|
||||
NetServer::_HandleDeviceMonitor(int socket, BMessage* message)
|
||||
NetServer::_HandleDeviceMonitor(BMessage* message)
|
||||
{
|
||||
int32 opcode;
|
||||
if (message->FindInt32("opcode", &opcode) != B_OK
|
||||
@ -983,11 +720,11 @@ NetServer::_HandleDeviceMonitor(int socket, BMessage* message)
|
||||
if (message->FindString("watched_path", &watchedPath) != B_OK
|
||||
|| message->FindString("path", &path) != B_OK)
|
||||
return;
|
||||
|
||||
|
||||
if (opcode == B_ENTRY_CREATED)
|
||||
_ConfigureDevice(socket, path);
|
||||
_ConfigureDevice(path);
|
||||
else
|
||||
_RemoveInterface(socket, path);
|
||||
_RemoveInterface(path);
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,21 +14,22 @@
|
||||
#include <net/if.h>
|
||||
|
||||
|
||||
class BNetworkAddress;
|
||||
|
||||
|
||||
// TODO: move this into a private shared header
|
||||
// NOTE: this header is used by other applications (such as ifconfig,
|
||||
// and Network) because of these three defines
|
||||
// and Network) because of these defines
|
||||
#define kNetServerSignature "application/x-vnd.haiku-net_server"
|
||||
#define kMsgConfigureInterface 'COif'
|
||||
#define kMsgConfigureResolver 'COrs'
|
||||
#define kMsgJoinNetwork 'JNnw'
|
||||
#define kMsgLeaveNetwork 'LVnw'
|
||||
|
||||
|
||||
extern bool get_family_index(const char* name, int32& familyIndex);
|
||||
extern int family_at_index(int32 index);
|
||||
extern bool parse_address(int32 familyIndex, const char* argument,
|
||||
struct sockaddr& address);
|
||||
extern void set_any_address(int32 familyIndex, struct sockaddr& address);
|
||||
extern void set_port(int32 familyIndex, struct sockaddr& address, int32 port);
|
||||
int get_address_family(const char* argument);
|
||||
bool parse_address(int32& family, const char* argument,
|
||||
BNetworkAddress& address);
|
||||
|
||||
extern bool prepare_request(ifreq& request, const char* name);
|
||||
extern status_t get_mac_address(const char* device, uint8* address);
|
||||
|
||||
#endif // NET_SERVER_H
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@ -12,6 +12,7 @@
|
||||
#include "Settings.h"
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <NetworkAddress.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
@ -31,7 +32,7 @@ struct service_address {
|
||||
int family;
|
||||
int type;
|
||||
int protocol;
|
||||
sockaddr address;
|
||||
BNetworkAddress address;
|
||||
|
||||
bool operator==(const struct service_address& other) const;
|
||||
};
|
||||
@ -100,8 +101,7 @@ service_address::operator==(const struct service_address& other) const
|
||||
return family == other.family
|
||||
&& type == other.type
|
||||
&& protocol == other.protocol
|
||||
&& address.sa_len == other.address.sa_len
|
||||
&& !memcmp(&address, &other.address, address.sa_len);
|
||||
&& address == other.address;
|
||||
}
|
||||
|
||||
|
||||
@ -274,7 +274,8 @@ Services::_StartService(struct service& service)
|
||||
|
||||
address.socket = socket(address.family, address.type, address.protocol);
|
||||
if (address.socket < 0
|
||||
|| bind(address.socket, &address.address, address.address.sa_len) < 0
|
||||
|| bind(address.socket, address.address, address.address.Length())
|
||||
< 0
|
||||
|| fcntl(address.socket, F_SETFD, FD_CLOEXEC) < 0) {
|
||||
failed = true;
|
||||
break;
|
||||
@ -378,13 +379,12 @@ Services::_ToService(const BMessage& message, struct service*& service)
|
||||
|
||||
// we default to inet/tcp/port-from-service-name if nothing is specified
|
||||
const char* string;
|
||||
int32 serviceFamilyIndex;
|
||||
int32 serviceFamily = -1;
|
||||
if (message.FindString("family", &string) != B_OK)
|
||||
string = "inet";
|
||||
|
||||
if (get_family_index(string, serviceFamilyIndex))
|
||||
serviceFamily = family_at_index(serviceFamilyIndex);
|
||||
int32 serviceFamily = get_address_family(string);
|
||||
if (serviceFamily == AF_UNSPEC)
|
||||
serviceFamily = AF_INET;
|
||||
|
||||
int32 serviceProtocol;
|
||||
if (message.FindString("protocol", &string) == B_OK)
|
||||
@ -424,12 +424,10 @@ Services::_ToService(const BMessage& message, struct service*& service)
|
||||
if (address.FindString("family", &string) != B_OK)
|
||||
continue;
|
||||
|
||||
int32 familyIndex;
|
||||
if (!get_family_index(string, familyIndex))
|
||||
serviceAddress.family = get_address_family(string);
|
||||
if (serviceAddress.family == AF_UNSPEC)
|
||||
continue;
|
||||
|
||||
serviceAddress.family = family_at_index(familyIndex);
|
||||
|
||||
if (address.FindString("protocol", &string) == B_OK)
|
||||
serviceAddress.protocol = parse_protocol(string);
|
||||
else
|
||||
@ -443,16 +441,16 @@ Services::_ToService(const BMessage& message, struct service*& service)
|
||||
serviceAddress.type = serviceType;
|
||||
|
||||
if (address.FindString("address", &string) == B_OK) {
|
||||
if (!parse_address(familyIndex, string, serviceAddress.address))
|
||||
if (!parse_address(serviceFamily, string, serviceAddress.address))
|
||||
continue;
|
||||
} else
|
||||
set_any_address(familyIndex, serviceAddress.address);
|
||||
serviceAddress.address.SetToWildcard(serviceFamily);
|
||||
|
||||
int32 port;
|
||||
if (address.FindInt32("port", &port) != B_OK)
|
||||
port = servicePort;
|
||||
|
||||
set_port(familyIndex, serviceAddress.address, port);
|
||||
serviceAddress.address.SetPort(port);
|
||||
serviceAddress.socket = -1;
|
||||
|
||||
serviceAddress.owner = service;
|
||||
@ -472,9 +470,8 @@ Services::_ToService(const BMessage& message, struct service*& service)
|
||||
serviceAddress.family = serviceFamily;
|
||||
serviceAddress.type = serviceType;
|
||||
serviceAddress.protocol = serviceProtocol;
|
||||
serviceAddress.address.SetToWildcard(serviceFamily, servicePort);
|
||||
|
||||
set_any_address(serviceFamilyIndex, serviceAddress.address);
|
||||
set_port(serviceFamilyIndex, serviceAddress.address, servicePort);
|
||||
serviceAddress.socket = -1;
|
||||
|
||||
serviceAddress.owner = service;
|
||||
|
Loading…
Reference in New Issue
Block a user