From b01a3a33a6a9307d29ecf2e428010e188e85a191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 19 Oct 2006 13:37:13 +0000 Subject: [PATCH] * Implemented node monitoring: if you change the interfaces settings file, the networking stack is reconfigured automatically. * The previous default route is now removed before installing a new one. * "gateway" was missing in the driver settings to BMessage conversion template, and thus, it was only set to a default value in case there was no settings file. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19086 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/net/NetServer.cpp | 71 +++++++++++++++++++++++------- src/servers/net/Settings.cpp | 83 ++++++++++++++++++++++++++++++++++- src/servers/net/Settings.h | 8 ++++ 3 files changed, 144 insertions(+), 18 deletions(-) diff --git a/src/servers/net/NetServer.cpp b/src/servers/net/NetServer.cpp index b8b7748f5a..cdc5cb3d2a 100644 --- a/src/servers/net/NetServer.cpp +++ b/src/servers/net/NetServer.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,7 @@ class NetServer : public BApplication { virtual void AboutRequested(); virtual void ReadyToRun(); + virtual void MessageReceived(BMessage* message); private: bool _PrepareRequest(ifreq& request, const char* name); @@ -44,6 +46,7 @@ class NetServer : public BApplication { status_t _ConfigureInterface(int socket, BMessage& interface); status_t _ConfigureDevice(int socket, const char* path); void _ConfigureDevices(int socket, const char* path); + void _ConfigureInterfaces(int socket); void _BringUpInterfaces(); Settings fSettings; @@ -153,10 +156,38 @@ NetServer::AboutRequested() void NetServer::ReadyToRun() { + fSettings.StartMonitoring(this); _BringUpInterfaces(); } +void +NetServer::MessageReceived(BMessage* message) +{ + switch (message->what) { + case B_NODE_MONITOR: + fSettings.Update(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); + break; + } + + default: + BApplication::MessageReceived(message); + return; + } +} + + bool NetServer::_PrepareRequest(ifreq& request, const char* name) { @@ -304,10 +335,13 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface) && parse_address(familyIndex, string, gateway)) { route_entry route; memset(&route, 0, sizeof(route_entry)); - route.gateway = &gateway; route.flags = RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY; + route.gateway = &gateway; request.ifr_route = route; + ioctl(socket, SIOCDELRT, &request, sizeof(request)); + // Try to remove a previous default route, doesn't matter + // if it fails. if (ioctl(socket, SIOCADDRT, &request, sizeof(request)) < 0) { fprintf(stderr, "%s: Could not add route for %s: %s\n", @@ -465,19 +499,8 @@ NetServer::_ConfigureDevices(int socket, const char* startPath) void -NetServer::_BringUpInterfaces() +NetServer::_ConfigureInterfaces(int socket) { - // we need a socket to talk to the networking stack - int socket = ::socket(AF_INET, SOCK_DGRAM, 0); - if (socket < 0) { - fprintf(stderr, "%s: The networking stack doesn't seem to be available.\n", - Name()); - Quit(); - return; - } - - // First, we look into the settings, and try to bring everything up from there - BMessage interface; uint32 cookie = 0; while (fSettings.GetNextInterface(cookie, interface) == B_OK) { @@ -492,16 +515,32 @@ NetServer::_BringUpInterfaces() continue; } - // try to bring the interface up - _ConfigureInterface(socket, interface); } +} + + +void +NetServer::_BringUpInterfaces() +{ + // we need a socket to talk to the networking stack + int socket = ::socket(AF_INET, SOCK_DGRAM, 0); + if (socket < 0) { + fprintf(stderr, "%s: The networking stack doesn't seem to be available.\n", + Name()); + Quit(); + return; + } + + // First, we look into the settings, and try to bring everything up from there + + _ConfigureInterfaces(socket); // check configuration if (!_TestForInterface(socket, "loop")) { // there is no loopback interface, create one - interface.MakeEmpty(); + BMessage interface; interface.AddString("device", "loop"); BMessage address; address.AddString("family", "inet"); diff --git a/src/servers/net/Settings.cpp b/src/servers/net/Settings.cpp index b7c53f757e..49749cc21b 100644 --- a/src/servers/net/Settings.cpp +++ b/src/servers/net/Settings.cpp @@ -9,7 +9,9 @@ #include "Settings.h" +#include #include +#include #include #include @@ -23,6 +25,7 @@ const static settings_template kInterfaceAddressTemplate[] = { {B_STRING_TYPE, "mask", NULL}, {B_STRING_TYPE, "peer", NULL}, {B_STRING_TYPE, "broadcast", NULL}, + {B_STRING_TYPE, "gateway", NULL}, {0, NULL, NULL} }; @@ -66,12 +69,13 @@ Settings::~Settings() status_t Settings::_GetPath(const char* name, BPath& path) { - if (find_directory(B_COMMON_SETTINGS_DIRECTORY, &path) != B_OK) + if (find_directory(B_COMMON_SETTINGS_DIRECTORY, &path, true) != B_OK) return B_ERROR; path.Append("network"); - path.Append(name); + create_directory(path.Path(), 0755); + path.Append(name); return B_OK; } @@ -186,6 +190,81 @@ Settings::_Load() } +status_t +Settings::StartMonitoring(const BMessenger& target) +{ + fListener = target; + + BPath path; + status_t status = _GetPath("interfaces", path); + if (status < B_OK) + return status; + + node_ref ref; + BNode node; + + BPath parent; + if (path.GetParent(&parent) == B_OK) { + status = node.SetTo(parent.Path()); + if (status < B_OK) + return status; + + status = node.GetNodeRef(&ref); + if (status < B_OK) + return status; + + status = watch_node(&ref, B_WATCH_DIRECTORY, target); + if (status < B_OK) + return status; + } + + status = node.SetTo(path.Path()); + if (status < B_OK) + return status; + + status = node.GetNodeRef(&ref); + if (status < B_OK) + return status; + + return watch_node(&ref, B_WATCH_STAT, target); +} + + +status_t +Settings::StopMonitoring(const BMessenger& target) +{ + // TODO: this needs to be changed in case the server will watch + // anything else but settings + return stop_watching(target); +} + + +status_t +Settings::Update(BMessage* message) +{ + const char* name; + int32 opcode; + if (message->FindInt32("opcode", &opcode) < B_OK + || message->FindString("name", &name) < B_OK) + return B_BAD_VALUE; + + if (opcode == B_ENTRY_REMOVED) + return B_OK; + + if (!strcmp(name, "interfaces")) { + status_t status = _ConvertFromDriverSettings("interfaces", + kInterfaceTemplate, fInterfaces); + if (status < B_OK) + return status; + + BMessage update(kMsgInterfaceSettingsUpdated); + fListener.SendMessage(&update); + } + + return B_OK; +} + + status_t Settings::GetNextInterface(uint32& cookie, BMessage& interface) { diff --git a/src/servers/net/Settings.h b/src/servers/net/Settings.h index c8419f5440..1ea6e3830c 100644 --- a/src/servers/net/Settings.h +++ b/src/servers/net/Settings.h @@ -11,6 +11,7 @@ #include #include +#include class BPath; @@ -28,6 +29,10 @@ class Settings { ~Settings(); status_t GetNextInterface(uint32& cookie, BMessage& interface); + status_t StartMonitoring(const BMessenger& target); + status_t StopMonitoring(const BMessenger& target); + + status_t Update(BMessage* message); private: status_t _Load(); @@ -42,8 +47,11 @@ class Settings { status_t _ConvertFromDriverSettings(const char* path, const settings_template* settingsTemplate, BMessage& message); + BMessenger fListener; BMessage fInterfaces; bool fUpdated; }; +static const uint32 kMsgInterfaceSettingsUpdated = 'SUif'; + #endif // SETTINGS_H