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:
@@ -10,6 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "EthernetSettingsView.h"
|
#include "EthernetSettingsView.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <Alert.h>
|
#include <Alert.h>
|
||||||
@@ -64,8 +65,7 @@ EthernetSettingsView::_PrepareRequest(struct ifreq& request, const char* name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EthernetSettingsView::_GatherInterfaces()
|
EthernetSettingsView::_GatherInterfaces() {
|
||||||
{
|
|
||||||
// iterate over all interfaces and retrieve minimal status
|
// iterate over all interfaces and retrieve minimal status
|
||||||
|
|
||||||
ifconf config;
|
ifconf config;
|
||||||
@@ -94,6 +94,7 @@ EthernetSettingsView::_GatherInterfaces()
|
|||||||
if (strncmp(interface->ifr_name, "loop", 4) && interface->ifr_name[0])
|
if (strncmp(interface->ifr_name, "loop", 4) && interface->ifr_name[0])
|
||||||
{
|
{
|
||||||
fInterfaces.AddItem(new BString(interface->ifr_name));
|
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));
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
|
||||||
|
fSettings.MakeEmpty();
|
||||||
fSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
fSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
_GatherInterfaces();
|
_GatherInterfaces();
|
||||||
|
|
||||||
@@ -236,122 +238,36 @@ EthernetSettingsView::_ShowConfiguration(BMessage* message)
|
|||||||
const char* name;
|
const char* name;
|
||||||
if (message->FindString("interface", &name) != B_OK)
|
if (message->FindString("interface", &name) != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ifreq request;
|
|
||||||
if (!_PrepareRequest(request, name))
|
|
||||||
return;
|
|
||||||
|
|
||||||
BString text = "dummy";
|
|
||||||
char address[32];
|
|
||||||
sockaddr_in* inetAddress = NULL;
|
|
||||||
|
|
||||||
// Obtain IP.
|
int i;
|
||||||
if (ioctl(fSocket, SIOCGIFADDR, &request,
|
for (i=0; i<fSettings.CountItems();i++) {
|
||||||
sizeof(request)) < 0) {
|
if (strcmp(fSettings.ItemAt(i)->GetName(), name) == 0) {
|
||||||
return;
|
fIPTextControl->SetText(fSettings.ItemAt(i)->GetIP());
|
||||||
}
|
fGatewayTextControl->SetText(fSettings.ItemAt(i)->GetGateway());
|
||||||
|
fNetMaskTextControl->SetText(fSettings.ItemAt(i)->GetNetmask());
|
||||||
inetAddress = (sockaddr_in*)&request.ifr_addr;
|
|
||||||
if (inet_ntop(AF_INET, &inetAddress->sin_addr, address,
|
|
||||||
sizeof(address)) == NULL) {
|
|
||||||
|
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;
|
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
|
// 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
|
#ifndef ETHERNET_SETTINGS_VIEW_H
|
||||||
#define ETHERNET_SETTINGS_VIEW_H
|
#define ETHERNET_SETTINGS_VIEW_H
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
#include <ObjectList.h>
|
#include <ObjectList.h>
|
||||||
#include <View.h>
|
#include <View.h>
|
||||||
|
|
||||||
@@ -46,6 +47,8 @@ class EthernetSettingsView : public BView {
|
|||||||
BTextControl* fPrimaryDNSTextControl;
|
BTextControl* fPrimaryDNSTextControl;
|
||||||
BTextControl* fSecondaryDNSTextControl;
|
BTextControl* fSecondaryDNSTextControl;
|
||||||
BObjectList<BString> fInterfaces;
|
BObjectList<BString> fInterfaces;
|
||||||
|
BObjectList<Settings> fSettings;
|
||||||
|
|
||||||
int32 fStatus;
|
int32 fStatus;
|
||||||
int fSocket;
|
int fSocket;
|
||||||
void _GatherInterfaces();
|
void _GatherInterfaces();
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ UsePrivateHeaders shared ;
|
|||||||
|
|
||||||
Preference Network :
|
Preference Network :
|
||||||
EthernetSettingsWindow.cpp
|
EthernetSettingsWindow.cpp
|
||||||
|
settings.cpp
|
||||||
EthernetSettingsView.cpp
|
EthernetSettingsView.cpp
|
||||||
EthernetSettings.cpp
|
EthernetSettings.cpp
|
||||||
: be root $(TARGET_NETWORK_LIBS)
|
: be root $(HAIKU_NETWORK_LIBS)
|
||||||
;
|
;
|
||||||
|
|
||||||
Package haiku-networksettings :
|
Package haiku-networksettings :
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
Reference in New Issue
Block a user