summaryrefslogblamecommitdiffstats
path: root/src/fbgui/networkdiscovery.cpp
blob: 4e08e8084536da7844aca34554c1a2aa35ab0d1e (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11










                                                                                                         
                      
 


                      

                             






                                                        



                                                     

 



                                       

                               


                                                                
                                                              

                         

 


                                                                  


                                                                                                                      


                                                                                               
                                                                       
 
                                 
 



                               
                       








                                               
 
                                                           
                                              
                                                           

                                                                                                                 

                                           
 

                                                 

         


                                                    
                                                                       

                                                                                      




                                                                               

                     
                                                                











                                                                                                        

                                                                                     

                                               
                                                                  
                                               

                                            
                   
 


                                                                           






                                                                                                               






                                                                                          
                                                                      


                                                                            

 





                                                                                                      

                            

                                                     






















                                                                                               
                         












                                                                                                                  
                
                                                                  


         
   





















                                                                                                  


                                                                 
   


                                            

                                                                                          






                                                                                      
                                                             


                                  
                              

         
 





                                                                     
                                      

                                               
                                                                              
                                             
                 
                                                      

                                                                     
                                     
                

                                                                                    
                    
                                                 
                                                                                                       
                 

                                                                                                                                                                
                       
         
 


                                                                           






                                                              


                                         

 






                                                                    
                                                     


                                           

                                                                                         

                                                       
                                                   





                                                                                
   





                                                                           
                                                                  
                                                                      
                                                                              

 














                                                                                    














                                                                                    
                                                                  



                                                                                                                 
                                                                           
                        


                                                                                                                                                           
                                           



                                                                                                   
                                
                                                                                 











                                                                                 







                                                                                                                 
                                                      



                                                            
                                                            



                                                             













                                                                            
   











                                                                    


                                                          




                                                                   
                                       
                                        
                                                      
                                               
                

                                               
                                                       

                                
                                                          

                                                                               
 


                                                                                       
                    
                                                              

                            

                                                                                       
                    
                                                                  



                             

                                                   
                                                  
 








                                                      

                                                                 
                                                
                                                                             
                         
                                                     
                                                                                                                                         

                                                
                                                                   
                                                      
                             


                            
                         

 















































































                                                                                                       


                                                                    
                      


                                                              
                                                          



                                                 

                                                       







                                                                





                                                                       
                                                                               


                                                       
                              
                                             




                                                        



















                                                                                      

                                                                
 

                                        
 





































































































                                                                                      
 


                                                                           
   
                                                                    
  
                                   
  
                                  
   

                                                                              

 
   


                                                     
   

                                                

 
 
 




                                         


































                                                                                                
/**
 * @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) {
}

/**
 * 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	userChoice
 * 			true if the user wishes to have a user choice. true: the chooseInterfaceDialog will be showed.
 *
 * @param	args
 * 			additional arguments for the customdhcpcd client. (default value: NULL)
 */
void NetworkDiscovery::initAndRun(bool userChoice, QStringList* args) {

	_userChoice = userChoice;

	_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 (gSocketServerPath != DEFAULT_QTSOCKETADDRESS) {
		_dhcpcdArguments.append("-q");
		_dhcpcdArguments.append(gSocketServerPath);
	}
	/* 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(gSocketServerPath)) {
		QFile::remove(gSocketServerPath);
	}

	emit
	updateStatus("try to create server socket");
	if (!_server->listen(gSocketServerPath)) {
		// 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(gPathToDhcpExe);
	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()));

	if (args != NULL && !args->isEmpty()) {
		LOG4CXX_DEBUG(ndcLogger, "added additional args");
		_dhcpcdArguments.append(*args);
	}
	emit updateStatus("start mainwork");
	mainWork();
}
//-------------------------------------------------------------------------
//                       Main Network Discovery Flow
//-------------------------------------------------------------------------
/**
 * @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() {
	gAutoUp ?
			emit updateStatus("search for usable interfaces (with auto Up)") :
			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 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)
					|| (gAutoUp && !(nI.flags() & QNetworkInterface::IsUp))
					|| checkBlackList(nI.humanReadableName())) {
				continue;
			}

			if ((nI.flags() & QNetworkInterface::IsRunning)) {
				_ifUpList.append(nI.humanReadableName());
			} else if (gAutoUp && !(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! ");
	}
}

/**
 * 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) {
	return (i.startsWith("v", Qt::CaseInsensitive) || i.startsWith("d", Qt::CaseInsensitive));
}

/**
 * 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;
		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::readyForRun() {
	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;
	}
}
//-------------------------------------------------------------------------
//                           DHCPCD Control
//-------------------------------------------------------------------------
/**
 * 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(gPathToDhcpExe, _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");
	}
}

/**/
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;
}
//-------------------------------------------------------------------------
//                       Connectivity Testing
//-------------------------------------------------------------------------
/**
 * 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(gServerIp)) {
		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(gServerIp);
}
/**
 * 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
	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;
}

//-------------------------------------------------------------------------
//                       Manual Configuration
//-------------------------------------------------------------------------

/**
 * 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(gServerIp)) {
		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;
}

//-------------------------------------------------------------------------
//                       Socket Connection Handling
//-------------------------------------------------------------------------

/**
 * 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();
}


/**
 * same function as handleNewInput() but with a client as parameter.
 *
 * @param 	client
 * 			a client
 */
void NetworkDiscovery::handleNewInput(QLocalSocket * client) {
	LOG4CXX_DEBUG(ndcLogger, "last read before exit");
	while (client->canReadLine()) {
		QString data(client->readLine());

		data = data.trimmed();
		if (!data.isEmpty())
			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;
	}
}

//-------------------------------------------------------------------------
//                       Public member access
//-------------------------------------------------------------------------
/**
 * @brief Return the InterfaceConfiguration for the given interface.
 *
 * @param Interface name as QString
 *
 * @return InterfaceConfiguration*
 */
InterfaceConfiguration* NetworkDiscovery::getInterfaceConfig(QString ifName) {
	return _ifcMap.value(ifName, NULL);
}

/**
 * @brief Returns the list of interfaces that are up.
 *
 * @return The QList<QString> member.
 */
QList<QString> NetworkDiscovery::getIfUpList() {
	return _ifUpList;
}



/**/
QString NetworkDiscovery::GetErrorStr() {
	return _errorStr;
}

 //-------------------------------------------------------------------------
 //                       Bugged Methods....
 //-------------------------------------------------------------------------

 /*
  *TODO: to be bug fixed
  *TODO: do it with kill and not QProcess("killall cdhcpcd")
  */
 void NetworkDiscovery::tryAgain() {
 	prepareTryAgain();
 	initAndRun(_userChoice);
 }
 /**/
 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;
 	}
 }