diff --git a/wpa_supplicant/wpa_gui-qt4/addinterface.cpp b/wpa_supplicant/wpa_gui-qt4/addinterface.cpp new file mode 100644 index 000000000..4d3603a4d --- /dev/null +++ b/wpa_supplicant/wpa_gui-qt4/addinterface.cpp @@ -0,0 +1,245 @@ +/* + * wpa_gui - AddInterface class + * Copyright (c) 2008, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include +#include "wpa_ctrl.h" + +#include + +#include "wpagui.h" +#include "addinterface.h" + +#ifdef CONFIG_NATIVE_WINDOWS +#include + +#ifndef WPA_KEY_ROOT +#define WPA_KEY_ROOT HKEY_LOCAL_MACHINE +#endif +#ifndef WPA_KEY_PREFIX +#define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant") +#endif +#endif /* CONFIG_NATIVE_WINDOWS */ + + +AddInterface::AddInterface(WpaGui *_wpagui, QWidget *parent) + : QDialog(parent), wpagui(_wpagui) +{ + setWindowTitle("Select network interface to add"); + resize(400, 200); + vboxLayout = new QVBoxLayout(this); + + interfaceWidget = new QTreeWidget(this); + interfaceWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + interfaceWidget->setUniformRowHeights(true); + interfaceWidget->setSortingEnabled(true); + interfaceWidget->setColumnCount(3); + interfaceWidget->headerItem()->setText(0, "driver"); + interfaceWidget->headerItem()->setText(1, "interface"); + interfaceWidget->headerItem()->setText(2, "description"); + interfaceWidget->setItemsExpandable(FALSE); + interfaceWidget->setRootIsDecorated(FALSE); + vboxLayout->addWidget(interfaceWidget); + + connect(interfaceWidget, + SIGNAL(itemActivated(QTreeWidgetItem *, int)), this, + SLOT(interfaceSelected(QTreeWidgetItem *))); + + addInterfaces(); +} + + +void AddInterface::addInterfaces() +{ +#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE + struct wpa_ctrl *ctrl; + int ret; + char buf[2048]; + size_t len; + + ctrl = wpa_ctrl_open(NULL); + if (ctrl == NULL) + return; + + len = sizeof(buf) - 1; + ret = wpa_ctrl_request(ctrl, "INTERFACE_LIST", 14, buf, &len, NULL); + if (ret < 0) { + wpa_ctrl_close(ctrl); + return; + } + buf[len] = '\0'; + + wpa_ctrl_close(ctrl); + + QString ifaces(buf); + QStringList lines = ifaces.split(QRegExp("\\n")); + for (QStringList::Iterator it = lines.begin(); + it != lines.end(); it++) { + QStringList arg = (*it).split(QChar('\t')); + if (arg.size() < 3) + continue; + QTreeWidgetItem *item = new QTreeWidgetItem(interfaceWidget); + if (!item) + break; + + item->setText(0, arg[0]); + item->setText(1, arg[1]); + item->setText(2, arg[2]); + } + + interfaceWidget->resizeColumnToContents(0); + interfaceWidget->resizeColumnToContents(1); + interfaceWidget->resizeColumnToContents(2); +#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ +} + + +#ifdef CONFIG_NATIVE_WINDOWS +bool AddInterface::addRegistryInterface(const QString &ifname) +{ + HKEY hk, ihk; + LONG ret; + int id, tmp; + TCHAR name[10]; + DWORD val, i; + + ret = RegOpenKeyEx(WPA_KEY_ROOT, WPA_KEY_PREFIX TEXT("\\interfaces"), + 0, KEY_ENUMERATE_SUB_KEYS | KEY_CREATE_SUB_KEY, + &hk); + if (ret != ERROR_SUCCESS) + return false; + + id = -1; + + for (i = 0; ; i++) { + TCHAR name[255]; + DWORD namelen; + + namelen = 255; + ret = RegEnumKeyEx(hk, i, name, &namelen, NULL, NULL, NULL, + NULL); + + if (ret == ERROR_NO_MORE_ITEMS) + break; + + if (ret != ERROR_SUCCESS) + break; + + if (namelen >= 255) + namelen = 255 - 1; + name[namelen] = '\0'; + +#ifdef UNICODE + QString s((QChar *) name, namelen); +#else /* UNICODE */ + QString s(name); +#endif /* UNICODE */ + tmp = s.toInt(); + if (tmp > id) + id = tmp; + } + + id += 1; + +#ifdef UNICODE + wsprintf(name, L"%04d", id); +#else /* UNICODE */ + os_snprintf(name, sizeof(name), "%04d", id); +#endif /* UNICODE */ + ret = RegCreateKeyEx(hk, name, 0, NULL, 0, KEY_WRITE, NULL, &ihk, + NULL); + RegCloseKey(hk); + if (ret != ERROR_SUCCESS) + return false; + +#ifdef UNICODE + RegSetValueEx(ihk, TEXT("adapter"), 0, REG_SZ, + (LPBYTE) ifname.unicode(), + (ifname.length() + 1) * sizeof(TCHAR)); + +#else /* UNICODE */ + RegSetValueEx(ihk, TEXT("adapter"), 0, REG_SZ, + (LPBYTE) ifname.toLocal8Bit(), ifname.length() + 1); +#endif /* UNICODE */ + RegSetValueEx(ihk, TEXT("config"), 0, REG_SZ, + (LPBYTE) TEXT("default"), 8 * sizeof(TCHAR)); + RegSetValueEx(ihk, TEXT("ctrl_interface"), 0, REG_SZ, + (LPBYTE) TEXT(""), 1 * sizeof(TCHAR)); + val = 1; + RegSetValueEx(ihk, TEXT("skip_on_error"), 0, REG_DWORD, (LPBYTE) &val, + sizeof(val)); + + RegCloseKey(ihk); + return true; +} +#endif /* CONFIG_NATIVE_WINDOWS */ + + +void AddInterface::interfaceSelected(QTreeWidgetItem *sel) +{ + if (!sel) + return; + +#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE + struct wpa_ctrl *ctrl; + int ret; + char buf[20], cmd[256]; + size_t len; + + /* + * INTERFACE_ADD TABTABTABTAB + * TAB + */ + snprintf(cmd, sizeof(cmd), + "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s", + sel->text(1).toAscii().constData(), + "default", + sel->text(0).toAscii().constData(), + "", "", ""); + cmd[sizeof(cmd) - 1] = '\0'; + + ctrl = wpa_ctrl_open(NULL); + if (ctrl == NULL) + return; + + len = sizeof(buf) - 1; + ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL); + wpa_ctrl_close(ctrl); + + if (ret < 0) { + QMessageBox::warning(this, "wpa_gui", + "Add interface command could not be " + "completed."); + return; + } + + buf[len] = '\0'; + if (buf[0] != 'O' || buf[1] != 'K') { + QMessageBox::warning(this, "wpa_gui", + "Failed to add the interface."); + return; + } + +#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ + +#ifdef CONFIG_NATIVE_WINDOWS + if (!addRegistryInterface(sel->text(1))) { + QMessageBox::information(this, "wpa_gui", + "Failed to add the interface into " + "registry."); + } +#endif /* CONFIG_NATIVE_WINDOWS */ + + wpagui->selectAdapter(sel->text(1)); + close(); +} diff --git a/wpa_supplicant/wpa_gui-qt4/addinterface.h b/wpa_supplicant/wpa_gui-qt4/addinterface.h new file mode 100644 index 000000000..9d9476a46 --- /dev/null +++ b/wpa_supplicant/wpa_gui-qt4/addinterface.h @@ -0,0 +1,45 @@ +/* + * wpa_gui - AddInterface class + * Copyright (c) 2008, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef ADDINTERFACE_H +#define ADDINTERFACE_H + +#include + +#include +#include +#include + +class WpaGui; + +class AddInterface : public QDialog +{ + Q_OBJECT + +public: + AddInterface(WpaGui *_wpagui, QWidget *parent = 0); + +public slots: + virtual void interfaceSelected(QTreeWidgetItem *sel); + +private: + void addInterfaces(); + bool addRegistryInterface(const QString &ifname); + + QVBoxLayout *vboxLayout; + QTreeWidget *interfaceWidget; + WpaGui *wpagui; +}; + +#endif /* ADDINTERFACE_H */ diff --git a/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro b/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro index 5efc07ff8..2317cbd48 100644 --- a/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro +++ b/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro @@ -34,7 +34,8 @@ HEADERS += wpamsg.h \ eventhistory.h \ scanresults.h \ userdatarequest.h \ - networkconfig.h + networkconfig.h \ + addinterface.h SOURCES += main.cpp \ wpagui.cpp \ @@ -42,6 +43,7 @@ SOURCES += main.cpp \ scanresults.cpp \ userdatarequest.cpp \ networkconfig.cpp \ + addinterface.cpp \ ../../src/common/wpa_ctrl.c RESOURCES += icons.qrc diff --git a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp index 20bb353e3..aca98f803 100644 --- a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp +++ b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp @@ -61,6 +61,13 @@ WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags) SLOT(startService())); connect(fileStopServiceAction, SIGNAL(triggered()), this, SLOT(stopService())); + + addInterfaceAction = new QAction(this); + addInterfaceAction->setIconText("Add Interface"); + fileMenu->insertAction(fileStartServiceAction, addInterfaceAction); + + connect(addInterfaceAction, SIGNAL(triggered()), this, + SLOT(addInterface())); #endif /* CONFIG_NATIVE_WINDOWS */ (void) statusBar(); @@ -118,6 +125,7 @@ WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags) eh = NULL; scanres = NULL; + add_iface = NULL; udr = NULL; tray_icon = NULL; startInTray = false; @@ -177,6 +185,12 @@ WpaGui::~WpaGui() scanres = NULL; } + if (add_iface) { + add_iface->close(); + delete add_iface; + add_iface = NULL; + } + if (udr) { udr->close(); delete udr; @@ -438,6 +452,20 @@ void WpaGui::updateStatus() textSsid->clear(); textBssid->clear(); textIpAddress->clear(); + +#ifdef CONFIG_NATIVE_WINDOWS + static bool first = true; + if (first && (ctrl_iface == NULL || *ctrl_iface == '\0')) { + first = false; + if (QMessageBox::information( + this, qAppName(), + "No network interfaces in use.\n" + "Would you like to add one?", + QMessageBox::Yes | QMessageBox::No) == + QMessageBox::Yes) + addInterface(); + } +#endif /* CONFIG_NATIVE_WINDOWS */ return; } @@ -1620,3 +1648,15 @@ bool WpaGui::serviceRunning() } #endif /* CONFIG_NATIVE_WINDOWS */ + + +void WpaGui::addInterface() +{ + if (add_iface) { + add_iface->close(); + delete add_iface; + } + add_iface = new AddInterface(this, this); + add_iface->show(); + add_iface->exec(); +} diff --git a/wpa_supplicant/wpa_gui-qt4/wpagui.h b/wpa_supplicant/wpa_gui-qt4/wpagui.h index e433832b1..2b14458ed 100644 --- a/wpa_supplicant/wpa_gui-qt4/wpagui.h +++ b/wpa_supplicant/wpa_gui-qt4/wpagui.h @@ -18,6 +18,7 @@ #include #include #include "ui_wpagui.h" +#include "addinterface.h" class UserDataRequest; @@ -82,6 +83,7 @@ public slots: virtual void startService(); virtual void stopService(); #endif /* CONFIG_NATIVE_WINDOWS */ + virtual void addInterface(); protected slots: virtual void languageChange(); @@ -129,6 +131,9 @@ private: bool serviceRunning(); #endif /* CONFIG_NATIVE_WINDOWS */ + + QAction *addInterfaceAction; + AddInterface *add_iface; }; #endif /* WPAGUI_H */