9904b53d67
"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.
245 lines
5.6 KiB
C++
245 lines
5.6 KiB
C++
/*
|
|
* 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();
|
|
}
|