* Added "services" to the network settings, and refactored the settings class a bit
to be easier extendable with more classes. * Fixed a bug in the settings that caused updated settings to be appended to the existing ones (missing BMessage::MakeEmpty()). * Started services system, doesn't do anything useful yet (inetd replacement). * Fixed the bug that caused the loopback default netmask to be incorrectly chosen; removed the temporary fix Bruno introduced before. The same bug has been in ifconfig where I copied the code from (but wrote it there, too) :-). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19609 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d2980e876d
commit
fc398fa2ab
@ -526,7 +526,7 @@ configure_interface(int socket, const char* name, char* const* args,
|
||||
if (!hasMask && hasAddress && kFamilies[familyIndex].family == AF_INET
|
||||
&& ioctl(socket, SIOCGIFNETMASK, &request, sizeof(struct ifreq)) == 0
|
||||
&& request.ifr_mask.sa_family == AF_UNSPEC) {
|
||||
// generate standard netmask if it doesn't have one yet
|
||||
// generate standard netmask if it doesn't have one yet
|
||||
sockaddr_in *netmask = (sockaddr_in *)&mask;
|
||||
netmask->sin_len = sizeof(sockaddr_in);
|
||||
netmask->sin_family = AF_INET;
|
||||
@ -537,7 +537,7 @@ configure_interface(int socket, const char* name, char* const* args,
|
||||
|| (ntohl(net) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
|
||||
// class A, or loopback
|
||||
netmask->sin_addr.s_addr = IN_CLASSA_NET;
|
||||
} if (IN_CLASSB(net)) {
|
||||
} else if (IN_CLASSB(net)) {
|
||||
// class B
|
||||
netmask->sin_addr.s_addr = IN_CLASSB_NET;
|
||||
} else {
|
||||
|
@ -13,6 +13,7 @@ Server net_server :
|
||||
Settings.cpp
|
||||
AutoconfigLooper.cpp
|
||||
DHCPClient.cpp
|
||||
Services.cpp
|
||||
;
|
||||
|
||||
LinkAgainst net_server :
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "AutoconfigLooper.h"
|
||||
#include "NetServer.h"
|
||||
#include "Services.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include <Alert.h>
|
||||
@ -56,9 +57,11 @@ class NetServer : public BApplication {
|
||||
void _ConfigureDevices(int socket, const char* path);
|
||||
void _ConfigureInterfaces(int socket);
|
||||
void _BringUpInterfaces();
|
||||
void _StartServices();
|
||||
|
||||
Settings fSettings;
|
||||
LooperMap fDeviceMap;
|
||||
BMessenger fServices;
|
||||
};
|
||||
|
||||
|
||||
@ -212,6 +215,7 @@ NetServer::ReadyToRun()
|
||||
{
|
||||
fSettings.StartMonitoring(this);
|
||||
_BringUpInterfaces();
|
||||
_StartServices();
|
||||
}
|
||||
|
||||
|
||||
@ -235,6 +239,15 @@ NetServer::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgServiceSettingsUpdated:
|
||||
{
|
||||
BMessage update = fSettings.Services();
|
||||
update.what = kMsgUpdateServices;
|
||||
|
||||
fServices.SendMessage(&update);
|
||||
break;
|
||||
}
|
||||
|
||||
case kMsgConfigureInterface:
|
||||
{
|
||||
if (!message->ReturnAddress().IsTargetLocal()) {
|
||||
@ -455,7 +468,7 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage
|
||||
if (!hasMask && hasAddress && kFamilies[familyIndex].family == AF_INET
|
||||
&& ioctl(familySocket, SIOCGIFNETMASK, &request, sizeof(struct ifreq)) == 0
|
||||
&& request.ifr_mask.sa_family == AF_UNSPEC) {
|
||||
// generate standard netmask if it doesn't have one yet
|
||||
// generate standard netmask if it doesn't have one yet
|
||||
sockaddr_in *netmask = (sockaddr_in *)&mask;
|
||||
netmask->sin_len = sizeof(sockaddr_in);
|
||||
netmask->sin_family = AF_INET;
|
||||
@ -466,7 +479,7 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage
|
||||
|| (ntohl(net) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
|
||||
// class A, or loopback
|
||||
netmask->sin_addr.s_addr = IN_CLASSA_NET;
|
||||
} if (IN_CLASSB(net)) {
|
||||
} else if (IN_CLASSB(net)) {
|
||||
// class B
|
||||
netmask->sin_addr.s_addr = IN_CLASSB_NET;
|
||||
} else {
|
||||
@ -665,7 +678,6 @@ NetServer::_BringUpInterfaces()
|
||||
BMessage address;
|
||||
address.AddString("family", "inet");
|
||||
address.AddString("address", "127.0.0.1");
|
||||
address.AddString("mask", "255.0.0.0");
|
||||
interface.AddMessage("address", &address);
|
||||
|
||||
_ConfigureInterface(socket, interface);
|
||||
@ -680,6 +692,17 @@ NetServer::_BringUpInterfaces()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NetServer::_StartServices()
|
||||
{
|
||||
BHandler* services = new (std::nothrow) Services(fSettings.Services());
|
||||
if (services != NULL) {
|
||||
AddHandler(services);
|
||||
fServices = BMessenger(services);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
|
225
src/servers/net/Services.cpp
Normal file
225
src/servers/net/Services.cpp
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
|
||||
|
||||
#include "Services.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include <Autolock.h>
|
||||
|
||||
#include <new>
|
||||
#include <sys/socket.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
struct service_address {
|
||||
int socket;
|
||||
int family;
|
||||
uint16 port;
|
||||
sockaddr address;
|
||||
};
|
||||
|
||||
typedef vector<service_address> AddressList;
|
||||
|
||||
struct service {
|
||||
std::string name;
|
||||
std::string launch;
|
||||
int type;
|
||||
int protocol;
|
||||
uint16 port;
|
||||
uid_t user;
|
||||
gid_t group;
|
||||
AddressList addresses;
|
||||
|
||||
~service();
|
||||
bool operator!=(const struct service& other);
|
||||
bool operator==(const struct service& other);
|
||||
};
|
||||
|
||||
|
||||
service::~service()
|
||||
{
|
||||
// close all open sockets
|
||||
AddressList::const_iterator iterator = addresses.begin();
|
||||
for (; iterator != addresses.end(); iterator++) {
|
||||
const service_address& address = *iterator;
|
||||
|
||||
close(address.socket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
service::operator!=(const struct service& other)
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
service::operator==(const struct service& other)
|
||||
{
|
||||
if (name != other.name
|
||||
|| launch != other.launch
|
||||
|| type != other.type
|
||||
|| protocol != other.protocol
|
||||
|| port != other.port)
|
||||
return false;
|
||||
|
||||
// TODO: compare addresses!
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
Services::Services(const BMessage& services)
|
||||
:
|
||||
fUpdate(0)
|
||||
{
|
||||
_Update(services);
|
||||
|
||||
fListener = spawn_thread(_Listener, "services listener", B_NORMAL_PRIORITY, this);
|
||||
if (fListener >= B_OK)
|
||||
resume_thread(fListener);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Services::~Services()
|
||||
{
|
||||
wait_for_thread(fListener, NULL);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Services::InitCheck() const
|
||||
{
|
||||
return fListener >= B_OK ? B_OK : fListener;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Services::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kMsgServiceSettingsUpdated:
|
||||
_Update(*message);
|
||||
break;
|
||||
|
||||
default:
|
||||
BHandler::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Services::_StartService(struct service& service)
|
||||
{
|
||||
// add service to maps
|
||||
|
||||
fNameMap[service.name] = &service;
|
||||
|
||||
AddressList::const_iterator iterator = service.addresses.begin();
|
||||
for (; iterator != service.addresses.end(); iterator++) {
|
||||
const service_address& address = *iterator;
|
||||
|
||||
fSocketMap[address.socket] = &service;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Services::_StopService(struct service& service)
|
||||
{
|
||||
// remove service from maps
|
||||
{
|
||||
ServiceNameMap::iterator iterator = fNameMap.find(service.name);
|
||||
if (iterator != fNameMap.end())
|
||||
fNameMap.erase(iterator);
|
||||
}
|
||||
{
|
||||
AddressList::const_iterator iterator = service.addresses.begin();
|
||||
for (; iterator != service.addresses.end(); iterator++) {
|
||||
const service_address& address = *iterator;
|
||||
|
||||
ServiceSocketMap::iterator socketIterator = fSocketMap.find(address.socket);
|
||||
if (socketIterator != fSocketMap.end())
|
||||
fSocketMap.erase(socketIterator);
|
||||
}
|
||||
}
|
||||
|
||||
delete &service;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Services::_ToService(const BMessage& message, struct service*& service)
|
||||
{
|
||||
// get mandatory fields
|
||||
const char* name;
|
||||
const char* launch;
|
||||
if (message.FindString("name", &name) != B_OK
|
||||
|| message.FindString("launch", &launch) != B_OK)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
service = new (std::nothrow) ::service;
|
||||
if (service == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
service->name = name;
|
||||
service->launch = launch;
|
||||
|
||||
// TODO: fill in other fields
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Services::_Update(const BMessage& services)
|
||||
{
|
||||
BAutolock locker(fLock);
|
||||
fUpdate++;
|
||||
|
||||
BMessage message;
|
||||
for (int32 index = 0; services.FindMessage("service", index,
|
||||
&message) == B_OK; index++) {
|
||||
const char* name;
|
||||
if (message.FindString("name", &name) != B_OK)
|
||||
continue;
|
||||
|
||||
struct service* service;
|
||||
if (_ToService(message, service) != B_OK)
|
||||
continue;
|
||||
|
||||
ServiceNameMap::iterator iterator = fNameMap.find(name);
|
||||
if (iterator == fNameMap.end()) {
|
||||
// this service does not exist yet, start it
|
||||
_StartService(*service);
|
||||
} else {
|
||||
// this service does already exist - check for any changes
|
||||
|
||||
if (service != iterator->second) {
|
||||
_StopService(*iterator->second);
|
||||
_StartService(*service);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
Services::_Listener(void* self)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
50
src/servers/net/Services.h
Normal file
50
src/servers/net/Services.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*/
|
||||
#ifndef SERVICES_H
|
||||
#define SERVICES_H
|
||||
|
||||
|
||||
#include <Handler.h>
|
||||
#include <Locker.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
struct service;
|
||||
typedef std::map<std::string, service*> ServiceNameMap;
|
||||
typedef std::map<int, service*> ServiceSocketMap;
|
||||
|
||||
|
||||
class Services : public BHandler {
|
||||
public:
|
||||
Services(const BMessage& services);
|
||||
virtual ~Services();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
status_t _StartService(struct service& service);
|
||||
status_t _StopService(struct service& service);
|
||||
status_t _ToService(const BMessage& message, struct service*& service);
|
||||
void _Update(const BMessage& services);
|
||||
int32 _CompareServices(struct service& a, struct service& b);
|
||||
static status_t _Listener(void* self);
|
||||
|
||||
thread_id fListener;
|
||||
BLocker fLock;
|
||||
ServiceNameMap fNameMap;
|
||||
ServiceSocketMap fSocketMap;
|
||||
int32 fUpdate;
|
||||
};
|
||||
|
||||
const static uint32 kMsgUpdateServices = 'srvU';
|
||||
|
||||
#endif // SERVICES_H
|
@ -19,6 +19,8 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// Interface templates
|
||||
|
||||
const static settings_template kInterfaceAddressTemplate[] = {
|
||||
{B_STRING_TYPE, "family", NULL},
|
||||
{B_STRING_TYPE, "address", NULL},
|
||||
@ -30,7 +32,7 @@ const static settings_template kInterfaceAddressTemplate[] = {
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
const static settings_template kInterfaceDeviceTemplate[] = {
|
||||
const static settings_template kInterfaceTemplate[] = {
|
||||
{B_STRING_TYPE, "device", NULL},
|
||||
{B_MESSAGE_TYPE, "address", kInterfaceAddressTemplate},
|
||||
{B_INT32_TYPE, "flags", NULL},
|
||||
@ -39,8 +41,32 @@ const static settings_template kInterfaceDeviceTemplate[] = {
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
const static settings_template kInterfaceTemplate[] = {
|
||||
{B_MESSAGE_TYPE, "interface", kInterfaceDeviceTemplate},
|
||||
const static settings_template kInterfacesTemplate[] = {
|
||||
{B_MESSAGE_TYPE, "interface", kInterfaceTemplate},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
// Service templates
|
||||
|
||||
const static settings_template kServiceAddressTemplate[] = {
|
||||
{B_STRING_TYPE, "family", NULL},
|
||||
{B_STRING_TYPE, "address", NULL},
|
||||
{B_INT32_TYPE, "port", NULL},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
const static settings_template kServiceTemplate[] = {
|
||||
{B_STRING_TYPE, "name", NULL},
|
||||
{B_MESSAGE_TYPE, "address", kServiceAddressTemplate},
|
||||
{B_STRING_TYPE, "user", NULL},
|
||||
{B_STRING_TYPE, "group", NULL},
|
||||
{B_STRING_TYPE, "launch", NULL},
|
||||
{B_INT32_TYPE, "port", NULL},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
const static settings_template kServicesTemplate[] = {
|
||||
{B_MESSAGE_TYPE, "service", kServiceTemplate},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
@ -76,7 +102,8 @@ Settings::_GetPath(const char* name, BPath& path)
|
||||
path.Append("network");
|
||||
create_directory(path.Path(), 0755);
|
||||
|
||||
path.Append(name);
|
||||
if (name != NULL)
|
||||
path.Append(name);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -147,6 +174,8 @@ status_t
|
||||
Settings::_ConvertFromDriverSettings(const driver_settings& settings,
|
||||
const settings_template* settingsTemplate, BMessage& message)
|
||||
{
|
||||
message.MakeEmpty();
|
||||
|
||||
for (int32 i = 0; i < settings.parameter_count; i++) {
|
||||
status_t status = _ConvertFromDriverParameter(settings.parameters[i],
|
||||
settingsTemplate, message);
|
||||
@ -185,49 +214,67 @@ Settings::_ConvertFromDriverSettings(const char* name,
|
||||
|
||||
|
||||
status_t
|
||||
Settings::_Load()
|
||||
Settings::_Load(const char* name, uint32* _type)
|
||||
{
|
||||
return _ConvertFromDriverSettings("interfaces", kInterfaceTemplate, fInterfaces);
|
||||
status_t status = B_ENTRY_NOT_FOUND;
|
||||
|
||||
if (name == NULL || !strcmp(name, "interfaces")) {
|
||||
status = _ConvertFromDriverSettings("interfaces", kInterfacesTemplate,
|
||||
fInterfaces);
|
||||
if (status == B_OK && _type != NULL)
|
||||
*_type = kMsgInterfaceSettingsUpdated;
|
||||
}
|
||||
if (name == NULL || !strcmp(name, "services")) {
|
||||
status = _ConvertFromDriverSettings("services", kServicesTemplate,
|
||||
fServices);
|
||||
if (status == B_OK && _type != NULL)
|
||||
*_type = kMsgServiceSettingsUpdated;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Settings::_StartWatching(const char* name, const BMessenger& target)
|
||||
{
|
||||
BPath path;
|
||||
status_t status = _GetPath(name, path);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
BNode node;
|
||||
status = node.SetTo(path.Path());
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
node_ref ref;
|
||||
status = node.GetNodeRef(&ref);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
return watch_node(&ref, name != NULL ? B_WATCH_STAT : B_WATCH_DIRECTORY,
|
||||
target);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Settings::StartMonitoring(const BMessenger& target)
|
||||
{
|
||||
if (_IsWatching(target))
|
||||
return B_OK;
|
||||
if (_IsWatching())
|
||||
StopMonitoring(fListener);
|
||||
|
||||
fListener = target;
|
||||
|
||||
BPath path;
|
||||
status_t status = _GetPath("interfaces", path);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
status_t status = _StartWatching(NULL, target);
|
||||
if (status == B_OK)
|
||||
status = _StartWatching("interfaces", target);
|
||||
if (status == B_OK)
|
||||
status = _StartWatching("services", target);
|
||||
|
||||
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);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -252,13 +299,9 @@ Settings::Update(BMessage* message)
|
||||
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);
|
||||
uint32 type;
|
||||
if (_Load(name, &type) == B_OK) {
|
||||
BMessage update(type);
|
||||
fListener.SendMessage(&update);
|
||||
}
|
||||
|
||||
@ -277,3 +320,22 @@ Settings::GetNextInterface(uint32& cookie, BMessage& interface)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Settings::GetNextService(uint32& cookie, BMessage& service)
|
||||
{
|
||||
status_t status = fServices.FindMessage("service", cookie, &service);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
cookie++;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
const BMessage&
|
||||
Settings::Services() const
|
||||
{
|
||||
return fServices;
|
||||
}
|
||||
|
||||
|
@ -29,15 +29,19 @@ class Settings {
|
||||
~Settings();
|
||||
|
||||
status_t GetNextInterface(uint32& cookie, BMessage& interface);
|
||||
status_t GetNextService(uint32& cookie, BMessage& service);
|
||||
const BMessage& Services() const;
|
||||
|
||||
status_t StartMonitoring(const BMessenger& target);
|
||||
status_t StopMonitoring(const BMessenger& target);
|
||||
|
||||
status_t Update(BMessage* message);
|
||||
|
||||
private:
|
||||
status_t _Load();
|
||||
status_t _Load(const char* name = NULL, uint32* _type = NULL);
|
||||
status_t _GetPath(const char* name, BPath& path);
|
||||
|
||||
status_t _StartWatching(const char* name, const BMessenger& target);
|
||||
const settings_template* _FindSettingsTemplate(const settings_template* settingsTemplate,
|
||||
const char* name);
|
||||
status_t _ConvertFromDriverParameter(const driver_parameter& parameter,
|
||||
@ -47,11 +51,16 @@ class Settings {
|
||||
status_t _ConvertFromDriverSettings(const char* path,
|
||||
const settings_template* settingsTemplate, BMessage& message);
|
||||
|
||||
bool _IsWatching(const BMessenger& target) const { return fListener == target; }
|
||||
bool _IsWatching() const { return fListener.IsValid(); }
|
||||
|
||||
BMessenger fListener;
|
||||
BMessage fInterfaces;
|
||||
BMessage fServices;
|
||||
bool fUpdated;
|
||||
};
|
||||
|
||||
static const uint32 kMsgInterfaceSettingsUpdated = 'SUif';
|
||||
static const uint32 kMsgServiceSettingsUpdated = 'SUsv';
|
||||
|
||||
#endif // SETTINGS_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user