1
/* KwlanInterface defines a class for configuring and monitoring an interface
2
Parts of it's implemtation are based on KNemo by Percy Leonhardt <percy@eris23.de>
3
The scanning part is derived from wireless-tools ba Jean Tourrilhes <jt@hpl.hp.com>
5
(c) 2006 by Thomas Michel <tom.michel@arcor.de>
7
Kwlan is free software; you can redistribute it and/or modify
8
it under the terms of the GNU Library General Public License as
9
published by the Free Software Foundation; either version 2 of
10
the License, or (at your option) any later version.
12
Kwlan is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU Library General Public License for more details.
17
You should have received a copy of the GNU Library General Public License
18
along with this library; see the file COPYING.LIB. If not, write to
19
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
20
Boston, MA 02110-1301, USA.
25
#include "kwlaninterface.h"
28
#include "configuration.h"
29
#include "kstartsupplicantdlg.h"
30
#include "kwlansuprocess.h"
31
#include "keventhistorydlg.h"
32
#include "kprofileconfigdlg.h"
33
#include "kwlansettingsdlg.h"
36
#include "kwlnetworklist.h"
38
#include <kmessagebox.h>
39
#include <ktempfile.h>
40
#include <kstandarddirs.h>
47
#include <kio/global.h>
48
#include <kstandarddirs.h>
50
#include <qcheckbox.h>
53
#include <sys/ioctl.h>
56
KwlanInterface::KwlanInterface(KwlanMainWin *mainWin)
58
// initialise variables
61
m_controlConnection = NULL;
62
m_monitorConnection = NULL;
63
m_controlInterfaceDir = strdup ("/var/run/wpa_supplicant");
67
m_userDataRequest = NULL;
68
m_useDhclient = FALSE;
71
m_ifconfigProcess = 0L;
72
m_iwconfigProcess = 0L;
76
m_ipConfigured = FALSE;
86
m_isConfiguring = FALSE;
87
KMessageBox::setDontShowAskAgainConfig(mainConfiguration().m_configuration);
88
//get path to wpa_supplicant
89
m_wpaPath = getPath("wpa_supplicant");
90
if (m_wpaPath.isEmpty()){
91
KMessageBox::error(0,i18n("Could not find wpa_supplicant binary. Without it Kwlan can't connect to encrypted networks.\n"
92
"Please check your wpa_supplicant installation."));
94
//Check for dhcp client to use
95
m_dhcpcdPath = getPath("dhcpcd");
96
if (!m_dhcpcdPath.isEmpty()){
99
m_dhclientPath = getPath("dhclient");
100
if (!m_dhclientPath.isEmpty())
101
m_useDhclient = TRUE;
103
if (! m_useDhclient && ! m_useDhcpcd)
104
KMessageBox::sorry(0,i18n("Neither dhclient nor dhcpcd found. Dynamic IP configuration will not work."));
105
// check for path to needed applications
106
m_ifconfigPath = getPath("ifconfig");
107
if (m_ifconfigPath.isEmpty())
108
kdDebug() << i18n("ifconfig not found. Network statistics and static ip addresses will not work.") << endl;
109
m_iwconfigPath = getPath("iwconfig");
110
if (m_iwconfigPath.isEmpty())
111
kdDebug() << i18n("iwconfig not found. Wireless statistics might not work.") << endl;
112
m_timer = new QTimer(this);
116
void KwlanInterface::init(QString interface)
120
if (!interface) return;
121
m_sysClassPath="/sys/class/net/"+interface+"/";
122
memset(&m_devInfo, 0, sizeof(m_devInfo));
123
strcpy(m_devInfo.ifr_name, interface.latin1());
124
m_confFile = QString("kwlanrc.") + interface;
125
// find out if we have a wireless interface
126
m_controlInterface = strdup(interface.ascii());
127
QStringList wirelessInterfaces = getInterfaces();
128
if (wirelessInterfaces.findIndex(m_controlInterface)!=-1)
129
m_interfaceData.wirelessDevice = TRUE;
130
else m_interfaceData.wirelessDevice = FALSE;
131
// check for File existance to see wether interface is already configured
132
QString tmpConf = KStandardDirs().findResource("config",m_confFile);
133
m_configuration = new Configuration(m_confFile);
134
// Check for interface type
136
if ((tmpConf.isEmpty() || !hasProfiles() && m_type != PPP) && KMessageBox::shouldBeShownContinue("newinterfacewizard"))
139
newInterfaceWizard(interface);
141
m_configureInterface = mainConfiguration().readConfigureInterface( interface);
143
if (m_type == ETHERNET)
145
// check if we have a custom wpa config file
146
if (m_configuration && m_configuration->m_useCustomWpaConf)
148
m_wpaConf = m_configuration->m_customWpaConf;
152
// check if wpa_config file for interface exists
153
m_wpaConf = QString("kwlan.")+ interface;
154
if (locate("config",m_wpaConf).isEmpty())
156
//create a new config file containig the important global settings
157
KConfig *conf= new KConfig(m_wpaConf,false,false,"config");
158
conf->writeEntry("update_config","1");
159
conf->writeEntry("ctrl_interface",m_controlInterfaceDir);
160
conf->writeEntry("ctrl_interface_group","20");
163
m_wpaConf = locate("config",m_wpaConf);
166
// To avoid Getting an IP Address if interface already has one, check ip address
167
// We set m_ipConfigured to true to avoid updateData getting an ip address
168
// It's a little ugly and needs some rework
169
m_ipConfigured = TRUE;
171
if (m_interfaceData.ipAddress.isEmpty() || m_interfaceData.ipAddress=="0.0.0.0") m_ipConfigured = FALSE;
172
else m_ipConfigured = TRUE;
173
if (::debugOutput) kdDebug() << "IP Address " << m_interfaceData.ipAddress << "M_ipconfigured " << m_ipConfigured << endl;
175
//check for existing WPA connection
176
checkWpaConnection();
177
//Start WPA Supplicant if configured and no connection is established
180
if (m_interfaceData.wirelessDevice)
182
if (!m_wpaStarted && m_configuration->m_startWpa && m_configureInterface){
183
KStartSupplicantDlg *startSupplicant = new KStartSupplicantDlg();
185
m_configuration->readDriver(driver);
186
if (startSupplicant ){
187
startSupplicant->setData(&interface,&driver);
188
if (m_configuration->m_startWpaNoQuestion&& !driver.isEmpty()){
189
startSupplicant->startSupplicant();
192
startSupplicant->show();
193
startSupplicant->exec();
195
QString wpa_supplicant;
196
if (startSupplicant->m_start){
197
KwlanSuProcess *startWpa= new KwlanSuProcess(NULL,"Start WPA Supplicant");
198
*startWpa << m_wpaPath << QString("-i%1").arg(QString(m_controlInterface)) << QString ("-D%1").arg(startSupplicant->getDriver()) << QString("-c")+ m_wpaConf << "-B";
199
startWpa->setDescription(i18n("Start WPA Supplicant"));
201
m_configuration->writeDriver(startSupplicant->getDriver());
203
delete startSupplicant;
204
m_networkChange = true;
209
if ((!m_wpaStarted && m_configuration->m_startWpa && m_configureInterface)&&(m_type == ETHERNET )){
210
//wired device, so drvier is wired
211
KwlanSuProcess *startWpa= new KwlanSuProcess(NULL,"Start WPA Supplicant");
212
*startWpa << m_wpaPath << QString("-i%1").arg(QString(m_controlInterface)) << QString ("-D%1").arg(QString("wired")) << QString("-c" ) + m_wpaConf <<"-B";
213
startWpa->setDescription(i18n("Start WPA Supplicant"));
218
// Set Status update timer
219
if (m_type ==ETHERNET)
221
if (m_configuration) m_configuration->readLastSsid(m_ssid);
224
// Now check if we have to use static ip addressing
225
// If so, scheck whether interface address is equal to configured address
228
if (m_staticIpAddress!=m_interfaceData.ipAddress)
230
m_ipConfigured = FALSE;
234
emit (networksChanged());
235
slotScanAvailableNetworks();
236
connect(this, SIGNAL(wpaStatusChanged( bool )), this, SLOT(slotWpaStatusChanged(bool)));
237
m_timer = new QTimer(this);
238
m_scanTimer = new QTimer(this);
242
connect (m_timer, SIGNAL(timeout()),SLOT(checkWpaConnection()));
243
m_timer->start(timerInterval,FALSE);
246
connect (m_scanTimer, SIGNAL(timeout()),SLOT(slotScanAvailableNetworks()));
247
m_scanTimer->start(3000,FALSE);
252
KwlanInterface::~KwlanInterface()
258
if (m_ifconfigProcess)
260
m_ifconfigProcess->kill();
261
delete (m_ifconfigProcess);
263
if (m_iwconfigProcess)
265
m_iwconfigProcess->kill();
266
delete (m_iwconfigProcess);
270
void KwlanInterface::slotWpaStatusChanged(bool status)
273
profileActivate(m_ssid);
276
void KwlanInterface::cleanTemporaryFiles()
278
resolvconf->unlink();
285
int KwlanInterface::openControlConnection()
287
bool tmpWpaStarted = m_wpaStarted;
291
if ((m_controlInterface == NULL) || (m_type==PPP))
293
//kdDebug() << "Trying to open control connection" << endl;
294
flen = strlen(m_controlInterfaceDir) + strlen(m_controlInterface) + 2;
295
cfile = (char *) malloc(flen);
298
snprintf(cfile, flen, "%s/%s", m_controlInterfaceDir, m_controlInterface);
301
if (m_controlConnection) {
302
wpa_ctrl_close(m_controlConnection);
303
m_controlConnection = NULL;
306
if (m_monitorConnection) {
307
delete m_messageNotifier;
308
m_messageNotifier = NULL;
309
wpa_ctrl_detach(m_monitorConnection);
310
wpa_ctrl_close(m_monitorConnection);
311
m_monitorConnection = NULL;
314
//if (::debugOutput) kdDebug() << "Trying to connect to " << cfile << endl;
315
m_controlConnection = wpa_ctrl_open(cfile);
316
if (m_controlConnection == NULL) {
317
//if (::debugOutput) kdDebug() << "Opening control connection failed" << endl;
324
if (debugOutput) kdDebug() << "Control connection established" << endl;
325
// Set ap_scan value as new connection is established
330
snprintf(command,sizeof(command),"AP_SCAN %d",m_configuration->m_ap_scan);
331
if (::debugOutput) kdDebug() << "Setting ap_scan value: " << command << endl;
332
if (ctrlRequest(command,buf,&len) <0)
334
kdDebug() << "Setting ap_scan value failed!" << endl;
337
if (::debugOutput) kdDebug() << buf << endl;
338
emit (wpaStatusChanged(m_wpaStarted));
339
emit (networksChanged());
341
m_monitorConnection = wpa_ctrl_open(cfile);
343
if (m_monitorConnection == NULL) {
344
wpa_ctrl_close(m_controlConnection);
345
if (::debugOutput) kdDebug() << "Could not establish monitor connection." << endl;
348
if (wpa_ctrl_attach(m_monitorConnection)) {
349
printf("Failed to attach to wpa_supplicant\n");
350
wpa_ctrl_close(m_monitorConnection);
351
m_monitorConnection = NULL;
352
wpa_ctrl_close(m_controlConnection);
353
m_controlConnection = NULL;
357
m_messageNotifier = new QSocketNotifier(wpa_ctrl_get_fd(m_monitorConnection),QSocketNotifier::Read, this);
358
if (m_messageNotifier)
359
connect(m_messageNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs()));
360
else kdDebug() << "Could not create Message Notifier" << endl;
365
void KwlanInterface::checkWpaConnection()
371
bool tmpWpaStarted = m_wpaStarted;
374
if (ctrlRequest("PING",buf,&len) <0)
379
m_controlConnection=0L;
380
m_monitorConnection=0L;
381
emit wpaStatusChanged (FALSE);
383
// try to open the connection
384
openControlConnection();
389
emit wpaStatusChanged (TRUE);
395
int KwlanInterface::ctrlRequest(const char *command, char *buf, size_t *buflen)
397
if (m_controlConnection == NULL)
399
return wpa_ctrl_request(m_controlConnection, command, strlen(command), buf, buflen, kwlan_msg_cb);
403
QStringList KwlanInterface::listProfiles()
405
QStringList wpaProfiles;
406
if (m_type == PPP) return wpaProfiles;
408
wpaProfiles = listWpaProfiles();
409
//kdDebug() << "WPA PRofiles: " << wpaProfiles << endl;
410
return wpaProfiles + listNonWpaProfiles(wpaProfiles);
413
QStringList KwlanInterface::listWpaProfiles()
415
char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
416
size_t len =sizeof(buf);
417
QStringList networks;
418
// Are we connected to wpa?
419
if (!m_controlConnection) {
420
//kdDebug() << "No control connection to list wpa profiles! "<< m_controlInterface << endl;
423
if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
425
kdDebug() << "Could not list wpa profiles" << endl;
429
start = strchr(buf, '\n');
435
end = strchr(start, '\n');
439
while (end[0] && end[1])
445
ssid = strchr(id, '\t');
449
bssid = strchr(ssid, '\t');
453
flags = strchr(bssid, '\t');
458
QString tmpNetwork(ssid);
459
networks.append (tmpNetwork);
468
QStringList KwlanInterface::listNonWpaProfiles(QStringList wpaProfiles)
470
QStringList profiles;
471
if (!m_configuration) return profiles;
472
profiles = m_configuration->getNetworks();
473
// Now test if networks already exists from wpa config
474
QStringList::Iterator it;
475
it = profiles.begin();
476
while (it !=profiles.end())
478
QStringList::Iterator index = wpaProfiles.find( *it );
479
if ( !(*index).isEmpty() )
481
it = profiles.remove(it);
484
// Check whether the Network can be used without encryption
486
m_configuration->readEncryption(*it,encrypted);
488
it = profiles.remove(it);
494
//kdDebug() << profiles << endl;
498
bool KwlanInterface::hasProfiles()
500
if (!m_configuration) return FALSE;
501
QStringList profiles;
502
profiles = m_configuration->getNetworks();
503
if (profiles.isEmpty()) return FALSE;
507
int KwlanInterface::getWpaId(QString findSsid)
509
char buf[2048], *start, *end, *id, *ssid, *bssid, *flags;
510
size_t len = sizeof(buf);
511
QStringList networks;
512
// Are we connected to wpa?
513
if (!m_controlConnection) {
514
//kdDebug() << "No control connection! " << endl;
517
if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0)
519
kdDebug() << "Getting list of networks failed! " << endl;
524
start = strchr(buf, '\n');
530
end = strchr(start, '\n');
534
while (end[0] && end[1])
540
ssid = strchr(id, '\t');
544
bssid = strchr(ssid, '\t');
548
flags = strchr(bssid, '\t');
552
QString tmpSsid =QString(ssid);
553
if (tmpSsid==findSsid)
555
return QString(id).toInt();
564
bool KwlanInterface::profileActivateNonWpa(QString ssid)
566
if (m_interfaceData.wirelessDevice)
568
KwlanSuProcess *iwconfig = new KwlanSuProcess(this);
569
*iwconfig << m_iwconfigPath << m_controlInterface << QString("essid") << ssid;
570
iwconfig->setDescription(i18n("Configure wlan interface using iwconfig"));
571
//iwconfig->start(SuProcessBase::Block);
575
if (m_configuration) m_configuration->writeLastSsid( ssid);
584
bool KwlanInterface::profileActivateWpa(QString ssid)
586
if (m_isConfiguring) return TRUE;
587
// select network using wpa_supplicant
588
if (!m_wpaStarted) return FALSE;
590
char reply[40], cmd[256];
591
size_t reply_len = sizeof(reply);
593
int id = getWpaId(ssid);
595
// Seems to be a new network, so configure it.
596
m_isConfiguring = TRUE;
597
for (kwlNetworkList::iterator it = m_availableNetworks.begin();it != m_availableNetworks.end();it++)
599
if ((*it).m_ssid == ssid)
601
KProfileConfigDlg *nc = new KProfileConfigDlg();
604
nc->setInterface(this);
605
nc->paramsFromScanResults((*it));
606
kdDebug() << (*it).m_flags << endl;
609
m_isConfiguring = FALSE;
613
//KMessageBox::sorry(0, i18n("Could not find network in wpa_supplicant\nconfiguration."));
616
snprintf(cmd, sizeof(cmd), "DISCONNECT");
617
reply_len = sizeof(reply);
618
ctrlRequest(cmd, reply, &reply_len);
621
snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %d", id);
622
reply_len = sizeof(reply);
623
ret=ctrlRequest(cmd, reply, &reply_len);
625
KMessageBox::sorry(0,"No control connection!");
628
if (strncmp(reply, "OK", 2) != 0) {
629
KMessageBox::sorry(0, i18n("Failed to enable network in wpa_supplicant\nconfiguration."));
633
snprintf(cmd, sizeof(cmd), "REASSOCIATE");
634
reply_len = sizeof(reply);
635
ctrlRequest(cmd, reply, &reply_len);
637
if (m_configuration) m_configuration->writeLastSsid( ssid);
641
checkWpaConnection();
645
bool KwlanInterface::profileActivate(QString ssid)
647
if (!m_configureInterface) return FALSE;
648
// release any existing ip address
649
if (m_ipConfigured) releaseIpAddress();
650
//m_interfaceData.available = FALSE;
651
m_interfaceData.connected = FALSE;
652
if (m_controlConnection){
653
return profileActivateWpa(ssid);
656
// check if wpa_supplicant is needed for the network
657
for (kwlNetworkList::iterator it = m_availableNetworks.begin();it != m_availableNetworks.end();it++)
659
if ((*it).m_ssid==ssid)
661
if ((*it).m_flags.contains("WPA") )
663
int result = KMessageBox::questionYesNo(0,i18n("To activate this network, wpa_supplicant must be started. Do you want to start wpa_supplicant?"),
665
if (result == KMessageBox::Yes)
667
KStartSupplicantDlg *startSupplicant = new KStartSupplicantDlg();
669
m_configuration->readDriver(driver);
670
if (startSupplicant )
672
QString iface = QString(m_controlInterface)
673
startSupplicant->setData(&iface,&driver);
674
startSupplicant->show();
675
startSupplicant->exec();
676
QString wpa_supplicant;
677
if (startSupplicant->m_start)
679
KwlanSuProcess *startWpa= new KwlanSuProcess(NULL,"Start WPA Supplicant");
680
*startWpa << m_wpaPath << QString("-i%1").arg(QString(m_controlInterface)) << QString ("-D%1").arg(startSupplicant->getDriver()) << QString("-c")+ m_wpaConf << "-B";
681
startWpa->setDescription(i18n("Start WPA Supplicant"));
683
m_configuration->writeDriver(startSupplicant->getDriver());
686
delete startSupplicant;
687
m_networkChange = true;
695
// select network using iwconfig
696
return profileActivateNonWpa(ssid);
700
void KwlanInterface::releaseIpAddress()
702
if (!m_controlInterface || (m_type == PPP) || !m_configureInterface) return;
703
if (m_releaseProcess) return;
704
// Now start script before disconnect if configured
707
m_configuration->readScriptBeforeDisconnect( m_ssid,script, useRoot);
708
if (::debugOutput) kdDebug() << "Now starting script before disconnect "<< script << endl;
709
if (!script.isEmpty())
712
KwlanSuProcess *proc = new KwlanSuProcess();
714
proc->setDescription( i18n("start script before disconnect"));
718
KProcess *proc = new KProcess();
724
m_releaseProcess = new KwlanSuProcess(this);
725
if (!m_dhcpEnabled) {
726
*m_releaseProcess << "ifconfig" << m_controlInterface << "0.0.0.0";
730
*m_releaseProcess << m_dhclientPath << "-r" << m_controlInterface;
731
} else if (m_useDhcpcd){
732
*m_releaseProcess << m_dhcpcdPath << "-k" << m_controlInterface;
735
m_releaseProcess->setDescription(i18n("Release IP address"));
736
connect (m_releaseProcess, SIGNAL(processExited(KwlanSuProcess*)), this, SLOT(releaseProcessExited(KwlanSuProcess*)));
737
m_releaseProcess->start();
740
void KwlanInterface::setDnsSettings()
742
if (m_type == PPP) return;
743
if (m_staticDns1.isEmpty() && m_staticDns2.isEmpty() && m_domain.isEmpty() && m_dnsSearchlist.isEmpty())
745
if (!m_dontOverrideDns || !hasNameserver()) {
746
// Create temporary file containing DNS configuration
747
resolvconf = new KTempFile(locateLocal("tmp", "resolv"), ".conf", 0644);
748
if (!m_staticDns1.isEmpty())
749
*(resolvconf->textStream()) << QString("nameserver %1").arg(m_staticDns1) << endl;
750
if (!m_staticDns2.isEmpty())
751
*(resolvconf->textStream()) << QString("nameserver %1").arg(m_staticDns2) << endl;
752
if (!m_domain.isEmpty())
753
*(resolvconf->textStream()) << QString("domain %1").arg(m_domain) << endl;
754
if (!m_dnsSearchlist.isEmpty())
756
*(resolvconf->textStream()) << QString("search ");
757
for (QStringList::iterator it = m_dnsSearchlist.begin(); it != m_dnsSearchlist.end(); it++)
758
*(resolvconf->textStream()) << *it << " ";
759
*(resolvconf->textStream()) << endl;
762
KwlanSuProcess * setNetwork = new KwlanSuProcess();
763
connect(setNetwork, SIGNAL( destroyed() ), this, SLOT( cleanTemporaryFiles() ));
765
// And copy it to /etc fixing permissions (moving wont work if /etc/resolv.conf is a symlink)
766
*setNetwork << getPath("cp") << resolvconf->name() << "/etc/resolv.conf";
768
*setNetwork << getPath("chown") << "root:root" << "/etc/resolv.conf";
769
setNetwork->setDescription(i18n("Set network settings"));
774
void KwlanInterface::checkType()
776
// check Interface type
777
int type = readInterfaceNumValue( "type");
788
void KwlanInterface::getIpAddress()
790
if ((m_type == PPP)||(m_ssid.isEmpty()) || !m_configureInterface || m_isConfiguring) return;
793
// We are already running
796
m_dhcpProcess = new KwlanSuProcess(this);
798
if (m_staticIpAddress.isEmpty()) return;
800
m_dhcpProcess->setDescription(i18n("Configure the network"));
801
*m_dhcpProcess << m_ifconfigPath << m_controlInterface << m_staticIpAddress.ascii();
803
if (!m_staticNetmask.isEmpty())
804
*m_dhcpProcess << "netmask" << m_staticNetmask.ascii();
806
// We can to set up our new route if there is no route (hasGateway()==false) or we have but m_ovrgw is true ()
807
bool m_hasGateway = hasGateway();
808
if (!m_staticGateway.isEmpty() && (!m_dontOverrideGw || !m_hasGateway)) {
809
*m_dhcpProcess << ";";
811
// Delete default route if we already have one
813
*m_dhcpProcess << getPath("route") << "del" << "default" << ";";
815
*m_dhcpProcess << getPath("route") << "add" << "default" << "gw" << m_staticGateway.ascii();
822
*m_dhcpProcess << m_dhclientPath << m_controlInterface;
823
} else if (m_useDhcpcd){
824
*m_dhcpProcess << m_dhcpcdPath << "-nd" << m_controlInterface;
826
say(i18n("%1 is requesting\nan IP address").arg(m_controlInterface));
827
m_dhcpProcess->setDescription(i18n("Obtain IP address dynamically"));
828
m_dhcpProcess->setRestart(true);
830
connect (m_dhcpProcess,SIGNAL(processExited(KwlanSuProcess*)), this, SLOT(dhcpProcessExited(KwlanSuProcess*)));
831
//m_dhcpProcess->start(SuProcessBase::Block);
832
m_dhcpProcess->start();
836
void KwlanInterface::processWpaMessage(char *message)
838
char *pos = message, *pos2;
843
priority = atoi(pos);
844
pos = strchr(pos, '>');
851
WpaMsg wm(pos, priority);
853
m_messages.append(wm);
854
while (m_messages.count() > 100)
855
m_messages.pop_front();
857
/* Update last message with truncated version of the event */
858
if (strncmp(pos, "CTRL-", 5) == 0) {
859
pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' ');
866
QString lastmsg = pos2;
867
lastmsg.truncate(40);
868
m_networkChange = true;
870
if (str_match(pos, WPA_CTRL_REQ))
871
processCtrlReq(pos + strlen(WPA_CTRL_REQ));
872
if (str_match(pos,WPA_EVENT_CONNECTED)){
875
if (str_match(pos,WPA_EVENT_DISCONNECTED)){
876
m_associated = false;
880
void KwlanInterface::receiveMsgs()
884
if (!m_monitorConnection) return;
885
while (wpa_ctrl_pending(m_monitorConnection)) {
886
len = sizeof(buf) - 1;
887
if (wpa_ctrl_recv(m_monitorConnection, buf, &len) == 0) {
889
processWpaMessage(buf);
894
void KwlanInterface::processCtrlReq( const char * request )
896
// processe control request, for example ask for password for private key file.
897
if (m_userDataRequest) {
898
m_userDataRequest->close();
899
delete m_userDataRequest;
901
m_userDataRequest = new KUserDataRequestDlg();
902
if (m_userDataRequest == NULL)
904
if (m_userDataRequest->setParams(this, request) < 0) {
905
delete m_userDataRequest;
906
m_userDataRequest = NULL;
909
m_userDataRequest->show();
910
m_userDataRequest->exec();
913
void KwlanInterface::startWpa(QString driver)
916
kdDebug() << "wpa_supplicant is already started!" << endl;
921
if (m_configuration->m_useCustomWpaConf)
922
m_wpaConf = m_configuration->m_customWpaConf;
924
m_wpaConf = QString("kwlan.")+ m_controlInterface;
925
m_wpaConf = locate("config",m_wpaConf);
928
KwlanSuProcess *startWpa = new KwlanSuProcess(this);
929
*startWpa << m_wpaPath << QString("-i%1").arg(QString(m_controlInterface)) << QString ("-D%1").arg(driver) << QString("-c") +m_wpaConf << "-B";
930
startWpa->setDescription(i18n("Start WPA Supplicant"));
932
//remember last interface driver
933
if (m_configuration) m_configuration->writeDriver(driver);
934
emit (networksChanged());
937
void KwlanInterface::stopWpa()
942
kdDebug() << "wpa_supplicant is not started!" << endl;
945
if (::debugOutput) kdDebug() << "Releasing IP address" << endl;
947
reply_len = sizeof(reply);
948
if (::debugOutput) kdDebug() << "Stopping wpa_supplicant" << endl;
949
ctrlRequest("TERMINATE", reply, &reply_len);
950
if (strncmp(reply,"OK",2) != 0) {
951
KMessageBox::sorry(0, i18n("Could not terminate WPA_Supplicant!"));
954
if (::debugOutput) kdDebug() << "wpa_supplicant stopped" << endl;
955
emit (networksChanged());
958
QString KwlanInterface::getInterfaceName()
960
return QString(m_controlInterface);
964
void KwlanInterface::profileAdded()
966
emit (networksChanged());
969
void KwlanInterface::updateData()
971
//bool tmpAvailable = m_interfaceData.available;
972
bool tmpUp = m_interfaceData.up;
973
//bool tmpConnected = m_interfaceData.connected;
974
FILE* flags_fp = fopen((m_sysClassPath+"flags").latin1(), "r");
978
// Interface seems to have gone away
979
emit (interfaceGone(this));
985
fscanf(flags_fp, "%Xu", &flags);
987
currentStatus = IFF_UP & flags;
989
if (!currentStatus) { // interface down...
990
// Interface is down and was up before -> set status variables
991
m_interfaceData.up = FALSE;
992
m_interfaceData.connected = FALSE;
994
} else if (currentStatus) {
995
// Interface is up, so check for connection status
996
m_interfaceData.up = TRUE;
997
// Now get connection status
998
FILE* carrier_fp = fopen((m_sysClassPath+"carrier").latin1(), "r");
999
char carrierFlag = '1';
1001
carrierFlag = fgetc(carrier_fp);
1004
if (carrierFlag == '0') { // carrier down
1005
// Interface is not connected
1006
m_state=NOTCONNECTED;
1007
if (m_interfaceData.connected) {
1008
m_interfaceData.connected = FALSE;
1009
say(i18n("%1 is disconnected").arg(m_controlInterface));
1011
} else if (!m_interfaceData.connected) {
1012
// Interface is connected
1013
m_interfaceData.connected = TRUE;
1017
say(i18n("%1 is connected").arg(m_controlInterface));
1023
if (m_interfaceData.wirelessDevice)
1025
long retval = readInterfaceNumValue("device/power/state");
1027
m_wirelessData.radioOff = FALSE;
1028
else m_wirelessData.radioOff = TRUE;
1030
if (m_interfaceData.connected)
1032
// Now get interface data
1033
unsigned long currentRxBytes = readInterfaceNumValue("statistics/rx_bytes");
1034
if ( currentRxBytes < m_interfaceData.prevRxBytes )
1036
// there was an overflow
1037
m_interfaceData.rxBytes = currentRxBytes;
1038
m_interfaceData.prevRxBytes = 0L;
1040
if ( m_interfaceData.rxBytes == 0L )
1042
// on startup set to currently received bytes
1043
m_interfaceData.rxBytes = currentRxBytes;
1044
m_interfaceData.prevRxBytes = currentRxBytes;
1047
// afterwards only add difference to previous number of bytes
1049
m_interfaceData.prevRxBytes = m_interfaceData.rxBytes;
1050
m_interfaceData.rxBytes = currentRxBytes;
1053
m_interfaceData.rxString = KIO::convertSize( m_interfaceData.rxBytes );
1055
unsigned long currentTxBytes = readInterfaceNumValue("statistics/tx_bytes");
1056
if ( currentTxBytes < m_interfaceData.prevTxBytes )
1058
// there was an overflow
1059
m_interfaceData.txBytes = currentTxBytes;
1060
m_interfaceData.prevTxBytes = 0L;
1062
if ( m_interfaceData.txBytes == 0L )
1064
// on startup set to currently transmitted bytes
1065
m_interfaceData.txBytes = currentTxBytes;
1066
m_interfaceData.prevTxBytes = currentTxBytes;
1070
m_interfaceData.prevTxBytes = m_interfaceData.txBytes;
1071
m_interfaceData.txBytes = currentTxBytes;
1074
m_interfaceData.txString = KIO::convertSize( m_interfaceData.txBytes );
1076
m_interfaceData.rxPackets = readInterfaceNumValue("statistics/rx_packets");
1077
m_interfaceData.txPackets = readInterfaceNumValue("statistics/tx_packets");
1078
// Now get IP Address
1079
if (!((m_fdSock == -1) && !openFdSocket()))
1081
memset(&m_devInfo, 0, sizeof(m_devInfo));
1082
strcpy(m_devInfo.ifr_name, m_controlInterface);
1083
ioctl(m_fdSock, SIOCGIFADDR, &m_devInfo);
1084
sockaddr_in sin = ((sockaddr_in&)m_devInfo.ifr_addr);
1085
m_interfaceData.ipAddress = inet_ntoa(sin.sin_addr);
1086
ioctl(m_fdSock, SIOCGIFNETMASK, &m_devInfo);
1087
sockaddr_in mask = ((sockaddr_in&)m_devInfo.ifr_netmask);
1088
m_interfaceData.subnetMask = inet_ntoa(mask.sin_addr);
1089
ioctl(m_fdSock, SIOCGIFBRDADDR, &m_devInfo);
1090
sockaddr_in broadcast = ((sockaddr_in&)m_devInfo.ifr_broadaddr);
1091
m_interfaceData.broadcastAddress = inet_ntoa(broadcast.sin_addr);
1095
m_interfaceData.ipAddress = "";
1096
m_interfaceData.subnetMask="";
1097
m_interfaceData.broadcastAddress="";
1099
//Now get wireless data
1100
if (m_interfaceData.wirelessDevice)
1102
QString filename = m_sysClassPath+"device/bssinfo";
1103
QFile bssFile (filename);
1104
if (bssFile.open(IO_ReadOnly))
1106
QTextStream stream (&bssFile);
1108
while (!stream.atEnd() && !line.isNull())
1110
line = stream.readLine();
1114
regExp.setPattern( "ESSID: (\\w*)" );
1115
if ( regExp.search( line ) > -1 )
1116
m_wirelessData.essid= regExp.cap( 1 );
1117
regExp.setPattern( "Channel: (\\d*)" );
1118
if ( regExp.search( line ) > -1 )
1119
m_wirelessData.channel = regExp.cap( 1 );
1124
unsigned long link = readInterfaceNumValue( "wireless/link");
1125
m_wirelessData.linkQuality = QString("%1/100").arg(link);
1126
m_wirelessData.linkQualityNum = link;
1130
if (tmpUp != m_interfaceData.up)
1132
emit (interfaceUp(m_interfaceData.up ));
1134
if (m_interfaceData.up && m_interfaceData.connected)
1136
if (!m_ipConfigured)
1144
void KwlanInterface::dhcpProcessExited(KwlanSuProcess *process)
1146
if (process == m_dhcpProcess)
1148
delete m_dhcpProcess;
1149
// check if the process returned an Error
1150
if (m_dhcpProcess->exitStatus()==0)
1152
say(i18n("%1 is connected").arg(m_controlInterface));
1153
if (::debugOutput) kdDebug() << "Now starting script after connect" << endl;
1154
// set Network settings like DNS etc
1156
//start script after connect
1157
startScriptAfterConnect();
1159
m_ipConfigured = TRUE;
1165
void KwlanInterface::releaseProcessExited(KwlanSuProcess *process)
1167
if (process == m_releaseProcess)
1169
delete m_releaseProcess;
1170
m_ipConfigured = FALSE;
1171
m_releaseProcess =0L;
1176
void KwlanInterface::logViewer()
1178
//kdDebug()<<"Log Viewer called" << endl;
1179
if (m_eventHistory) {
1180
m_eventHistory->close();
1181
delete m_eventHistory;
1184
m_eventHistory = new KEventHistoryDlg();
1185
if (m_eventHistory == NULL)
1187
connect (this, SIGNAL (wpaEvent(WpaMsg)), m_eventHistory,SLOT (addEvent(WpaMsg)));
1188
connect (this, SIGNAL (wpaEvents(WpaMsgList)), m_eventHistory,SLOT (addEvents(WpaMsgList)));
1189
emit (wpaEvents( m_messages));
1190
m_eventHistory->show();
1191
m_eventHistory->exec();
1194
void KwlanInterface::getIpData()
1196
if (!m_configuration) return;
1197
QString ipAddress,netmask,dns1,dns2,gateway, domain;
1198
QStringList dnsSearchlist;
1199
bool dontOverrideGw,dontOverrideDns, dhcpEnabled;
1201
ret = m_configuration->readIpSettings(m_ssid,dhcpEnabled, ipAddress, netmask, gateway, dns1, dns2,domain,dontOverrideGw,dontOverrideDns,dnsSearchlist);
1203
m_dhcpEnabled = true; //default will be dhcp
1204
m_staticIpAddress="";
1205
m_staticNetmask = "";
1209
m_dontOverrideDns=TRUE;
1210
m_dontOverrideGw=TRUE;
1212
m_dnsSearchlist.clear();
1215
m_dhcpEnabled = dhcpEnabled;
1216
m_staticIpAddress= ipAddress;
1217
m_staticNetmask = netmask;
1218
m_staticGateway=gateway;
1219
m_staticDns1 = dns1;
1221
m_dontOverrideGw=dontOverrideGw;
1222
m_dontOverrideDns=dontOverrideDns;
1224
m_dnsSearchlist = dnsSearchlist;
1228
void KwlanInterface::enableInterface( bool enable)
1230
if (!m_controlInterface || !m_configureInterface) return;
1231
KwlanSuProcess *ifup = new KwlanSuProcess();
1233
*ifup << m_ifconfigPath << m_controlInterface << "up";
1234
ifup->setDescription( i18n("Enable interface"));
1235
//ifup->start(SuProcessBase::Block );
1238
else if (m_type != PPP){
1239
//releaseIpAddress(); // Don't release IP Address as it will reenable the interface if
1240
// it is run after setting the interface to down state.
1241
// TODO: Release IP Address and connect processExited with function to set interface down
1242
*ifup << m_ifconfigPath << m_controlInterface << "down";
1243
ifup->setDescription( i18n("Disable interface"));
1244
//ifup->start( SuProcessBase::Block );
1250
void KwlanInterface::slotNewProfile()
1252
KProfileConfigDlg *profileDlg = new KProfileConfigDlg();
1253
if (!profileDlg) return;
1254
profileDlg->setInterface(this);
1255
profileDlg->newNetwork();
1258
emit (networksChanged());
1262
void KwlanInterface::slotEditProfile(QString profile)
1265
//int wpaId = getWpaId( profile);
1267
// Open Config Dialog
1268
KProfileConfigDlg *profileDlg = new KProfileConfigDlg();
1269
if (!profileDlg) return;
1270
profileDlg->setInterface(this);
1271
profileDlg->paramsFromConfig(this, profile);
1272
//profileDlg->show();
1276
void KwlanInterface::slotDeleteProfile(QString profile)
1278
char cmd[256],reply[100];
1279
size_t reply_len = sizeof(reply);
1280
if (!m_controlConnection && !m_wpaStarted) {
1281
int result = KMessageBox::questionYesNo(0,"wpa_supplicant is not started. Only the non-wpa related network settings will be deleted.\n"
1282
"Do you want to delete these settings?");
1283
if (result == KMessageBox::Yes){
1284
m_configuration->deleteNetwork( profile);
1288
int id = getWpaId(profile);
1289
snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %i", id);
1290
reply_len = sizeof(reply);
1291
ctrlRequest(cmd, reply, &reply_len);
1292
if (strncmp(reply, "OK", 2) != 0) {
1293
KMessageBox::sorry(0, i18n("Failed to remove network from wpa_supplicant\nconfiguration."));
1295
reply_len = sizeof(reply);
1296
ctrlRequest("SAVE_CONFIG", reply, &reply_len);
1297
if (strncmp(reply,"OK",2) != 0) {
1298
KMessageBox::sorry(0, "Failed to save the wpa_supplicant configuration.\nIs update_config=1 defined in wpa_supplicant.conf?");
1301
m_configuration->deleteNetwork( profile);
1302
emit (networksChanged());
1305
void KwlanInterface::startScriptAfterConnect()
1307
// Now start script after connect if configured
1310
m_configuration->readScriptAfterConnect( m_ssid,script, useRoot);
1311
if (::debugOutput) kdDebug() << "Now starting script after connect "<< script << endl;
1312
if (!script.isEmpty())
1315
KwlanSuProcess *proc = new KwlanSuProcess();
1317
proc->setDescription( i18n("start script after connect"));
1321
KProcess *proc = new KProcess();
1328
unsigned long KwlanInterface::readInterfaceNumValue(const char* name)
1330
// stdio functions appear to be more fast than QFile?
1331
FILE* fp = fopen((m_sysClassPath+name).latin1(), "r");
1334
fscanf(fp, "%lu", &retval);
1339
bool KwlanInterface::openFdSocket() {
1342
if ((m_fdSock = socket(AF_INET, SOCK_DGRAM, 0)) > 0)
1347
void KwlanInterface::say(QString message) {
1348
emit sigMessage(message);
1352
void KwlanInterface::newInterfaceWizard(QString interface)
1354
int res = KMessageBox::warningContinueCancel(0,QString(i18n("New interface found!\n%1\n Click Continue to configure it now.")).arg(interface),"Kwlan",
1355
KStdGuiItem::cont(),"newinterfacewizard");
1356
if (res == KMessageBox::Continue)
1358
//User wants to configure interface
1359
int result = KMessageBox::questionYesNo(0, i18n("Do you want to start wpa_supplicant for this interface?"));
1360
if (result == KMessageBox::Yes)
1362
KStartSupplicantDlg *startSupplicant = new KStartSupplicantDlg();
1364
if (m_interfaceData.wirelessDevice) driver = "wext";
1365
else driver = "wired";
1366
if (startSupplicant ){
1367
startSupplicant->setData(&interface,&driver);
1368
// startSupplicant->show();
1369
startSupplicant->exec();
1371
QString wpa_supplicant;
1372
if (startSupplicant->m_start){
1373
KwlanSuProcess *startWpa= new KwlanSuProcess(NULL,"Start WPA Supplicant");
1374
*startWpa << m_wpaPath << QString("-i%1").arg(QString(m_controlInterface)) << QString ("-D%1").arg(startSupplicant->getDriver()) << QString("-c")+ m_wpaConf << "-B";
1375
startWpa->setDescription(i18n("Start WPA Supplicant"));
1377
m_configuration->writeDriver(startSupplicant->getDriver());
1379
delete startSupplicant;
1380
// show wpa settings
1381
KwlanSettingsDlg *settings = new KwlanSettingsDlg();
1382
settings->setConfiguraton( m_configuration);
1384
if (!settings) return;
1385
settings->setCaption(QString(i18n("Settings for %1")).arg(interface));
1389
// Now add a default profile
1392
m_networkChange = true;
1395
void KwlanInterface::slotEnableConfigureInterface(QString interface, bool enable)
1397
if (interface != QString(m_controlInterface)) return;
1398
m_configureInterface = enable;
1401
void KwlanInterface::slotScan()
1408
m_scanDlg = new KScanDlg();
1409
if (m_scanDlg == NULL)
1411
m_scanDlg->setInterface(this);
1416
void KwlanInterface::slotScanAvailableNetworks()
1418
//avoid mulitple scans due timeout of scann being longer than scan interval
1419
if (m_isScanning | (!m_interfaceData.wirelessDevice)) return;
1420
m_isScanning = TRUE;
1421
QStringList configuredProfiles = listProfiles();
1422
char buf[2048]; QString signal;
1423
m_availableNetworks.clear();
1424
size_t len =sizeof(buf);
1425
// Are we connected to wpa? If so, send scan request
1426
// We are not using the results but without it the iwlib functions
1427
// will not return any network;
1428
if (m_controlConnection) {
1429
if (ctrlRequest("SCAN", buf, &len) < 0)
1431
kdDebug() << "Could not scan for wpa available networks" << endl;
1435
kwireless_scan(m_availableNetworks,m_controlInterface);
1436
// check if found networks are already configured
1437
for (kwlNetworkList::iterator it = m_availableNetworks.begin();it != m_availableNetworks.end();it++)
1439
QStringList::Iterator index = configuredProfiles.find((*it).m_ssid);
1440
if ((*index).isEmpty())
1442
(*it).m_isConfigured = FALSE;
1443
} else (*it).m_isConfigured = TRUE;
1446
m_isScanning = FALSE;
1451
kwlNetworkList KwlanInterface::getAvailableProfiles()
1453
QStringList profiles = listProfiles();
1454
if ( !m_interfaceData.wirelessDevice )
1456
kwlNetworkList tmpList;
1457
for (QStringList::Iterator it = profiles.begin(); it != profiles.end();it++)
1459
tmpList.append(kwlNetwork(*it));
1463
return m_availableNetworks;