* 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:
Axel Dörfler
2010-11-23 21:11:04 +00:00
parent 01308f219b
commit af0745618f
7 changed files with 264 additions and 553 deletions
+17 -30
View File
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -17,7 +17,8 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <net_notifications.h> #include <NetworkInterface.h>
#include <NetworkNotifications.h>
#include "DHCPClient.h" #include "DHCPClient.h"
#include "NetServer.h" #include "NetServer.h"
@@ -57,20 +58,11 @@ AutoconfigLooper::_RemoveClient()
void void
AutoconfigLooper::_Configure() AutoconfigLooper::_Configure()
{ {
ifreq request;
if (!prepare_request(request, fDevice.String()))
return;
// set IFF_CONFIGURING flag on interface // set IFF_CONFIGURING flag on interface
int socket = ::socket(AF_INET, SOCK_DGRAM, 0); BNetworkInterface interface(fDevice.String());
if (socket < 0) int32 flags = interface.Flags() & ~IFF_AUTO_CONFIGURED;
return; interface.SetFlags(flags | IFF_CONFIGURING);
if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0) {
request.ifr_flags |= IFF_CONFIGURING;
ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq));
}
// remove current handler // remove current handler
@@ -81,10 +73,8 @@ AutoconfigLooper::_Configure()
fCurrentClient = new DHCPClient(fTarget, fDevice.String()); fCurrentClient = new DHCPClient(fTarget, fDevice.String());
AddHandler(fCurrentClient); AddHandler(fCurrentClient);
if (fCurrentClient->Initialize() == B_OK) { if (fCurrentClient->Initialize() == B_OK)
close(socket);
return; return;
}
_RemoveClient(); _RemoveClient();
@@ -94,23 +84,20 @@ AutoconfigLooper::_Configure()
// TODO: have a look at zeroconf // TODO: have a look at zeroconf
// TODO: this could also be done add-on based // TODO: this could also be done add-on based
if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0 if ((interface.Flags() & IFF_CONFIGURING) == 0) {
&& (request.ifr_flags & IFF_CONFIGURING) == 0) {
// Someone else configured the interface in the mean time // Someone else configured the interface in the mean time
close(socket);
return; return;
} }
close(socket); BMessage message(kMsgConfigureInterface);
message.AddString("device", fDevice.String());
message.AddBool("auto", true);
BMessage interface(kMsgConfigureInterface); BNetworkAddress link;
interface.AddString("device", fDevice.String());
interface.AddBool("auto", true);
uint8 mac[6];
uint8 last = 56; 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 // 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]; last = mac[0] ^ mac[1] ^ mac[2] ^ mac[3] ^ mac[4] ^ mac[5];
if (last > 253) if (last > 253)
last = 253; last = 253;
@@ -126,11 +113,11 @@ AutoconfigLooper::_Configure()
snprintf(string, sizeof(string), "169.254.0.%u", last); snprintf(string, sizeof(string), "169.254.0.%u", last);
BMessage address; BMessage address;
address.AddString("family", "inet"); address.AddInt32("family", AF_INET);
address.AddString("address", string); address.AddString("address", string);
interface.AddMessage("address", &address); message.AddMessage("address", &address);
fTarget.SendMessage(&interface); fTarget.SendMessage(&message);
} }
+25 -40
View File
@@ -13,6 +13,8 @@
#include <Message.h> #include <Message.h>
#include <MessageRunner.h> #include <MessageRunner.h>
#include <NetworkDevice.h>
#include <NetworkInterface.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
@@ -332,23 +334,24 @@ dhcp_message::FinishOptions(uint8* options)
DHCPClient::DHCPClient(BMessenger target, const char* device) DHCPClient::DHCPClient(BMessenger target, const char* device)
: AutoconfigClient("dhcp", target, device), :
AutoconfigClient("dhcp", target, device),
fConfiguration(kMsgConfigureInterface), fConfiguration(kMsgConfigureInterface),
fResolverConfiguration(kMsgConfigureResolver), fResolverConfiguration(kMsgConfigureResolver),
fRunner(NULL), fRunner(NULL),
fServer(AF_INET, NULL, DHCP_SERVER_PORT),
fLeaseTime(0) fLeaseTime(0)
{ {
fStartTime = system_time(); fStartTime = system_time();
fTransactionID = (uint32)fStartTime; fTransactionID = (uint32)fStartTime;
fStatus = get_mac_address(device, fMAC); BNetworkAddress link;
if (fStatus < B_OK) BNetworkInterface interface(device);
fStatus = interface.GetHardwareAddress(link);
if (fStatus != B_OK)
return; return;
memset(&fServer, 0, sizeof(struct sockaddr_in)); memcpy(fMAC, link.LinkLevelAddress(), sizeof(fMAC));
fServer.sin_family = AF_INET;
fServer.sin_len = sizeof(struct sockaddr_in);
fServer.sin_port = htons(DHCP_SERVER_PORT);
openlog_thread("DHCP", 0, LOG_DAEMON); openlog_thread("DHCP", 0, LOG_DAEMON);
} }
@@ -393,12 +396,7 @@ DHCPClient::_Negotiate(dhcp_state state)
if (socket < 0) if (socket < 0)
return errno; return errno;
sockaddr_in local; BNetworkAddress local(AF_INET, NULL, DHCP_CLIENT_PORT);
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;
// Enable reusing the port . This is needed in case there is more // 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 // 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; int option = 1;
setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &option, sizeof(option)); 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); close(socket);
return errno; return errno;
} }
sockaddr_in broadcast; BNetworkAddress broadcast;
memset(&broadcast, 0, sizeof(struct sockaddr_in)); broadcast.SetToBroadcast(AF_INET, DHCP_SERVER_PORT);
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;
option = 1; option = 1;
setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &option, sizeof(option)); setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &option, sizeof(option));
@@ -425,19 +419,10 @@ DHCPClient::_Negotiate(dhcp_state state)
if (state == INIT) { if (state == INIT) {
// The local interface does not have an address yet, bind the socket // The local interface does not have an address yet, bind the socket
// to the device directly. // to the device directly.
int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0); BNetworkDevice device(Device());
if (linkSocket >= 0) { int index = device.Index();
// 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));
}
close(linkSocket); setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, &index, sizeof(int));
}
} }
bigtime_t previousLeaseTime = fLeaseTime; bigtime_t previousLeaseTime = fLeaseTime;
@@ -558,7 +543,7 @@ DHCPClient::_Negotiate(dhcp_state state)
status = Target().SendMessage(&fConfiguration, &reply); status = Target().SendMessage(&fConfiguration, &reply);
if (status == B_OK) if (status == B_OK)
status = reply.FindInt32("status", &fStatus); status = reply.FindInt32("status", &fStatus);
// configure resolver // configure resolver
reply.MakeEmpty(); reply.MakeEmpty();
status = Target().SendMessage(&fResolverConfiguration, &reply); status = Target().SendMessage(&fResolverConfiguration, &reply);
@@ -653,7 +638,7 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address,
break; break;
} }
case OPTION_SERVER_ADDRESS: case OPTION_SERVER_ADDRESS:
fServer.sin_addr.s_addr = *(in_addr_t*)data; fServer.SetAddress(*(in_addr_t*)data);
break; break;
case OPTION_ADDRESS_LEASE_TIME: case OPTION_ADDRESS_LEASE_TIME:
@@ -684,8 +669,8 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address,
min_c(size + 1, sizeof(domain))); min_c(size + 1, sizeof(domain)));
syslog(LOG_INFO, "DHCP domain name: \"%s\"\n", domain); syslog(LOG_INFO, "DHCP domain name: \"%s\"\n", domain);
resolverConfiguration.AddString("domain", domain); resolverConfiguration.AddString("domain", domain);
break; break;
} }
@@ -718,9 +703,10 @@ DHCPClient::_PrepareMessage(dhcp_message& message, dhcp_state state)
case DHCP_RELEASE: case DHCP_RELEASE:
{ {
// add server identifier option // add server identifier option
const sockaddr_in& server = (sockaddr_in&)fServer.SockAddr();
uint8* next = message.PrepareMessage(type); uint8* next = message.PrepareMessage(type);
next = message.PutOption(next, OPTION_SERVER_ADDRESS, 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 // In RENEWAL or REBINDING state, we must set the client_address field, and not
// use OPTION_REQUEST_IP_ADDRESS for DHCP_REQUEST messages // use OPTION_REQUEST_IP_ADDRESS for DHCP_REQUEST messages
@@ -805,14 +791,13 @@ DHCPClient::_ToString(in_addr_t address) const
status_t status_t
DHCPClient::_SendMessage(int socket, dhcp_message& message, 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(), syslog(LOG_DEBUG, "DHCP send message %u for %s\n", message.Type(),
Device()); Device());
ssize_t bytesSent = sendto(socket, &message, message.Size(), ssize_t bytesSent = sendto(socket, &message, message.Size(),
address.sin_addr.s_addr == INADDR_BROADCAST ? MSG_BCAST : 0, address.IsBroadcast() ? MSG_BCAST : 0, address, address.Length());
(struct sockaddr*)&address, sizeof(sockaddr_in));
if (bytesSent < 0) if (bytesSent < 0)
return errno; return errno;
+6 -2
View File
@@ -13,9 +13,13 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <NetworkAddress.h>
class BMessageRunner; class BMessageRunner;
class dhcp_message; class dhcp_message;
enum dhcp_state { enum dhcp_state {
INIT, INIT,
REQUESTING, REQUESTING,
@@ -44,7 +48,7 @@ private:
void _PrepareMessage(dhcp_message& message, void _PrepareMessage(dhcp_message& message,
dhcp_state state); dhcp_state state);
status_t _SendMessage(int socket, dhcp_message& message, status_t _SendMessage(int socket, dhcp_message& message,
sockaddr_in& address) const; const BNetworkAddress& address) const;
dhcp_state _CurrentState() const; dhcp_state _CurrentState() const;
void _ResetTimeout(int socket, time_t& timeout, void _ResetTimeout(int socket, time_t& timeout,
uint32& tries); uint32& tries);
@@ -61,7 +65,7 @@ private:
uint8 fMAC[6]; uint8 fMAC[6];
uint32 fTransactionID; uint32 fTransactionID;
in_addr_t fAssignedAddress; in_addr_t fAssignedAddress;
sockaddr_in fServer; BNetworkAddress fServer;
bigtime_t fStartTime; bigtime_t fStartTime;
bigtime_t fRenewalTime; bigtime_t fRenewalTime;
bigtime_t fRebindingTime; bigtime_t fRebindingTime;
+1 -1
View File
@@ -16,7 +16,7 @@ Server net_server :
DHCPClient.cpp DHCPClient.cpp
Services.cpp Services.cpp
: be libnetwork.so $(TARGET_LIBSTDC++) : be network bnetapi $(TARGET_LIBSTDC++)
# for PPP # for PPP
#libppp.a #libppp.a
; ;
+190 -453
View File
@@ -29,6 +29,8 @@
#include <Deskbar.h> #include <Deskbar.h>
#include <Directory.h> #include <Directory.h>
#include <Entry.h> #include <Entry.h>
#include <NetworkInterface.h>
#include <NetworkRoster.h>
#include <Path.h> #include <Path.h>
#include <PathMonitor.h> #include <PathMonitor.h>
#include <Roster.h> #include <Roster.h>
@@ -54,27 +56,24 @@ public:
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
private: private:
bool _IsValidInterface(int socket, const char* name); bool _IsValidInterface(BNetworkInterface& interface);
void _RemoveInvalidInterfaces(int socket); void _RemoveInvalidInterfaces();
status_t _RemoveInterface(int socket, const char* name); status_t _RemoveInterface(const char* name);
status_t _DisableInterface(int socket, const char* name); status_t _DisableInterface(const char* name);
bool _TestForInterface(int socket, const char* name); bool _TestForInterface(const char* name);
status_t _ConfigureInterface(int socket, status_t _ConfigureInterface(BMessage& interface);
BMessage& interface,
bool fromMessage = false);
status_t _ConfigureResolver( status_t _ConfigureResolver(
BMessage& resolverConfiguration); BMessage& resolverConfiguration);
bool _QuitLooperForDevice(const char* device); bool _QuitLooperForDevice(const char* device);
AutoconfigLooper* _LooperForDevice(const char* device); AutoconfigLooper* _LooperForDevice(const char* device);
status_t _ConfigureDevice(int socket, const char* path); status_t _ConfigureDevice(const char* path);
void _ConfigureDevices(int socket, const char* path, void _ConfigureDevices(const char* path,
BMessage* suggestedInterface = NULL); BMessage* suggestedInterface = NULL);
void _ConfigureInterfaces(int socket, void _ConfigureInterfaces(
BMessage* _missingDevice = NULL); BMessage* _missingDevice = NULL);
void _BringUpInterfaces(); void _BringUpInterfaces();
void _StartServices(); void _StartServices();
void _HandleDeviceMonitor(int socket, void _HandleDeviceMonitor(BMessage* message);
BMessage* message);
private: private:
Settings fSettings; Settings fSettings;
@@ -87,179 +86,89 @@ struct address_family {
int family; int family;
const char* name; const char* name;
const char* identifiers[4]; 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[] = { static const address_family kFamilies[] = {
{ {
AF_INET, AF_INET,
"inet", "inet",
{"AF_INET", "inet", "ipv4", NULL}, {"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 int
inet_parse_address(const char* string, sockaddr* _address) get_address_family(const char* argument)
{
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)
{ {
for (int32 i = 0; kFamilies[i].family >= 0; i++) { for (int32 i = 0; kFamilies[i].family >= 0; i++) {
for (int32 j = 0; kFamilies[i].identifiers[j]; j++) { 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 // found a match
familyIndex = i; return kFamilies[i].family;
return true;
} }
} }
} }
// defaults to AF_INET return AF_UNSPEC;
familyIndex = 0;
return false;
}
int
family_at_index(int32 index)
{
return kFamilies[index].family;
} }
/*! 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 bool
parse_address(int32 familyIndex, const char* argument, struct sockaddr& address) parse_address(int32& family, const char* argument, BNetworkAddress& address)
{ {
if (argument == NULL) if (argument == NULL)
return false; return false;
return kFamilies[familyIndex].parse_address(argument, &address); status_t status = address.SetTo(family, argument, (uint16)0,
} B_NO_ADDRESS_RESOLUTION);
if (status != B_OK)
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)
return false; 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; 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 - // #pragma mark -
NetServer::NetServer(status_t& error) NetServer::NetServer(status_t& error)
: BServer(kNetServerSignature, false, &error) :
BServer(kNetServerSignature, false, &error)
{ {
} }
NetServer::~NetServer() NetServer::~NetServer()
{ {
BPrivate::BPathMonitor::StopWatching("/dev/net", this); BPrivate::BPathMonitor::StopWatching("/dev/net", this);
} }
@@ -288,7 +197,7 @@ NetServer::ReadyToRun()
fSettings.StartMonitoring(this); fSettings.StartMonitoring(this);
_BringUpInterfaces(); _BringUpInterfaces();
_StartServices(); _StartServices();
BPrivate::BPathMonitor::StartWatching("/dev/net", B_ENTRY_CREATED BPrivate::BPathMonitor::StartWatching("/dev/net", B_ENTRY_CREATED
| B_ENTRY_REMOVED | B_WATCH_FILES_ONLY | B_WATCH_RECURSIVELY, this); | B_ENTRY_REMOVED | B_WATCH_FILES_ONLY | B_WATCH_RECURSIVELY, this);
} }
@@ -301,25 +210,13 @@ NetServer::MessageReceived(BMessage* message)
case B_PATH_MONITOR: case B_PATH_MONITOR:
{ {
fSettings.Update(message); fSettings.Update(message);
_HandleDeviceMonitor(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);
break; break;
} }
case kMsgInterfaceSettingsUpdated: case kMsgInterfaceSettingsUpdated:
{ {
// we need a socket to talk to the networking stack _ConfigureInterfaces();
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
if (socket < 0)
break;
_ConfigureInterfaces(socket);
close(socket);
break; break;
} }
@@ -334,32 +231,18 @@ NetServer::MessageReceived(BMessage* message)
case kMsgConfigureInterface: case kMsgConfigureInterface:
{ {
#if 0 status_t status = _ConfigureInterface(*message);
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);
BMessage reply(B_REPLY); BMessage reply(B_REPLY);
reply.AddInt32("status", status); reply.AddInt32("status", status);
message->SendReply(&reply); message->SendReply(&reply);
close(socket);
break; break;
} }
case kMsgConfigureResolver: case kMsgConfigureResolver:
{ {
status_t status = _ConfigureResolver(*message); status_t status = _ConfigureResolver(*message);
BMessage reply(B_REPLY); BMessage reply(B_REPLY);
reply.AddInt32("status", status); reply.AddInt32("status", status);
message->SendReply(&reply); 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. family, and, in case of ethernet, a hardware MAC address.
*/ */
bool 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 // check if it has an address
int32 addresses = 0; if (interface.CountAddresses() == 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)
return false; return false;
// check if it has a hardware address, too, in case of ethernet // check if it has a hardware address, too, in case of ethernet
int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0); BNetworkAddress link;
if (linkSocket < 0) if (interface.GetHardwareAddress(link) != B_OK)
return false; return false;
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) { if (link.LinkLevelType() == IFT_ETHER && link.LinkLevelAddressLength() != 6)
close(linkSocket);
return false;
}
close(linkSocket);
sockaddr_dl &link = *(sockaddr_dl *)&request.ifr_addr;
if (link.sdl_type == IFT_ETHER && link.sdl_alen < 6)
return false; return false;
return true; return true;
@@ -426,154 +281,82 @@ NetServer::_IsValidInterface(int socket, const char* name)
void void
NetServer::_RemoveInvalidInterfaces(int socket) NetServer::_RemoveInvalidInterfaces()
{ {
// get a list of all interfaces BNetworkRoster& roster = BNetworkRoster::Default();
BNetworkInterface interface;
uint32 cookie = 0;
ifconf config; while (roster.GetNextInterface(&cookie, interface) == B_OK) {
config.ifc_len = sizeof(config.ifc_value); if (!_IsValidInterface(interface)) {
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)) {
// remove invalid 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 bool
NetServer::_TestForInterface(int socket, const char* name) NetServer::_TestForInterface(const char* name)
{ {
// get a list of all interfaces
ifconf config; BNetworkRoster& roster = BNetworkRoster::Default();
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;
int32 nameLength = strlen(name); int32 nameLength = strlen(name);
bool success = false; BNetworkInterface interface;
uint32 cookie = 0;
for (uint32 i = 0; i < count; i++) { while (roster.GetNextInterface(&cookie, interface) == B_OK) {
if (!strncmp(interface->ifr_name, name, nameLength)) { if (!strncmp(interface.Name(), name, nameLength))
success = true; return true;
break;
}
interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
+ interface->ifr_addr.sa_len);
} }
free(buffer); return false;
return success;
} }
status_t status_t
NetServer::_RemoveInterface(int socket, const char* name) NetServer::_RemoveInterface(const char* name)
{ {
ifreq request; BNetworkRoster& roster = BNetworkRoster::Default();
if (!prepare_request(request, name)) status_t status = roster.RemoveInterface(name);
return B_ERROR; if (status != B_OK) {
if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
fprintf(stderr, "%s: Could not delete interface %s: %s\n", fprintf(stderr, "%s: Could not delete interface %s: %s\n",
Name(), name, strerror(errno)); Name(), name, strerror(status));
return B_ERROR; return status;
} }
return B_OK; return B_OK;
} }
status_t status_t
NetServer::_DisableInterface(int socket, const char* name) NetServer::_DisableInterface(const char* name)
{ {
ifreq request; BNetworkInterface interface(name);
if (!prepare_request(request, name)) int32 flags = interface.Flags();
return B_ERROR;
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 // 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) { status_t status = interface.SetFlags(flags);
fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), if (status != B_OK) {
strerror(errno)); fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
return B_ERROR; 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; return B_OK;
} }
status_t status_t
NetServer::_ConfigureInterface(int socket, BMessage& interface, NetServer::_ConfigureInterface(BMessage& interface)
bool fromMessage)
{ {
const char *device; const char* device;
if (interface.FindString("device", &device) != B_OK) if (interface.FindString("device", &device) != B_OK)
return B_BAD_VALUE; return B_BAD_VALUE;
ifreq request;
if (!prepare_request(request, device))
return B_ERROR;
bool startAutoConfig = false; bool startAutoConfig = false;
int32 flags; int32 flags;
@@ -595,41 +378,28 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface,
BMessage addressMessage; BMessage addressMessage;
for (int32 index = 0; interface.FindMessage("address", index, for (int32 index = 0; interface.FindMessage("address", index,
&addressMessage) == B_OK; index++) { &addressMessage) == B_OK; index++) {
const char* family; int32 family;
if (addressMessage.FindString("family", &family) < B_OK) if (addressMessage.FindInt32("family", &family) != B_OK) {
continue; 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; BNetworkInterface interface(device);
if (!get_family_index(family, familyIndex)) { if (!interface.Exists()) {
// we don't support this family // the interface does not exist yet, we have to add it first
continue; BNetworkRoster& roster = BNetworkRoster::Default();
}
int familySocket = socket; status_t status = roster.AddInterface(interface);
if (family_at_index(familyIndex) != AF_INET) if (status != B_OK) {
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) {
fprintf(stderr, "%s: Could not add interface: %s\n", Name(), fprintf(stderr, "%s: Could not add interface: %s\n", Name(),
strerror(errno)); strerror(status));
return errno; return status;
} }
} }
@@ -638,129 +408,97 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface,
bool autoConfig; bool autoConfig;
if (addressMessage.FindBool("auto_config", &autoConfig) != B_OK) if (addressMessage.FindBool("auto_config", &autoConfig) != B_OK)
autoConfig = false; 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; BNetworkAddress address;
bool hasBroadcast = false; BNetworkAddress mask;
struct sockaddr address, mask, peer, broadcast, gateway; BNetworkAddress broadcast;
BNetworkAddress peer;
BNetworkAddress gateway;
const char* string; const char* string;
if (!autoConfig) { if (!autoConfig) {
if (addressMessage.FindString("address", &string) == B_OK if (addressMessage.FindString("address", &string) == B_OK) {
&& parse_address(familyIndex, string, address)) { parse_address(family, string, address);
hasAddress = true;
if (addressMessage.FindString("mask", &string) == B_OK if (addressMessage.FindString("mask", &string) == B_OK)
&& parse_address(familyIndex, string, mask)) parse_address(family, string, mask);
hasMask = true;
} }
if (addressMessage.FindString("peer", &string) == B_OK
&& parse_address(familyIndex, string, peer)) if (addressMessage.FindString("peer", &string) == B_OK)
hasPeer = true; parse_address(family, string, peer);
if (addressMessage.FindString("broadcast", &string) == B_OK
&& parse_address(familyIndex, string, broadcast)) if (addressMessage.FindString("broadcast", &string) == B_OK)
hasBroadcast = true; 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) { if (autoConfig) {
_QuitLooperForDevice(device); _QuitLooperForDevice(device);
startAutoConfig = true; startAutoConfig = true;
} else if (addressMessage.FindString("gateway", &string) == B_OK } 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 // add gateway route, if we're asked for it
interface.RemoveDefaultRoute(family);
ioctl(socket, SIOCDELRT, &request, sizeof(request));
// Try to remove a previous default route, doesn't matter // Try to remove a previous default route, doesn't matter
// if it fails. // if it fails.
route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY; status_t status = interface.AddDefaultRoute(gateway);
route.gateway = &gateway; if (status != B_OK) {
request.ifr_route = route;
if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) {
fprintf(stderr, "%s: Could not add route for %s: %s\n", fprintf(stderr, "%s: Could not add route for %s: %s\n",
Name(), device, strerror(errno)); Name(), device, strerror(errno));
} }
} }
// set addresses // set address/mask/broadcast/peer
if (hasAddress) { if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) {
memcpy(&request.ifr_addr, &address, address.sa_len); 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) { status_t status = interface.SetAddress(interfaceAddress);
fprintf(stderr, "%s: Setting address failed: %s\n", Name(), strerror(errno)); if (status != B_OK) {
continue; fprintf(stderr, "%s: Setting address failed: %s\n", Name(),
} strerror(status));
} return status;
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;
} }
} }
// set flags // set flags
if (flags != 0) { if (flags != 0) {
request.ifr_flags = (currentFlags & ~IFF_CONFIGURING) | flags; int32 newFlags = interface.Flags();
newFlags = (newFlags & ~IFF_CONFIGURING) | flags;
if (!autoConfigured) if (!autoConfigured)
request.ifr_flags = request.ifr_flags & ~IFF_AUTO_CONFIGURED; newFlags &= ~IFF_AUTO_CONFIGURED;
if (ioctl(familySocket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) status_t status = interface.SetFlags(newFlags);
fprintf(stderr, "%s: Setting flags failed: %s\n", Name(), strerror(errno)); if (status != B_OK) {
fprintf(stderr, "%s: Setting flags failed: %s\n", Name(),
strerror(status));
}
} }
// set options // set options
if (mtu != -1) { if (mtu != -1) {
request.ifr_mtu = mtu; status_t status = interface.SetMTU(mtu);
if (ioctl(familySocket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0) if (status != B_OK) {
fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(), strerror(errno)); fprintf(stderr, "%s: Setting MTU failed: %s\n", Name(),
strerror(status));
}
} }
if (metric != -1) { if (metric != -1) {
request.ifr_metric = metric; status_t status = interface.SetMetric(metric);
if (ioctl(familySocket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0) if (status != B_OK) {
fprintf(stderr, "%s: Setting metric failed: %s\n", Name(), strerror(errno)); fprintf(stderr, "%s: Setting metric failed: %s\n", Name(),
strerror(status));
}
} }
} }
@@ -800,7 +538,7 @@ NetServer::_ConfigureResolver(BMessage& resolverConfiguration)
const char* domain; const char* domain;
if (resolverConfiguration.FindString("domain", &domain) == B_OK) if (resolverConfiguration.FindString("domain", &domain) == B_OK)
fprintf(file, "domain %s\n", domain); fprintf(file, "domain %s\n", domain);
fclose(file); fclose(file);
} }
return B_OK; return B_OK;
@@ -835,22 +573,22 @@ NetServer::_LooperForDevice(const char* device)
status_t status_t
NetServer::_ConfigureDevice(int socket, const char* path) NetServer::_ConfigureDevice(const char* device)
{ {
// bring interface up, but don't configure it just yet // bring interface up, but don't configure it just yet
BMessage interface; BMessage interface;
interface.AddString("device", path); interface.AddString("device", device);
BMessage address; BMessage address;
address.AddString("family", "inet"); address.AddString("family", "inet");
address.AddBool("auto_config", true); address.AddBool("auto_config", true);
interface.AddMessage("address", &address); interface.AddMessage("address", &address);
return _ConfigureInterface(socket, interface); return _ConfigureInterface(interface);
} }
void void
NetServer::_ConfigureDevices(int socket, const char* startPath, NetServer::_ConfigureDevices(const char* startPath,
BMessage* suggestedInterface) BMessage* suggestedInterface)
{ {
BDirectory directory(startPath); BDirectory directory(startPath);
@@ -868,18 +606,18 @@ NetServer::_ConfigureDevices(int socket, const char* startPath,
if (suggestedInterface != NULL if (suggestedInterface != NULL
&& suggestedInterface->RemoveName("device") == B_OK && suggestedInterface->RemoveName("device") == B_OK
&& suggestedInterface->AddString("device", path.Path()) == B_OK && suggestedInterface->AddString("device", path.Path()) == B_OK
&& _ConfigureInterface(socket, *suggestedInterface) == B_OK) && _ConfigureInterface(*suggestedInterface) == B_OK)
suggestedInterface = NULL; suggestedInterface = NULL;
else else
_ConfigureDevice(socket, path.Path()); _ConfigureDevice(path.Path());
} else if (entry.IsDirectory()) } else if (entry.IsDirectory())
_ConfigureDevices(socket, path.Path(), suggestedInterface); _ConfigureDevices(path.Path(), suggestedInterface);
} }
} }
void void
NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice) NetServer::_ConfigureInterfaces(BMessage* _missingDevice)
{ {
BMessage interface; BMessage interface;
uint32 cookie = 0; uint32 cookie = 0;
@@ -888,11 +626,11 @@ NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice)
const char *device; const char *device;
if (interface.FindString("device", &device) != B_OK) if (interface.FindString("device", &device) != B_OK)
continue; continue;
bool disabled = false; bool disabled = false;
if (interface.FindBool("disabled", &disabled) == B_OK && disabled) { if (interface.FindBool("disabled", &disabled) == B_OK && disabled) {
// disabled by user request // disabled by user request
_DisableInterface(socket, device); _DisableInterface(device);
continue; continue;
} }
@@ -908,7 +646,7 @@ NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice)
} }
} }
_ConfigureInterface(socket, interface); _ConfigureInterface(interface);
} }
} }
@@ -924,17 +662,18 @@ NetServer::_BringUpInterfaces()
Quit(); Quit();
return; return;
} }
close(socket);
_RemoveInvalidInterfaces(socket); _RemoveInvalidInterfaces();
// First, we look into the settings, and try to bring everything up from there // First, we look into the settings, and try to bring everything up from there
BMessage missingDevice; BMessage missingDevice;
_ConfigureInterfaces(socket, &missingDevice); _ConfigureInterfaces(&missingDevice);
// check configuration // check configuration
if (!_TestForInterface(socket, "loop")) { if (!_TestForInterface("loop")) {
// there is no loopback interface, create one // there is no loopback interface, create one
BMessage interface; BMessage interface;
interface.AddString("device", "loop"); interface.AddString("device", "loop");
@@ -943,19 +682,17 @@ NetServer::_BringUpInterfaces()
address.AddString("address", "127.0.0.1"); address.AddString("address", "127.0.0.1");
interface.AddMessage("address", &address); interface.AddMessage("address", &address);
_ConfigureInterface(socket, interface); _ConfigureInterface(interface);
} }
// TODO: also check if the networking driver is correctly initialized! // TODO: also check if the networking driver is correctly initialized!
// (and check for other devices to take over its configuration) // (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 // 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); missingDevice.HasString("device") ? &missingDevice : NULL);
} }
close(socket);
} }
@@ -971,7 +708,7 @@ NetServer::_StartServices()
void void
NetServer::_HandleDeviceMonitor(int socket, BMessage* message) NetServer::_HandleDeviceMonitor(BMessage* message)
{ {
int32 opcode; int32 opcode;
if (message->FindInt32("opcode", &opcode) != B_OK 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 if (message->FindString("watched_path", &watchedPath) != B_OK
|| message->FindString("path", &path) != B_OK) || message->FindString("path", &path) != B_OK)
return; return;
if (opcode == B_ENTRY_CREATED) if (opcode == B_ENTRY_CREATED)
_ConfigureDevice(socket, path); _ConfigureDevice(path);
else else
_RemoveInterface(socket, path); _RemoveInterface(path);
} }
+10 -9
View File
@@ -14,21 +14,22 @@
#include <net/if.h> #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, // 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 kNetServerSignature "application/x-vnd.haiku-net_server"
#define kMsgConfigureInterface 'COif' #define kMsgConfigureInterface 'COif'
#define kMsgConfigureResolver 'COrs' #define kMsgConfigureResolver 'COrs'
#define kMsgJoinNetwork 'JNnw'
#define kMsgLeaveNetwork 'LVnw'
extern bool get_family_index(const char* name, int32& familyIndex); int get_address_family(const char* argument);
extern int family_at_index(int32 index); bool parse_address(int32& family, const char* argument,
extern bool parse_address(int32 familyIndex, const char* argument, BNetworkAddress& address);
struct sockaddr& address);
extern void set_any_address(int32 familyIndex, struct sockaddr& address);
extern void set_port(int32 familyIndex, struct sockaddr& address, int32 port);
extern bool prepare_request(ifreq& request, const char* name);
extern status_t get_mac_address(const char* device, uint8* address);
#endif // NET_SERVER_H #endif // NET_SERVER_H
+15 -18
View File
@@ -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. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -12,6 +12,7 @@
#include "Settings.h" #include "Settings.h"
#include <Autolock.h> #include <Autolock.h>
#include <NetworkAddress.h>
#include <errno.h> #include <errno.h>
#include <netdb.h> #include <netdb.h>
@@ -31,7 +32,7 @@ struct service_address {
int family; int family;
int type; int type;
int protocol; int protocol;
sockaddr address; BNetworkAddress address;
bool operator==(const struct service_address& other) const; 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 return family == other.family
&& type == other.type && type == other.type
&& protocol == other.protocol && protocol == other.protocol
&& address.sa_len == other.address.sa_len && address == other.address;
&& !memcmp(&address, &other.address, address.sa_len);
} }
@@ -274,7 +274,8 @@ Services::_StartService(struct service& service)
address.socket = socket(address.family, address.type, address.protocol); address.socket = socket(address.family, address.type, address.protocol);
if (address.socket < 0 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) { || fcntl(address.socket, F_SETFD, FD_CLOEXEC) < 0) {
failed = true; failed = true;
break; 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 // we default to inet/tcp/port-from-service-name if nothing is specified
const char* string; const char* string;
int32 serviceFamilyIndex;
int32 serviceFamily = -1;
if (message.FindString("family", &string) != B_OK) if (message.FindString("family", &string) != B_OK)
string = "inet"; string = "inet";
if (get_family_index(string, serviceFamilyIndex)) int32 serviceFamily = get_address_family(string);
serviceFamily = family_at_index(serviceFamilyIndex); if (serviceFamily == AF_UNSPEC)
serviceFamily = AF_INET;
int32 serviceProtocol; int32 serviceProtocol;
if (message.FindString("protocol", &string) == B_OK) 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) if (address.FindString("family", &string) != B_OK)
continue; continue;
int32 familyIndex; serviceAddress.family = get_address_family(string);
if (!get_family_index(string, familyIndex)) if (serviceAddress.family == AF_UNSPEC)
continue; continue;
serviceAddress.family = family_at_index(familyIndex);
if (address.FindString("protocol", &string) == B_OK) if (address.FindString("protocol", &string) == B_OK)
serviceAddress.protocol = parse_protocol(string); serviceAddress.protocol = parse_protocol(string);
else else
@@ -443,16 +441,16 @@ Services::_ToService(const BMessage& message, struct service*& service)
serviceAddress.type = serviceType; serviceAddress.type = serviceType;
if (address.FindString("address", &string) == B_OK) { if (address.FindString("address", &string) == B_OK) {
if (!parse_address(familyIndex, string, serviceAddress.address)) if (!parse_address(serviceFamily, string, serviceAddress.address))
continue; continue;
} else } else
set_any_address(familyIndex, serviceAddress.address); serviceAddress.address.SetToWildcard(serviceFamily);
int32 port; int32 port;
if (address.FindInt32("port", &port) != B_OK) if (address.FindInt32("port", &port) != B_OK)
port = servicePort; port = servicePort;
set_port(familyIndex, serviceAddress.address, port); serviceAddress.address.SetPort(port);
serviceAddress.socket = -1; serviceAddress.socket = -1;
serviceAddress.owner = service; serviceAddress.owner = service;
@@ -472,9 +470,8 @@ Services::_ToService(const BMessage& message, struct service*& service)
serviceAddress.family = serviceFamily; serviceAddress.family = serviceFamily;
serviceAddress.type = serviceType; serviceAddress.type = serviceType;
serviceAddress.protocol = serviceProtocol; serviceAddress.protocol = serviceProtocol;
serviceAddress.address.SetToWildcard(serviceFamily, servicePort);
set_any_address(serviceFamilyIndex, serviceAddress.address);
set_port(serviceFamilyIndex, serviceAddress.address, servicePort);
serviceAddress.socket = -1; serviceAddress.socket = -1;
serviceAddress.owner = service; serviceAddress.owner = service;