summaryrefslogblamecommitdiffstats
path: root/src/networkdiscovery.cpp
blob: 13242c2dbc78cdc7e7285d0ade9a03e889f4111e (plain) (tree)
1
2
3
4
5
6


                      

                             
 







































































                                                                                                                                               
                                                                     








                                                                               

                                                                                                                   








                                                                                                                
                                                                   

                                               
               












                                                                     
                                                                              




                                                      
                                                                                             











































































                                                                                             
                                                                          

                                                  
                                                                          













































                                                                                                
                                         








                                                                          
                                                              



 






                                                                                                                    
                                   
                                     
                                                     


                                          
                                                                    



















                                                                                                                       
 




                 
 

                                                                  
                            


                                                                   







                                                                







                                                                                              
                       



 






                                                                                   















                                                                                    












                                                                                                      
















                                                                                                        










                                                                                                  



                                                                                        



                                                                                   
                                                                   














                                                                                                      
                                                                                                        



                                                                                                  


                                                                                            
                                                                                   
                                                                                   


                                                                                 

                         
                                                                   














                                                                     
                                                                                      















                                                                                
                                                                


                                                                                                                 
                                                                



                                                                                                                    
                                                                                       



                                 
                                                               

































                                                                    
                                                     



































                                                                                
                                                            



                                                            
                                                                                              











                                                                 
                                                                                              







                                                                     






                                                  














                                                                
                                                                     












                                                                     
                                                             


















                                                                                
                                                        












                                                                    
                                                            



                                                 
                                                



















                                                                                

                                         
                              
                                          





































                                                                                      
                                             










                                                                                     
                                                                                        


                                                                   
                                                                                    


                                                                   
                                                                                       


                                                                   
                                                                              


                                                                   
                                                                              


                                                                   
                                                                                      










                                                                   
                                                                                                 


                                                                   
                                                                                          


                                                                    
                                                                                  



                                
                                                                             



                              
                                                                     

                      
                                                   






































                                                                                    
                                                    

                                                                                                                 
                                                                                                                              
                        

                                                                                                       
                                           
                                                                                        

                                                                                            
                                                                                  









                                                                                                                 

                                                                                     



                                                            
                                                              














                                                                           
                                                                               






























                                                                                    
#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() {

}



/**
 * 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;

	_pathToDhcpcdExe = pathToExe;
	_blocked = false;
	_numberOfProcesses = 0;
	_ifUpCountdown = 10;

	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);
	}

	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;
	}

	// check if the path to the customdhcpcd file is correct
		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);
	}
    mainWork();
}



/**
 * 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();
		runDHCPCD( _ifUpList);
	} else {
		qxtLog->debug() << _tag << "list is empty. Have not found usable interface.";
		emit
		abortBoot("Have not found usable interface");
		return;
	}
}



/**
 * 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;
	QList<QString> copyOfIfDownList(_ifDownList);
	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();
		emit readyForRun();
	}
}



/**
 * 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;
	}
	emit continueBoot(result["ifname"].toString(), 0);
	return 0;
}



/**
 * returns the gateway address, written into the dhcp config file.
 *
 * @param	ifName
 * 			name of the interface.
 *
 * @return
 * 			gateway address as string.
 */
QString NetworkDiscovery::getGatewayForInterface(QString ifName) {
	interfaceconfiguration * ifConf = _ifcMap.value(ifName);
	return ifConf->getGateway();
}



/**
 * 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());
			}
			return retval;
		}
	}
	qxtLog->debug() << _tag << " could not open log file";
}



/*
 *TODO: to be bug fixed
 *TODO: do it with kill and not QProcess("killall cdhcpcd")
 *TODO: still some bugs. if you press tryAgain it can happen that the app stops with the mainscreen.
 *TODO: reproducible: start normal with user choice. plug out the cable. press continue. abort screen should appear.
 *TODO: press tryAgain.
 */
