]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wpa_gui-qt4: Added support for adding new network interfaces
authorJouni Malinen <j@w1.fi>
Thu, 25 Dec 2008 14:38:09 +0000 (16:38 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 25 Dec 2008 14:38:09 +0000 (16:38 +0200)
"Add interface" command in File menu can now be used to add a new
network interface to running wpa_supplicant (using INTERFACE_ADD control
interface command). In addition, the network interface is added into
Windows registry (with skip_on_error) for future use. This functionality
is currently enabled only for Windows builds. The user is also prompted
about the possibility of adding an interface if no interfaces are
enabled. This makes it easier to get started without having to touch
registry manually.

wpa_supplicant/wpa_gui-qt4/addinterface.cpp [new file with mode: 0644]
wpa_supplicant/wpa_gui-qt4/addinterface.h [new file with mode: 0644]
wpa_supplicant/wpa_gui-qt4/wpa_gui.pro
wpa_supplicant/wpa_gui-qt4/wpagui.cpp
wpa_supplicant/wpa_gui-qt4/wpagui.h

diff --git a/wpa_supplicant/wpa_gui-qt4/addinterface.cpp b/wpa_supplicant/wpa_gui-qt4/addinterface.cpp
new file mode 100644 (file)
index 0000000..4d3603a
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * wpa_gui - AddInterface class
+ * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ *
+ * 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 <cstdio>
+#include "wpa_ctrl.h"
+
+#include <QMessageBox>
+
+#include "wpagui.h"
+#include "addinterface.h"
+
+#ifdef CONFIG_NATIVE_WINDOWS
+#include <windows.h>
+
+#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 <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
+        * <driver_param>TAB<bridge_name>
+        */
+       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 (file)
index 0000000..9d9476a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * wpa_gui - AddInterface class
+ * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ *
+ * 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 <QObject>
+
+#include <QtGui/QDialog>
+#include <QtGui/QTreeWidget>
+#include <QtGui/QVBoxLayout>
+
+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 */
index 5efc07ff88e2a85a96297675fec79a281c4a38bb..2317cbd48d0430a7700a51a1480d80a83fd1195c 100644 (file)
@@ -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
index 20bb353e348b0fc9f89b18ac94921210a8ed569d..aca98f8035c3df6ba8f0f0cdf24c209d76726464 100644 (file)
@@ -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();
+}
index e433832b1814960782112234928edce68fe25b17..2b14458edc7550164ffc9ca85b4d732c9d35c98a 100644 (file)
@@ -18,6 +18,7 @@
 #include <QSystemTrayIcon>
 #include <QObject>
 #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 */