diff options
Diffstat (limited to 'src/fbgui/networkdiscovery.cpp')
-rw-r--r-- | src/fbgui/networkdiscovery.cpp | 990 |
1 files changed, 990 insertions, 0 deletions
diff --git a/src/fbgui/networkdiscovery.cpp b/src/fbgui/networkdiscovery.cpp new file mode 100644 index 0000000..132429c --- /dev/null +++ b/src/fbgui/networkdiscovery.cpp @@ -0,0 +1,990 @@ +/** + * @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 <sys/types.h> +#include <signal.h> + +#include "networkdiscovery.h" + + + + +/** + * constructor + */ +NetworkDiscovery::NetworkDiscovery(QObject *parent) { + _tag = "[nd:NetworkDiscovery]"; + _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 + qxtLog->debug() << _tag << " 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()) { + qxtLog->debug() << _tag + << " 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()) { + qxtLog->debug() << _tag << "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) + { + qxtLog->debug() << _tag << "found Interface:" << nI.humanReadableName(); + if ((nI.flags() & QNetworkInterface::CanBroadcast)) { + qxtLog->debug() << _tag << " flags: can broadcast "; + } + if ((nI.flags() & QNetworkInterface::IsLoopBack)) { + qxtLog->debug() << _tag << " flags: is LoopBack "; + } + if ((nI.flags() & QNetworkInterface::IsPointToPoint)) { + qxtLog->debug() << _tag << " flags: is Point to Point "; + } + if ((nI.flags() & QNetworkInterface::IsRunning)) { + qxtLog->debug() << _tag << " flags: is Running "; + } + if ((nI.flags() & QNetworkInterface::IsUp)) { + qxtLog->debug() << _tag << " 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()); + qxtLog->debug() << _tag << " interface is down, try to bring up: " << nI.humanReadableName() ; + _ifDownList.append(nI.humanReadableName()); + } + else if (!(nI.flags() & QNetworkInterface::IsRunning)) { + _ifDownList.append(nI.humanReadableName()); + } + } + } else { + qxtLog->debug() << _tag << " 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) + { + qxtLog->debug() << _tag << "found Interface:" + << nI.humanReadableName(); + if ((nI.flags() & QNetworkInterface::CanBroadcast)) { + qxtLog->debug() << _tag << " flags: can broadcast "; + } + if ((nI.flags() & QNetworkInterface::IsLoopBack)) { + qxtLog->debug() << _tag << " flags: is LoopBack "; + } + if ((nI.flags() & QNetworkInterface::IsPointToPoint)) { + qxtLog->debug() << _tag << " flags: is Point to Point "; + } + if ((nI.flags() & QNetworkInterface::IsRunning)) { + qxtLog->debug() << _tag << " flags: is Running "; + } + if ((nI.flags() & QNetworkInterface::IsUp)) { + qxtLog->debug() << _tag << " 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 { + qxtLog->debug() << _tag << " 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) { + qxtLog->debug() << _tag << " emit addInterface : " << i; + emit addInterface(i); + } + _numberOfProcesses = _ifUpList.size(); + emit updateStatus("start dhcp client for each interface"); + runDHCPCD( _ifUpList); + } else { + qxtLog->debug() << _tag << " list is empty. Have not found usable interface. "; + emit + foreach(QString i, _ifDownList) { + qxtLog->debug() << _tag << " " << 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); + + qxtLog->debug() << _tag << " start cdhcpcd with arguments: " << _dhcpcdArguments; + + _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"); + qxtLog->debug() << _tag << " 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) { + qxtLog->debug() << _tag << " haven't found process!"; + } else { + qxtLog->debug() << _tag << " process for interface " << ifName + << " finished " << " exit code: " << exitCode + << " exit status " << exitStatus; + if (exitCode > 0) { + qxtLog->debug() << _tag << " process exited unexpected: " + << p->errorString(); + emit updateIfStatus(ifName, "process exited unexpected" + + p->errorString()); + } else { + qxtLog->debug() << _tag << " 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 { + qxtLog->debug() << _tag << " 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 + qxtLog->debug() << _tag << "replace default route"; + _networkManager->replaceDefaultRoute(ifName, + ifConf->getGateway(), mss, AF_INET); + + if (checkConnectivityViaTcp(_serverIp)) { + qxtLog->debug() << _tag << " passed connectivity check! for interface " << ifName; + emit + updateIfStatus(ifName, "connection possible"); + return true; + } else { + qxtLog->debug() << _tag << " 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 + qxtLog->debug() << _tag << " check connectivity to server: " << server; + // do host lookup + //QHostInfo hostInfo = QHostInfo::fromName(server); + QTcpSocket *tcpSocket = new QTcpSocket(this); + //qxtLog->debug() << _tag << " hostInfo first address: " << hostInfo.addresses().first().toString(); //hostInfo.addresses().first() + tcpSocket->connectToHost(server, 80); + if (!tcpSocket->waitForConnected(500)) { + qxtLog->debug() << _tag << 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) { + qxtLog->debug() << _tag << "last read before exit"; + while (client->canReadLine()) { + QString data(client->readLine()); + + data = data.trimmed(); + qxtLog->debug() << _tag << 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 data) { + + QString logMsg(data); + 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(); + //qxtLog->debug() << _tag << logMsg; + + if (_ifNameToClient.size() < _numberOfProcesses && !_ifNameToClient.contains( + interface)) { + _ifNameToClient.insert(interface, client); + } + + switch (st) { + case LOG_INFO: + switch (sst) { + case DHCP_DISCOVER: + emit changeProgressBarValue(interface, 10); + qxtLog->debug() << _tag << " " << interface << " send discover"; + break; + case DHCP_OFFER: + emit changeProgressBarValue(interface, 20); + qxtLog->debug() << _tag << " " << interface << " got offer"; + break; + case DHCP_REQUEST: + emit changeProgressBarValue(interface, 30); + qxtLog->debug() << _tag << " " << interface << " send request"; + break; + case DHCP_ACK: + emit changeProgressBarValue(interface, 40); + qxtLog->debug() << _tag << " " << interface << " ack"; + break; + case DHCP_NAK: + emit changeProgressBarValue(interface, 40); + qxtLog->debug() << _tag << " " << interface << " nak"; + break; + case DHCPCD_ARP_TEST: + emit changeProgressBarValue(interface, 50); + qxtLog->debug() << _tag << " " << interface << " do arp test"; + break; + case DHCP_DECLINE: + emit changeProgressBarValue(interface, 60); + break; + case DHCP_RELEASE: + qxtLog->debug() << _tag << " " << interface << " release"; + break; + case DHCP_INFORM: + break; + case DHCPCD_CONFIGURE: + emit changeProgressBarValue(interface, 70); + qxtLog->debug() << _tag << " " << interface << " do configure interface"; + break; + case DHCPCD_WRITE: + emit changeProgressBarValue(interface, 80); + qxtLog->debug() << _tag << " " << interface << " write conf file"; + break; + case DHCPCD_EXIT: + emit changeProgressBarValue(interface, 100); + qxtLog->debug() << _tag << " " << interface << " exiting"; + break; + case DHCPCD_LOG: + qxtLog->debug() << _tag << " received dhcpcd log: " << msg; + default: + qxtLog->debug() << _tag << " received unknown substatus: " << msg; + break; + } + break; + case LOG_ERR: + qxtLog->debug() << _tag << " received error: " << msg; + break; + default: + qxtLog->debug() << _tag << " " << logMsg; + 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); + + qxtLog->debug() << _tag << " set man conf. and check connectivity"; + + if (!checkConnectivityViaTcp(_serverIp)) { + qxtLog->debug() << _tag << " 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; + } + qxtLog->debug() << _tag << " 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 { + qxtLog->debug() << _tag << " 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 { + qxtLog->debug() << _tag << " could not open log file"; + retval = "could not open log file"; + } + } + else { + qxtLog->debug() << _tag << " log file does not exist at: " << _pathToLogFile; + retval = " log file does not exist at: " + _pathToLogFile; + } + return retval; + +} + + +/**/ +void NetworkDiscovery::killDHCPCD() { + qxtLog->debug() << " kill cdhcpcd processes"; + QProcess * p = new QProcess(this); + p->start("killall cdhcpcd"); + p->waitForFinished(); + if (p->exitCode() > 0) + qxtLog->debug() << _tag << " [tryAgain] " << p->errorString(); + + delete p; +} + + + +/**/ +void NetworkDiscovery::prepareTryAgain() { + // kill all cdhcpcd processes + killDHCPCD(); + + /* + foreach(Q_PID pid , _pidsList) { + if (kill(pid,SIGKILL) <= -1) + qDebug() << _tag << " 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() { + qxtLog->debug() << _tag << " 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); + + qxtLog->debug() << _tag << " 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) { + + qxtLog->debug() << _tag << "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) { + qxtLog->debug() + << "carrier is 1. Cable is plugged. return true"; + return true; + } else { + qxtLog->debug() + << "carrier is 0. Cable is unplugged. return false"; + return false; + } + } else { + qxtLog->debug() << _tag << "conversion error"; + } + } + } + } else { + qxtLog->debug() << _tag << "attrlist is Null"; + } + sysfs_close_class_device(class_device); + + return true; +} |