void NetworkDiscovery::tryAgain() {
	// kill all cdhcpcd processes
	qxtLog->debug() << " kill cdhcpcd processes";
	QProcess * p = new QProcess(this);
	p->start("killall cdhcpcd");
	p->waitForFinished();
	qxtLog->debug() << _tag << "[tryAgain]" << p->errorString();
	/*
	foreach(Q_PID pid , _pidsList) {
		if (kill(pid,SIGKILL) <= -1)
			qDebug() << _tag << " error: trying to kill process: " << pid << " error: " << strerror(errno);
	}
	*/
	// reset everything
	_clients.clear();
	_clientProcessToIfNameMap.clear();
	_ifNameToClient.clear();
	_numberOfProcesses = 0;
	_blocked = false;
	_ifUpCountdown = 10;
	_ifUpList.clear();
	_ifDownList.clear();
	_pidsList.clear();
	_ifcMap.clear();

	// start again
	mainWork();

	//SIGK
	//kill();
}



/**/
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());
//
//		dns.clear();
//		dns = ifc->getDnsservers().trimmed().split(" ");
//
//				//ifc->getIpAddress(), ifc->getNetmask(), ifc->getBroadcast(),
//				//ifc->getGateway(), 0, AF_INET, "/etc/", dns);
//
	}
	return jsonObj;
}



/**
 * ================================================================================
 ********************************* Private Methods ********************************
 * ================================================================================
 **/


/**/
void NetworkDiscovery::mainWork()
{
    if (_autoUp) {
		getListOfNetworkInterfacesWithAutoUp();
		_timer = new QTimer(this);
		connect(_timer, SIGNAL(timeout()), this, SLOT(checkForIsRunning()));
		_timer->start(1000);

	} else {
		getListOfNetworkInterfaces();
		emit readyForRun();
	}
}



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

	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 << " bring up ..";
					_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();

	if (nIList.size() > 0) {
		foreach(QNetworkInterface nI, nIList)
			{
				qxtLog->debug() << _tag << "found Interface:" << nI.humanReadableName();
				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!";
	}
}



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



/**
 * 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 updateStatusLabel(interface, "start DHCP");
	_dhcpcdArguments.append(interface);
	QProcess * p = new QProcess(this);

	qxtLog->debug()  << _tag << _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();
}



/**
 * 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 = new interfaceconfiguration();
	ifConf->readConfigOutOfFile(pathToGatewayFile);
	_ifcMap.insert(ifName, ifConf);

	// replace default route
	qxtLog->debug()  << _tag << "replace default route";
	_networkManager.replaceDefaultRoute(ifName,
			ifConf->getGateway(), mss, AF_INET);

	if (checkConnectivityViaTcp(_serverIp)) {
		qxtLog->debug()  << _tag << "internet: check passed! for interface" << ifName;
		emit
		updateStatusLabel(ifName, "connection possible");
		if (!_userChoice) {
			// blockiere jeden weiteren check
			// emite continueBoot
			_blocked = true;
			emit continueBoot(ifName, 0);
		} else {
			emit connectionEstablished(ifName);
		}
		return true;
	} else {
		qxtLog->debug()  << _tag << "no internet connection with interface" << ifName;
		emit
		updateStatusLabel(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
	QTcpSocket *tcpSocket = new QTcpSocket(this);
	tcpSocket->connectToHost(server, 80);
	if (!tcpSocket->waitForConnected(500)) {
		qxtLog->debug()  << _tag << tcpSocket->errorString();
		return false;
	} else {
		return true;
	}
}



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



/**
 * 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));
	//client->write("ACK", ACK_SIZE);
	//client->waitForBytesWritten();
	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 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:

			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:

		default:
			qxtLog->debug() << _tag << " received error:" << msg;
			break;
		}
		break;
	case LOG_ERR:
		qxtLog->debug() << _tag << " received error:" << msg;
		break;
	default:
		qxtLog->debug()  << _tag << logMsg;
		break;
	}
}



/**
 * 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 updateStatusLabel() to check connection
 *  checkConnectivity() @see NetworkDiscovery::checkConnectivity()
 * Unexpected exit:
 *  emit updateStatusLabel() to process exited unexpected
 *  TODO:: the reason for the unexpected exit should be presented in the logfile.
 *
 * @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 << "--- \t [NetworkDiscovery::handleProcessFinished] 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";
				emit updateStatusLabel(ifName, "process exited unexpected");
			} else {
				qxtLog->debug()  << _tag << "process normal exit";
				emit changeProgressBarValue(ifName, 100);
				emit updateStatusLabel(ifName, "check connectivity");
				checkConnectivity(ifName);
			}
		}
		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 updateStatusLabel(ifName, "finished DHCP");
	}
}



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