From af0745618fc4fca86016d858e5ba9dc64dab16ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 23 Nov 2010 21:11:04 +0000 Subject: [PATCH] * 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 --- src/servers/net/AutoconfigLooper.cpp | 47 +- src/servers/net/DHCPClient.cpp | 65 ++- src/servers/net/DHCPClient.h | 8 +- src/servers/net/Jamfile | 2 +- src/servers/net/NetServer.cpp | 643 ++++++++------------------- src/servers/net/NetServer.h | 19 +- src/servers/net/Services.cpp | 33 +- 7 files changed, 264 insertions(+), 553 deletions(-) diff --git a/src/servers/net/AutoconfigLooper.cpp b/src/servers/net/AutoconfigLooper.cpp index 1799cb7a8e..294aa71888 100644 --- a/src/servers/net/AutoconfigLooper.cpp +++ b/src/servers/net/AutoconfigLooper.cpp @@ -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 #include -#include +#include +#include #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); } diff --git a/src/servers/net/DHCPClient.cpp b/src/servers/net/DHCPClient.cpp index 6dc7f8c1e2..d488aa63d2 100644 --- a/src/servers/net/DHCPClient.cpp +++ b/src/servers/net/DHCPClient.cpp @@ -13,6 +13,8 @@ #include #include +#include +#include #include #include @@ -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; diff --git a/src/servers/net/DHCPClient.h b/src/servers/net/DHCPClient.h index 04afc2845b..ebc044d6fd 100644 --- a/src/servers/net/DHCPClient.h +++ b/src/servers/net/DHCPClient.h @@ -13,9 +13,13 @@ #include +#include + + 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; diff --git a/src/servers/net/Jamfile b/src/servers/net/Jamfile index 9ddac3679d..25b56f8f7a 100644 --- a/src/servers/net/Jamfile +++ b/src/servers/net/Jamfile @@ -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 ; diff --git a/src/servers/net/NetServer.cpp b/src/servers/net/NetServer.cpp index ae4c087a03..f8404919d7 100644 --- a/src/servers/net/NetServer.cpp +++ b/src/servers/net/NetServer.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -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); } diff --git a/src/servers/net/NetServer.h b/src/servers/net/NetServer.h index 975e2f15a2..260833d0bc 100644 --- a/src/servers/net/NetServer.h +++ b/src/servers/net/NetServer.h @@ -14,21 +14,22 @@ #include +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 diff --git a/src/servers/net/Services.cpp b/src/servers/net/Services.cpp index f389c29614..6196f5eef9 100644 --- a/src/servers/net/Services.cpp +++ b/src/servers/net/Services.cpp @@ -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 +#include #include #include @@ -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;