patch by Andre Garzia:

* extracted a settings class from the view, now a dynamic number of ethernet
  devices is handled at the same time
* resolv.conf is parsed to extract the nameservers


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21970 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2007-08-15 21:57:41 +00:00
parent 07580bfab4
commit 6b9d63b18f
5 changed files with 273 additions and 109 deletions
+24 -108
View File
@@ -10,6 +10,7 @@
*/
#include "EthernetSettingsView.h"
#include "settings.h"
#include <Application.h>
#include <Alert.h>
@@ -64,8 +65,7 @@ EthernetSettingsView::_PrepareRequest(struct ifreq& request, const char* name)
}
void
EthernetSettingsView::_GatherInterfaces()
{
EthernetSettingsView::_GatherInterfaces() {
// iterate over all interfaces and retrieve minimal status
ifconf config;
@@ -94,6 +94,7 @@ EthernetSettingsView::_GatherInterfaces()
if (strncmp(interface->ifr_name, "loop", 4) && interface->ifr_name[0])
{
fInterfaces.AddItem(new BString(interface->ifr_name));
fSettings.AddItem(new Settings(interface->ifr_name));
}
@@ -130,6 +131,7 @@ EthernetSettingsView::EthernetSettingsView(BRect rect)
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fSettings.MakeEmpty();
fSocket = socket(AF_INET, SOCK_DGRAM, 0);
_GatherInterfaces();
@@ -236,122 +238,36 @@ EthernetSettingsView::_ShowConfiguration(BMessage* message)
const char* name;
if (message->FindString("interface", &name) != B_OK)
return;
ifreq request;
if (!_PrepareRequest(request, name))
return;
BString text = "dummy";
char address[32];
sockaddr_in* inetAddress = NULL;
// Obtain IP.
if (ioctl(fSocket, SIOCGIFADDR, &request,
sizeof(request)) < 0) {
return;
}
inetAddress = (sockaddr_in*)&request.ifr_addr;
if (inet_ntop(AF_INET, &inetAddress->sin_addr, address,
sizeof(address)) == NULL) {
int i;
for (i=0; i<fSettings.CountItems();i++) {
if (strcmp(fSettings.ItemAt(i)->GetName(), name) == 0) {
fIPTextControl->SetText(fSettings.ItemAt(i)->GetIP());
fGatewayTextControl->SetText(fSettings.ItemAt(i)->GetGateway());
fNetMaskTextControl->SetText(fSettings.ItemAt(i)->GetNetmask());
if (fSettings.ItemAt(i)->fNameservers.CountItems() == 2) {
fSecondaryDNSTextControl->SetText(
fSettings.ItemAt(i)->fNameservers.ItemAt(1)->String());
}
if (fSettings.ItemAt(i)->fNameservers.CountItems() >= 1) {
fPrimaryDNSTextControl->SetText(
fSettings.ItemAt(i)->fNameservers.ItemAt(0)->String());
}
} else {
return;
}
fIPTextControl->SetText(address);
// Obtain netmask.
if (ioctl(fSocket, SIOCGIFNETMASK, &request,
sizeof(request)) < 0) {
return;
}
inetAddress = (sockaddr_in*)&request.ifr_mask;
if (inet_ntop(AF_INET, &inetAddress->sin_addr, address,
sizeof(address)) == NULL) {
return;
}
fNetMaskTextControl->SetText(address);
// Obtain gateway
char* gwAddress;
ifconf config;
config.ifc_len = sizeof(config.ifc_value);
if (ioctl(fSocket, SIOCGRTSIZE, &config, sizeof(struct ifconf)) < 0)
return;
uint32 size = (uint32)config.ifc_value;
if (size == 0)
return;
void *buffer = malloc(size);
if (buffer == NULL)
return;
config.ifc_len = size;
config.ifc_buf = buffer;
if (ioctl(fSocket, SIOCGRTTABLE, &config, sizeof(struct ifconf)) < 0) {
free(buffer);
return;
}
ifreq *interface = (ifreq *)buffer;
ifreq *end = (ifreq *)((uint8 *)buffer + size);
while (interface < end) {
route_entry& route = interface->ifr_route;
if (route.flags & RTF_GATEWAY) {
inetAddress = (sockaddr_in *)route.gateway;
gwAddress = inet_ntoa(inetAddress->sin_addr);
fGatewayTextControl->SetText(gwAddress);
}
int32 addressSize = 0;
if (route.destination != NULL)
addressSize += route.destination->sa_len;
if (route.mask != NULL)
addressSize += route.mask->sa_len;
if (route.gateway != NULL)
addressSize += route.gateway->sa_len;
interface = (ifreq *)((addr_t)interface +
IF_NAMESIZE + sizeof(route_entry) + addressSize);
}
free(buffer);
// Obtain DNS
//resolv.conf is always actual.
BFile file;
BString* line;
int i = 0;
char* ch = "0";
if (file.SetTo("/etc/resolv.conf", B_READ_ONLY) != B_OK)
return;
off_t length;
file.GetSize(&length);
/*
The idea here is to iterate over resolv.conf
and look for the nameservers.
Both netserver and DHCPClient will write to resolv.conf
so we can trust that the information on the file is actual.
I need help with this routine :$
*/
@@ -11,6 +11,7 @@
#ifndef ETHERNET_SETTINGS_VIEW_H
#define ETHERNET_SETTINGS_VIEW_H
#include "settings.h"
#include <ObjectList.h>
#include <View.h>
@@ -46,6 +47,8 @@ class EthernetSettingsView : public BView {
BTextControl* fPrimaryDNSTextControl;
BTextControl* fSecondaryDNSTextControl;
BObjectList<BString> fInterfaces;
BObjectList<Settings> fSettings;
int32 fStatus;
int fSocket;
void _GatherInterfaces();
+2 -1
View File
@@ -6,9 +6,10 @@ UsePrivateHeaders shared ;
Preference Network :
EthernetSettingsWindow.cpp
settings.cpp
EthernetSettingsView.cpp
EthernetSettings.cpp
: be root $(TARGET_NETWORK_LIBS)
: be root $(HAIKU_NETWORK_LIBS)
;
Package haiku-networksettings :
+197
View File
@@ -0,0 +1,197 @@
/*
* Copyright 2004-2007 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Author:
* Andre Alves Garzia, [email protected]
*/
#include "settings.h"
#include <String.h>
#include <File.h>
#include <Path.h>
#include <SupportDefs.h>
#include <AutoDeleter.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
Settings::Settings(const char *name)
{
fSocket = socket(AF_INET, SOCK_DGRAM, 0);
fName = name;
ReadConfiguration();
}
Settings::~Settings()
{
close(fSocket);
}
bool
Settings::_PrepareRequest(struct ifreq& request)
{
//This function is used for talking direct to the stack.
//It´s used by _ShowConfiguration.
const char* name = fName.String();
if (strlen(name) > IF_NAMESIZE)
return false;
strcpy(request.ifr_name, name);
return true;
}
void
Settings::ReadConfiguration()
{
ifreq request;
if (!_PrepareRequest(request))
return;
BString text = "dummy";
char address[32];
sockaddr_in* inetAddress = NULL;
// Obtain IP.
if (ioctl(fSocket, SIOCGIFADDR, &request,
sizeof(request)) < 0) {
return;
}
inetAddress = (sockaddr_in*)&request.ifr_addr;
if (inet_ntop(AF_INET, &inetAddress->sin_addr, address,
sizeof(address)) == NULL) {
return;
}
fIP = address;
// Obtain netmask.
if (ioctl(fSocket, SIOCGIFNETMASK, &request,
sizeof(request)) < 0) {
return;
}
inetAddress = (sockaddr_in*)&request.ifr_mask;
if (inet_ntop(AF_INET, &inetAddress->sin_addr, address,
sizeof(address)) == NULL) {
return;
}
fNetmask = address;
// Obtain gateway
char* gwAddress;
ifconf config;
config.ifc_len = sizeof(config.ifc_value);
if (ioctl(fSocket, SIOCGRTSIZE, &config, sizeof(struct ifconf)) < 0)
return;
uint32 size = (uint32)config.ifc_value;
if (size == 0)
return;
void *buffer = malloc(size);
if (buffer == NULL)
return;
MemoryDeleter bufferDeleter(buffer);
config.ifc_len = size;
config.ifc_buf = buffer;
if (ioctl(fSocket, SIOCGRTTABLE, &config, sizeof(struct ifconf)) < 0)
return;
ifreq *interface = (ifreq *)buffer;
ifreq *end = (ifreq *)((uint8 *)buffer + size);
while (interface < end) {
route_entry& route = interface->ifr_route;
if (route.flags & RTF_GATEWAY) {
inetAddress = (sockaddr_in *)route.gateway;
gwAddress = inet_ntoa(inetAddress->sin_addr);
fGateway = gwAddress;
}
int32 addressSize = 0;
if (route.destination != NULL)
addressSize += route.destination->sa_len;
if (route.mask != NULL)
addressSize += route.mask->sa_len;
if (route.gateway != NULL)
addressSize += route.gateway->sa_len;
interface = (ifreq *)((addr_t)interface +
IF_NAMESIZE + sizeof(route_entry) + addressSize);
}
bufferDeleter.Detach();
free(buffer);
// Now that silly DNS problem...
fNameservers.MakeEmpty();
#define MATCH(line, name) \
(!strncmp(line, name, sizeof(name) - 1) && \
(line[sizeof(name) - 1] == ' ' || \
line[sizeof(name) - 1] == '\t'))
int nserv = 0;
char buf[1024];
register FILE *fp;
register char *cp, **pp;
register int n;
int MAXNS = 2;
if ((fp = fopen("/etc/resolv.conf", "r")) != NULL) {
/* read the config file */
while (fgets(buf, sizeof(buf), fp) != NULL) {
/* skip comments */
if (*buf == ';' || *buf == '#')
continue;
/* read nameservers to query */
if (MATCH(buf, "nameserver") && nserv < MAXNS) {
char sbuf[2];
cp = buf + sizeof("nameserver") - 1;
while (*cp == ' ' || *cp == '\t')
cp++;
cp[strcspn(cp, ";# \t\n")] = '\0';
if ((*cp != '\0') && (*cp != '\n')) {
fNameservers.AddItem(new BString(cp));
nserv++;
}
}
continue;
}
fclose(fp);
}
}
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright 2004-2007 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Author:
* Andre Alves Garzia, [email protected]
*/
#ifndef SETTINGS_H
#define SETTINGS_H
#include <ObjectList.h>
#include <String.h>
class Settings {
public:
Settings(const char* name);
virtual ~Settings();
void SetName(BString name);
void SetIP(BString ip);
void SetGateway(BString ip);
void SetNetmask(BString ip);
void SetAutoConfigure(bool t);
const char* GetIP() {return fIP.String(); }
const char* GetGateway() {return fGateway.String(); }
const char* GetNetmask() {return fNetmask.String(); }
const char* GetName() {return fName.String(); }
bool GetAutoConfigure() const {return fAuto; }
BObjectList<BString> fNameservers;
void SaveProfile(BString profileName);
void LoadProfile(BString profileName);
void SaveConfiguration();
void ReadConfiguration();
private:
bool _PrepareRequest(struct ifreq& request);
BString fIP;
BString fGateway;
BString fNetmask;
BString fName;
int fSocket;
bool fAuto;
};
#endif /* SETTINGS_H */