/**
* @class NetworkDiscovery
*
* @brief the logic behind the NetworkDiscovery.
*
* This class holds all the logic of the NetworkDiscovery. It's main task is to search for usable
* interfaces, check if they are wired (in Running state) and start a cdhcpcd process for each interface.
* It also sends signals to the ndgui class for presenting notifications to the user.
*
*/
#include <QTextStream>
#include <sys/types.h>
#include <signal.h>
#include "networkdiscovery.h"
#include <log4cxx/logger.h>
#include "qlog4cxx.h"
using namespace log4cxx;
using namespace log4cxx::helpers;
LoggerPtr ndcLogger(Logger::getLogger("fbgui.nd.core"));
/**
* constructor
*/
NetworkDiscovery::NetworkDiscovery(QObject *parent) {
_server = new QLocalServer(this);
}
/**
* destructor
*/
NetworkDiscovery::~NetworkDiscovery() {
delete _networkManager;
delete _server;
foreach(QProcess* p, _clientProcessToIfNameMap.keys()) {
delete p;
}
foreach(interfaceconfiguration* i, _ifcMap.values()) {
delete i;
}
}
/**
* initialize all important class members and start the main work.
*
* @param serverIp
* the ip of the server with which we are testing the connectivity.
*
* @param userChoice
* true if the user wishes to have a user choice. true: the chooseInterfaceDialog will be showed.
*
* @param autoUp
* true if we want to "auto Up" all down interfaces.
*
* @param pathToLogFile
* the path to the log file.
*
* @param serverPath
* the path to the server socket (default value: DEFAULT_QTSOCKETADDRESS "/var/tmp/qt_c_socket_default")
*
* @param pathToExe
* the path to the customdhcpcd exe. (default value: #define DEFAULT_QTSOCKETADDRESS "/var/tmp/qt_c_socket_default")
*
* @param args
* additional arguments for the customdhcpcd client. (default value: NULL)
*/
void NetworkDiscovery::initAndRun(QString serverIp, bool userChoice, bool autoUp, QString pathToLogFile, QString serverPath, QString pathToExe,
QStringList* args) {
_serverIp = serverIp;
_userChoice = userChoice;
_autoUp = autoUp;
_pathToLogFile = pathToLogFile;
_serverPath = serverPath;
_pathToDhcpcdExe = pathToExe;
_blocked = false;
_numberOfProcesses = 0;
_ifUpCountdown = 10;
_errorStr = "";
_networkManager = new NetworkManager();
_clientProcessToIfNameMap.clear();
_clients.clear();
_dhcpcdArguments.clear();
_ifDownList.clear();
_ifNameToClient.clear();
_ifUpList.clear();
_ifcMap.clear();
_server = new QLocalServer();
if (serverPath != DEFAULT_QTSOCKETADDRESS) {
_dhcpcdArguments.append("-q");
_dhcpcdArguments.append(serverPath);
}
/* delete the file at serverPath. this is necessary since in case the application crashes, the file still
* exists which leads to an error.
*/
if(QFile::exists(serverPath)) {
QFile::remove(serverPath);
}
emit updateStatus("try to create server socket");
if (!_server->listen(serverPath)) {
// emit signal to the gui that a critial error occoured
LOG4CXX_DEBUG(ndcLogger, "Unable to start server: " << _server->errorString());
emit
abortBoot("Unable to start server: " + _server->errorString());
return;
}
killDHCPCD();
// check if the path to the customdhcpcd file is correct
emit updateStatus("check if cdhcpcd is available");
QFileInfo fInfo(_pathToDhcpcdExe);
if (!fInfo.exists()) {
LOG4CXX_DEBUG(ndcLogger, "could not find customdhcpcd exe. Please check the path to this file.");
emit abortBoot(
"could not find customdhcpcd exe. Please check the path to this file.");
return;
}
connect(_server, SIGNAL(newConnection()), this, SLOT(handleNewConnection()));
connect(this, SIGNAL(readyForRun()), this, SLOT(slotReadyForRun()));
if (args != NULL && !args->isEmpty()) {
LOG4CXX_DEBUG(ndcLogger, "added additional args");
_dhcpcdArguments.append(*args);
}
emit updateStatus("start mainwork");
mainWork();
}
/**
* @brief the main work. Here we start with searching for usable interfaces and check the IsRunning state.
*
* the main work. Here we start with searching for usable interfaces and check the IsRunning state.
* check every second the IsRunning state. Do this as long the counter (@see _ifUpCountdown) is greater than 0.
* Default: _ifUpCountdown = 10.
*/
void NetworkDiscovery::mainWork()
{
if (_autoUp) {
emit updateStatus("search for usable interfaces (with auto Up)");
getListOfNetworkInterfacesWithAutoUp();
} else {
emit updateStatus("search for usable interfaces");
getListOfNetworkInterfaces();
}
emit updateStatus("check if interfaces are in running state");
_timer = new QTimer(this);
connect(_timer, SIGNAL(timeout()), this, SLOT(checkForIsRunning()));
_timer->start(1000);
}
/**
* searches for usable interfaces and puts them into a list.
* if the interface is down, put it in the _ifDownList, try to bring it up.
* else put it in the _ifUpList.
* usable interfaces are: can Broadcast, no loopback, no point to point, name is not in the BlackList,
*/
void NetworkDiscovery::getListOfNetworkInterfacesWithAutoUp() {
QList<QNetworkInterface> nIList = QNetworkInterface::allInterfaces();
_ifUpList.clear();
_ifDownList.clear();
if (nIList.size() > 0) {
foreach(QNetworkInterface nI, nIList)
{
LOG4CXX_DEBUG(ndcLogger, "found Interface:" << nI.humanReadableName());
if ((nI.flags() & QNetworkInterface::CanBroadcast)) {
LOG4CXX_DEBUG(ndcLogger, "flags: can broadcast ");
}
if ((nI.flags() & QNetworkInterface::IsLoopBack)) {
LOG4CXX_DEBUG(ndcLogger, "flags: is LoopBack ");
}
if ((nI.flags() & QNetworkInterface::IsPointToPoint)) {
LOG4CXX_DEBUG(ndcLogger, "flags: is Point to Point ");
}
if ((nI.flags() & QNetworkInterface::IsRunning)) {
LOG4CXX_DEBUG(ndcLogger, "flags: is Running ");
}
if ((nI.flags() & QNetworkInterface::IsUp)) {
LOG4CXX_DEBUG(ndcLogger, "flags: is Up ");
}
if (((!(nI.flags() & QNetworkInterface::CanBroadcast)
|| nI.flags() & QNetworkInterface::IsLoopBack)
|| nI.flags() & QNetworkInterface::IsPointToPoint)
|| checkBlackList(nI.humanReadableName())) {
continue;
}
if ((nI.flags() & QNetworkInterface::IsRunning)) {
_ifUpList.append(nI.humanReadableName());
}
else if (!(nI.flags() & QNetworkInterface::IsUp)) {
_networkManager->bringInterfaceUP(nI.humanReadableName());
LOG4CXX_DEBUG(ndcLogger, "interface is down, try to bring up: " << nI.humanReadableName() );
_ifDownList.append(nI.humanReadableName());
}
else if (!(nI.flags() & QNetworkInterface::IsRunning)) {
_ifDownList.append(nI.humanReadableName());
}
}
} else {
LOG4CXX_DEBUG(ndcLogger, "no interfaces found! ");
}
}
/**
* searches for usable interfaces which are up and running and put them into a list.
* usable interfaces are: can Broadcast, no loopback, no point to point, name is not in the BlackList,
*/
void NetworkDiscovery::getListOfNetworkInterfaces() {
QList<QNetworkInterface> nIList = QNetworkInterface::allInterfaces();
_ifUpList.clear();
_ifDownList.clear();
if (nIList.size() > 0) {
foreach(QNetworkInterface nI, nIList)
{
LOG4CXX_DEBUG(ndcLogger, "found Interface:" << nI.humanReadableName());
if ((nI.flags() & QNetworkInterface::CanBroadcast)) {
LOG4CXX_DEBUG(ndcLogger, "flags: can broadcast ");
}
if ((nI.flags() & QNetworkInterface::IsLoopBack)) {
LOG4CXX_DEBUG(ndcLogger, "flags: is LoopBack ");
}
if ((nI.flags() & QNetworkInterface::IsPointToPoint)) {
LOG4CXX_DEBUG(ndcLogger, "flags: is Point to Point ");
}
if ((nI.flags() & QNetworkInterface::IsRunning)) {
LOG4CXX_DEBUG(ndcLogger, "flags: is Running ");
}
if ((nI.flags() & QNetworkInterface::IsUp)) {
LOG4CXX_DEBUG(ndcLogger, "flags: is Up ");
}
if (((!(nI.flags() & QNetworkInterface::CanBroadcast)
|| nI.flags() & QNetworkInterface::IsLoopBack)
|| nI.flags() & QNetworkInterface::IsPointToPoint)
|| !(nI.flags() & QNetworkInterface::IsUp)
|| checkBlackList(nI.humanReadableName())) {
continue;
}
if (!(nI.flags() & QNetworkInterface::IsRunning)) {
_ifDownList.append(nI.humanReadableName());
} else {
_ifUpList.append(nI.humanReadableName());
}
}
} else {
LOG4CXX_DEBUG(ndcLogger, "no interfaces found! ");
}
}
/**
* only called if autoUp == true.
* check the IsRunning flag of each interface in the _ifDownList.
* connected to the timeout signal of the timer.
*/
void NetworkDiscovery::checkForIsRunning() {
bool isRunning = false;
foreach(QString i, _ifDownList) {
QNetworkInterface networkInterface = QNetworkInterface::interfaceFromName(i);
isRunning = (networkInterface.flags() & QNetworkInterface::IsRunning);
if (isRunning) {
_ifUpList.append(i);
_ifDownList.removeAt(_ifDownList.indexOf(i));
}
}
_ifUpCountdown--;
if ((_ifUpCountdown <= 0 ) || _ifDownList.isEmpty()) {
// shut down timer
_timer->stop();
delete _timer;
emit readyForRun();
}
}
/**
* emits the addInterface signal for each interface name in _ifUpList
* and calls the runDHCPCD method.
* if the _ifUpList is empty, this method emits an abortBoot signal.
* connected to the readyForRun signal.
*/
void NetworkDiscovery::slotReadyForRun() {
if (_ifUpList.size() > 0) {
foreach(QString i, _ifUpList) {
LOG4CXX_DEBUG(ndcLogger, "emit addInterface : " << i);
emit addInterface(i);
}
_numberOfProcesses = _ifUpList.size();
emit updateStatus("start dhcp client for each interface");
runDHCPCD( _ifUpList);
} else {
LOG4CXX_DEBUG(ndcLogger, "list is empty. Have not found usable interface. ");
emit
foreach(QString i, _ifDownList) {
LOG4CXX_DEBUG(ndcLogger, "" << i << " is not in running state. (check cable)");
}
abortBoot("All interfaces are not usable. (e.g. please check if all network cables are plugged in. Read the log for more informations.)");
return;
}
}
/**
* call for every interface in the list the runDHCPCD method.
*
* @param interfaces
* list of interface names.
*/
void NetworkDiscovery::runDHCPCD(QList<QString> &interfaces) {
foreach(QString nI, interfaces)
{
runDHCPCD(nI);
}
}
/**
* start a cdhcpcd process with the interface name as last argument.
*
* @param interface
* name of an interface.
*/
void NetworkDiscovery::runDHCPCD(QString interface) {
emit updateIfStatus(interface, "start DHCP");
_dhcpcdArguments.append(interface);
QProcess * p = new QProcess(this);
LOG4CXX_DEBUG(ndcLogger, "start cdhcpcd with arguments: " << _dhcpcdArguments.join(", "));
_clientProcessToIfNameMap.insert(p, interface);
p->start(_pathToDhcpcdExe, _dhcpcdArguments);
connect(p, SIGNAL(started()), this, SLOT(handleProcessStarted()));
connect(p, SIGNAL(finished(int, QProcess::ExitStatus)), this,
SLOT(handleProcessFinished(int, QProcess::ExitStatus)));
_dhcpcdArguments.removeLast();
}
/**
* This Method is called when a process is started.
*
* This Method is called when a process is started.
* It prints the message: "process started for interface: <interfaceName>".
*/
void NetworkDiscovery::handleProcessStarted() {
QProcess* p = qobject_cast<QProcess *> (QObject::sender());
QString ifName = _clientProcessToIfNameMap.value(p, "ifName");
LOG4CXX_DEBUG(ndcLogger, "process started for interface: " << ifName);
}
/**
* This Method is called when a process is finished.
*
* This Method is called when a process is finished. This slot is connected
* with the signal finished() of the QProcess class.
* If the process finishes, it will be checked if the process exited normal
* or if an unexpected error occurred. For this, we determine the sender (which is a
* QProcess), get the corresponding interface (which is stored in a map), and check
* the exitCode. Further actions are taken according to the exitCode check.
* Normal exit:
* emit changeProgressBar() to 100%
* emit updateIfStatus() to check connection
* checkConnectivity() @see NetworkDiscovery::checkConnectivity()
* Unexpected exit:
* emit updateIfStatus() to process exited unexpected
*
* @param exitCode
*
* @param exitStatus
*
* @return bool
* returns true: if the interface name i starts with a letter in the blacklist.
*
* returns false: else
*
* @see NetworkDiscovery::getListOfNetworkInterfaces()
*/
void NetworkDiscovery::handleProcessFinished(int exitCode,
QProcess::ExitStatus exitStatus) {
QProcess* p = qobject_cast<QProcess *> (QObject::sender());
QString ifName = _clientProcessToIfNameMap.value(p, "ifName");
_numberOfProcesses = _numberOfProcesses - 1;
if (!_blocked) { //_blocked becomes true, if _userChoice is false and we already found a usable interface
if (ifName.compare("ifName") == 0) {
LOG4CXX_DEBUG(ndcLogger, "haven't found process!");
} else {
LOG4CXX_DEBUG(ndcLogger, "process for interface " << ifName << " finished " << " exit code: " << exitCode << " exit status " << exitStatus);
if (exitCode > 0) {
LOG4CXX_DEBUG(ndcLogger, "process exited unexpected: " << p->errorString());
emit updateIfStatus(ifName, "process exited unexpected"
+ p->errorString());
} else {
LOG4CXX_DEBUG(ndcLogger, "process normal exit ");
emit
changeProgressBarValue(ifName, 100);
emit
updateIfStatus(ifName, "check connectivity");
if (checkConnectivity(ifName)) {
emit connectionEstablished(ifName);
if (!_userChoice) {
// blockiere jeden weiteren check
_blocked = true;
emit allProcessesFinished();
}
}
}
}
if (!_blocked) { //_blocked becomes true, if _userChoice is false and we found a usable interface
QLocalSocket *client = _ifNameToClient.value(ifName, 0);
if (client != 0) {
handleNewInput(client);
}
//_numberOfProcesses = _numberOfProcesses - 1; && _userChoice
if (_numberOfProcesses <= 0) {
emit allProcessesFinished();
}
}
} else {
LOG4CXX_DEBUG(ndcLogger, "already blocked");
emit updateIfStatus(ifName, "finished DHCP");
}
}
/**
* checks the connectivity. tries to open a TCP connection to the
* server (see _serverIp). For this it adjusts the routing table.
* (sets the gateway of the interface as default gateway)
* Gateway is written into the dhcpcd config file of this interface.
* (see DEFAULT_INTERFACE_CONF_LOCATION "/var/tmp/conf_")
*
* @param ifName
* name of a interface.
*
* @return
* true: connection is possible
* false: connection not possible
*/
bool NetworkDiscovery::checkConnectivity(QString ifName) {
int mss = 0;
// get gateway address
QString pathToGatewayFile(DEFAULT_INTERFACE_CONF_LOCATION);
pathToGatewayFile += ifName;
interfaceconfiguration* ifConf;
if (!_ifcMap.contains(ifName)) {
ifConf = new interfaceconfiguration();
_ifcMap.insert(ifName, ifConf);
}
else {
ifConf = _ifcMap.value(ifName);
}
ifConf->readConfigOutOfFile(pathToGatewayFile);
// replace default route
LOG4CXX_DEBUG(ndcLogger, "replace default route");
_networkManager->replaceDefaultRoute(ifName,
ifConf->getGateway(), mss, AF_INET);
if (checkConnectivityViaTcp(_serverIp)) {
LOG4CXX_DEBUG(ndcLogger, "passed connectivity check! for interface " << ifName);
emit
updateIfStatus(ifName, "connection possible");
return true;
} else {
LOG4CXX_DEBUG(ndcLogger, "failed connectivity check! for interface " << ifName);
emit
updateIfStatus(ifName, "connection not possible");
return false;
}
}
/**/
bool NetworkDiscovery::checkConnectivityViaTcp() {
return checkConnectivityViaTcp(_serverIp);
}
/**
* try to open a tcp connection to the server
*
* @param server
* a ip address.
*
* @return
* true: connection is possible
* false: connection not possible
*/
bool NetworkDiscovery::checkConnectivityViaTcp(QString server) {
// check connectivity via tcp connection
LOG4CXX_DEBUG(ndcLogger, "check connectivity to server: " << server);
// do host lookup
//QHostInfo hostInfo = QHostInfo::fromName(server);
QTcpSocket *tcpSocket = new QTcpSocket(this);
//LOG4CXX_DEBUG(ndcLogger, "hostInfo first address: " << hostInfo.addresses().first().toString()); //hostInfo.addresses().first()
tcpSocket->connectToHost(server, 80);
if (!tcpSocket->waitForConnected(500)) {
LOG4CXX_DEBUG(ndcLogger, tcpSocket->errorString());
_errorStr += tcpSocket->errorString();
return false;
} else {
return true;
}
delete tcpSocket;
}
/**
* same function as handleNewInput() but with a client as parameter.
*
* @param cleint
* a client
*/
void NetworkDiscovery::handleNewInput(QLocalSocket * client) {
LOG4CXX_DEBUG(ndcLogger, "last read before exit");
while (client->canReadLine()) {
QString data(client->readLine());
data = data.trimmed();
LOG4CXX_DEBUG(ndcLogger, data);
QStringList lines = data.split("\n");
for (int i = 0; i < lines.length(); i++) {
handleNewInputLine(client, lines.at(i));
}
}
}
/**
* This method is connected to the readyRead Signal of the QLocalSocket
* client.
* send an ACK to the client with every received message.
*/
void NetworkDiscovery::handleNewInput() {
QLocalSocket* socket = qobject_cast<QLocalSocket *> (QObject::sender());
QLocalSocket * client = _clients.value(socket);
QString data(client->read(DHCP_MESSAGE_SIZE));
data = data.trimmed();
QStringList lines = data.split("\n");
for (int i = 0; i < lines.length(); i++) {
handleNewInputLine(client, lines.at(i));
}
}
/**
* This Method processes the send messages.
*
* This Method processes the send messages. It splits the line
* into several components. Those components are:
* interface: interface name ==> indicates the process who send the message
* s_state: is the number representation of syslog.h LOG levels
* s_subState: is the number representation of the dhcp.c DHCP states (1 - 8) plus
* the status. h states (9 - ..)
* msg: is a message which can contain additional informations
*
* According to the s_state and s_subState we emit the changeProgressBarValue() signal
* with different values.
*
* @param client
* the client who send the message
*
* @param data
* the message. (format <interfaceName>;<state>;<subState>;<msg> )
*/
void NetworkDiscovery::handleNewInputLine(QLocalSocket * client, QString logMsg) {
if (logMsg.trimmed().size() < 1) return;
QString interface = logMsg.section(";", 0, 0);
QString s_state = logMsg.section(";", 1, 1);
QString s_subState = logMsg.section(";", 2, 2);
QString msg = logMsg.section(";", 3, 3);
int st = s_state.trimmed().toInt();
int sst = s_subState.trimmed().toInt();
//LOG4CXX_DEBUG(ndcLogger, logMsg);
if (_ifNameToClient.size() < _numberOfProcesses
&& !_ifNameToClient.contains(interface))
{
_ifNameToClient.insert(interface, client);
}
// st states
// #define LOG_EMERG 0 /* system is unusable */
// #define LOG_ALERT 1 /* action must be taken immediately */
// #define LOG_CRIT 2 /* critical conditions */
// #define LOG_ERR 3 /* error conditions */
// #define LOG_WARNING 4 /* warning conditions */
// #define LOG_NOTICE 5 /* normal but significant condition */
// #define LOG_INFO 6 /* informational */
// #define LOG_DEBUG 7 /* debug-level messages */
QString out;
QTextStream outStream(&out);
switch (sst)
{
case DHCP_DISCOVER:
emit changeProgressBarValue(interface, 10);
outStream << interface << " send discover";
break;
case DHCP_OFFER:
emit changeProgressBarValue(interface, 20);
outStream << interface << " got offer";
break;
case DHCP_REQUEST:
emit changeProgressBarValue(interface, 30);
outStream << interface << " send request";
break;
case DHCP_ACK:
emit changeProgressBarValue(interface, 40);
outStream << interface << " ack";
break;
case DHCP_NAK:
emit changeProgressBarValue(interface, 40);
outStream << interface << " nak";
break;
case DHCP_RELEASE:
outStream << interface << " release";
break;
case DHCP_INFORM:
break;
case DHCPCD_ARP_TEST:
emit changeProgressBarValue(interface, 50);
outStream << interface << " do arp test";
break;
case DHCP_DECLINE:
emit changeProgressBarValue(interface, 60);
break;
case DHCPCD_CONFIGURE:
emit changeProgressBarValue(interface, 70);
outStream << interface << " do configure interface";
break;
case DHCPCD_WRITE:
emit changeProgressBarValue(interface, 80);
outStream << interface << " write conf file";
break;
case DHCPCD_EXIT:
emit changeProgressBarValue(interface, 100);
outStream << interface << " exiting";
break;
case DHCPCD_LOG:
outStream << "received dhcpcd log: " << msg;
break;
default:
outStream << "received unknown substatus: " << msg;
break;
}
switch (st)
{
case LOG_INFO:
LOG4CXX_INFO(ndcLogger, out);
break;
case LOG_NOTICE:
LOG4CXX_WARN(ndcLogger, out);
break;
case LOG_WARNING:
LOG4CXX_WARN(ndcLogger, out);
break;
case LOG_DEBUG:
LOG4CXX_DEBUG(ndcLogger, out);
break;
case LOG_ERR:
LOG4CXX_ERROR(ndcLogger, out);
break;
default:
LOG4CXX_DEBUG(ndcLogger, out);
break;
}
}
/**
* replace the default route. sets af automatically to AF_INET
*
* @param ifName
* interface name
*
* @param gateway
* gateway address
*
* @param mss
* mss value (i think this is the metric. in most cases this value is 0)
*/
int NetworkDiscovery::ip4_replaceDefaultRoute(QString ifName, QString gateway, int mss) {
return _networkManager->replaceDefaultRoute(ifName, gateway, mss, AF_INET);
}
/**
* replace the dhcp configuration with the manual config, entered by the user.
* if we can not establish a connection with the entered values, reset to the old
* dhcp values.
*
* @param result
* a json object formated string.
*
* @return
* 0 if everything ok
*/
int NetworkDiscovery::ip4_setManualConfiguration(QVariantMap result) {
QList<QString> dns;
dns.append(result["dns"].toString());
_networkManager->ip4_setManualConfiguration(result["ifname"].toString(),
result["ipaddr"].toString(), result["netmask"].toString(),
result["broadcast"].toString(), result["gateway"].toString(), 0,
AF_INET, "/etc/", dns);
LOG4CXX_DEBUG(ndcLogger, "set man conf. and check connectivity");
if (!checkConnectivityViaTcp(_serverIp)) {
LOG4CXX_DEBUG(ndcLogger, "no connectivity. reset conf.");
interfaceconfiguration * ifc = _ifcMap.value(
result["ifname"].toString(), NULL);
if (ifc != NULL) {
dns.clear();
dns = ifc->getDnsservers().trimmed().split(" ");
_networkManager->ip4_setManualConfiguration(
result["ifname"].toString(), ifc->getIpAddress(),
ifc->getNetmask(), ifc->getBroadcast(), ifc->getGateway(),
0, AF_INET, "/etc/", dns);
}
return 0;
}
LOG4CXX_DEBUG(ndcLogger, "emit signal continueBootWithoutCheck(" << result["ifname"].toString() << ")");
emit
continueBootWithoutCheck(result["ifname"].toString());
return 0;
}
/**
* returns the gateway address, written into the dhcp config file.
*
* @param ifName
* name of the interface.
*
* @return
* gateway address as string. or empty string if no interface config was found.
*/
QString NetworkDiscovery::getGatewayForInterface(QString ifName) {
interfaceconfiguration * ifConf = _ifcMap.value(ifName, NULL);
if (ifConf != NULL)
{
return ifConf->getGateway();
}
else {
LOG4CXX_DEBUG(ndcLogger, "could not find interface configuration");
return "";
}
}
/**
* reads the log file.
*
* @return the log file as one string.
*/
QString NetworkDiscovery::readLogFile() {
// path to log file is in _pathToLogFile. initialized in initAndRun().
QString retval("the log file\n");
QFile logFile(_pathToLogFile);
if (logFile.exists()) {
if (logFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
while (!logFile.atEnd()) {
retval.append(logFile.readLine());
}
}
else {
LOG4CXX_DEBUG(ndcLogger, "could not open log file");
retval = "could not open log file";
}
}
else {
LOG4CXX_DEBUG(ndcLogger, "log file does not exist at: " << _pathToLogFile);
retval = " log file does not exist at: " + _pathToLogFile;
}
return retval;
}
/**/
void NetworkDiscovery::killDHCPCD() {
LOG4CXX_DEBUG(ndcLogger, "kill cdhcpcd processes");
QProcess * p = new QProcess(this);
p->start("killall cdhcpcd");
p->waitForFinished();
if (p->exitCode() > 0)
LOG4CXX_DEBUG(ndcLogger, "[tryAgain] " << p->errorString());
delete p;
}
/**/
void NetworkDiscovery::prepareTryAgain() {
// kill all cdhcpcd processes
killDHCPCD();
/*
foreach(Q_PID pid , _pidsList) {
if (kill(pid,SIGKILL) <= -1)
qDebug() << " error: trying to kill process: " << pid << " error: " << strerror(errno);
}
*/
// reset everything
delete _networkManager;
delete _server;
foreach(QProcess* p, _clientProcessToIfNameMap.keys())
{
delete p;
}
foreach(interfaceconfiguration* i, _ifcMap.values())
{
delete i;
}
}
/*
*TODO: to be bug fixed
*TODO: do it with kill and not QProcess("killall cdhcpcd")
*/
void NetworkDiscovery::tryAgain() {
prepareTryAgain();
initAndRun(_serverIp, _userChoice, _autoUp, _pathToLogFile, _serverPath, DEFAULT_PATHTODHCPCDEXE);
}
/**/
QVariantMap NetworkDiscovery::getInterfaceConfig(QString ifName) {
QVariantMap jsonObj;
QList<QString> dns;
interfaceconfiguration * ifc = _ifcMap.value(ifName, NULL);
if (ifc != NULL) {
jsonObj.insert("ipaddr",ifc->getIpAddress());
jsonObj.insert("netmask",ifc->getNetmask());
jsonObj.insert("broadcast",ifc->getBroadcast());
jsonObj.insert("gateway",ifc->getGateway());
dns.clear();
dns = ifc->getDnsservers().trimmed().split(" ");
jsonObj.insert("dns",dns.first());
}
return jsonObj;
}
/**
* connected to the new client arrived signal.
* connects the client readyRead signal with the handleNewInput slot.
*/
void NetworkDiscovery::handleNewConnection() {
LOG4CXX_DEBUG(ndcLogger, "New Connection arrived");
/*QLocalSocket **/
_client = _server->nextPendingConnection();
_clients.insert(_client, _client);
connect(_client, SIGNAL(disconnected()), this,
SLOT(handleClientDisconnect()));
connect(_client, SIGNAL(readyRead()), this, SLOT(handleNewInput()));
}
/**
* called when a client disconnects.
*/
void NetworkDiscovery::handleClientDisconnect() {
QLocalSocket* socket = qobject_cast<QLocalSocket *> (QObject::sender());
QLocalSocket * client = _clients.value(socket);
LOG4CXX_DEBUG(ndcLogger, "disconnect client");
handleNewInput(client);
client->deleteLater();
}
/**
* This Method implements a blacklist.
*
* This Method implements a blacklist. We check the fist character
* of the interface name. if this letter is in the list, we return true.
* True means, that this interface won't be put into the result list of
* getListOfNetworkInterfaces().
*
* @param i
* is a interface name.
*
* @return bool
* returns true: if the interface name i starts with a letter in the blacklist.
*
* returns false: else
*
* @see NetworkDiscovery::getListOfNetworkInterfaces()
*/
bool NetworkDiscovery::checkBlackList(QString i) {
if (i.startsWith("v", Qt::CaseInsensitive)) {
return true;
} else if (i.startsWith("d", Qt::CaseInsensitive)) {
return true;
} else {
return false;
}
}
/**/
QString NetworkDiscovery::GetErrorStr() {
return _errorStr;
}
//////////////////////////////////////////////////////////////////////////////////////
/**
* not used so far. checks the carrier state using the sysfs library.
* if carrier = 1 ==> the interface is running.
* interfaces have to be up in order to get right results.
*
* @param interface
* name of the interface
*/
bool NetworkDiscovery::checkCarrierState(QString interface) {
LOG4CXX_DEBUG(ndcLogger, "check carrier state for interface " << interface);
QByteArray ba = interface.toAscii();
const char * iface = ba.data();
struct sysfs_class_device *class_device = sysfs_open_class_device("net",
iface);
struct dlist *attrlist = sysfs_get_classdev_attributes(class_device);
if (attrlist != NULL) {
struct sysfs_attribute *attr = NULL;
dlist_for_each_data(attrlist, attr, struct sysfs_attribute) {
if (strcmp("carrier", attr->name) == 0) {
QString value(attr->value);
bool ok = false;
bool * pok = &ok;
int v = value.toInt(pok);
if (*pok) {
if (v == 1) {
LOG4CXX_DEBUG(ndcLogger, "carrier is 1. Cable is plugged. return true");
return true;
} else {
LOG4CXX_DEBUG(ndcLogger, "carrier is 0. Cable is unplugged. return false");
return false;
}
} else {
LOG4CXX_DEBUG(ndcLogger, "conversion error");
}
}
}
} else {
LOG4CXX_DEBUG(ndcLogger, "attrlist is Null");
}
sysfs_close_class_device(class_device);
return true;
}