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