1/*
2 * wpa_gui - AddInterface class
3 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include <cstdio>
16#include "wpa_ctrl.h"
17
18#include <QMessageBox>
19
20#include "wpagui.h"
21#include "addinterface.h"
22
23#ifdef CONFIG_NATIVE_WINDOWS
24#include <windows.h>
25
26#ifndef WPA_KEY_ROOT
27#define WPA_KEY_ROOT HKEY_LOCAL_MACHINE
28#endif
29#ifndef WPA_KEY_PREFIX
30#define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant")
31#endif
32#endif /* CONFIG_NATIVE_WINDOWS */
33
34
35AddInterface::AddInterface(WpaGui *_wpagui, QWidget *parent)
36	: QDialog(parent), wpagui(_wpagui)
37{
38	setWindowTitle("Select network interface to add");
39	resize(400, 200);
40	vboxLayout = new QVBoxLayout(this);
41
42	interfaceWidget = new QTreeWidget(this);
43	interfaceWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
44	interfaceWidget->setUniformRowHeights(true);
45	interfaceWidget->setSortingEnabled(true);
46	interfaceWidget->setColumnCount(3);
47	interfaceWidget->headerItem()->setText(0, "driver");
48	interfaceWidget->headerItem()->setText(1, "interface");
49	interfaceWidget->headerItem()->setText(2, "description");
50	interfaceWidget->setItemsExpandable(FALSE);
51	interfaceWidget->setRootIsDecorated(FALSE);
52	vboxLayout->addWidget(interfaceWidget);
53
54	connect(interfaceWidget,
55		SIGNAL(itemActivated(QTreeWidgetItem *, int)), this,
56		SLOT(interfaceSelected(QTreeWidgetItem *)));
57
58	addInterfaces();
59}
60
61
62void AddInterface::addInterfaces()
63{
64#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
65	struct wpa_ctrl *ctrl;
66	int ret;
67	char buf[2048];
68	size_t len;
69
70	ctrl = wpa_ctrl_open(NULL);
71	if (ctrl == NULL)
72		return;
73
74	len = sizeof(buf) - 1;
75	ret = wpa_ctrl_request(ctrl, "INTERFACE_LIST", 14, buf, &len, NULL);
76	if (ret < 0) {
77		wpa_ctrl_close(ctrl);
78		return;
79	}
80	buf[len] = '\0';
81
82	wpa_ctrl_close(ctrl);
83
84	QString ifaces(buf);
85	QStringList lines = ifaces.split(QRegExp("\\n"));
86	for (QStringList::Iterator it = lines.begin();
87	     it != lines.end(); it++) {
88		QStringList arg = (*it).split(QChar('\t'));
89		if (arg.size() < 3)
90			continue;
91		QTreeWidgetItem *item = new QTreeWidgetItem(interfaceWidget);
92		if (!item)
93			break;
94
95		item->setText(0, arg[0]);
96		item->setText(1, arg[1]);
97		item->setText(2, arg[2]);
98	}
99
100	interfaceWidget->resizeColumnToContents(0);
101	interfaceWidget->resizeColumnToContents(1);
102	interfaceWidget->resizeColumnToContents(2);
103#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
104}
105
106
107#ifdef CONFIG_NATIVE_WINDOWS
108bool AddInterface::addRegistryInterface(const QString &ifname)
109{
110	HKEY hk, ihk;
111	LONG ret;
112	int id, tmp;
113	TCHAR name[10];
114	DWORD val, i;
115
116	ret = RegOpenKeyEx(WPA_KEY_ROOT, WPA_KEY_PREFIX TEXT("\\interfaces"),
117			   0, KEY_ENUMERATE_SUB_KEYS | KEY_CREATE_SUB_KEY,
118			   &hk);
119	if (ret != ERROR_SUCCESS)
120		return false;
121
122	id = -1;
123
124	for (i = 0; ; i++) {
125		TCHAR name[255];
126		DWORD namelen;
127
128		namelen = 255;
129		ret = RegEnumKeyEx(hk, i, name, &namelen, NULL, NULL, NULL,
130				   NULL);
131
132		if (ret == ERROR_NO_MORE_ITEMS)
133			break;
134
135		if (ret != ERROR_SUCCESS)
136			break;
137
138		if (namelen >= 255)
139			namelen = 255 - 1;
140		name[namelen] = '\0';
141
142#ifdef UNICODE
143		QString s((QChar *) name, namelen);
144#else /* UNICODE */
145		QString s(name);
146#endif /* UNICODE */
147		tmp = s.toInt();
148		if (tmp > id)
149			id = tmp;
150	}
151
152	id += 1;
153
154#ifdef UNICODE
155	wsprintf(name, L"%04d", id);
156#else /* UNICODE */
157	os_snprintf(name, sizeof(name), "%04d", id);
158#endif /* UNICODE */
159	ret = RegCreateKeyEx(hk, name, 0, NULL, 0, KEY_WRITE, NULL, &ihk,
160			     NULL);
161	RegCloseKey(hk);
162	if (ret != ERROR_SUCCESS)
163		return false;
164
165#ifdef UNICODE
166	RegSetValueEx(ihk, TEXT("adapter"), 0, REG_SZ,
167		      (LPBYTE) ifname.unicode(),
168		      (ifname.length() + 1) * sizeof(TCHAR));
169
170#else /* UNICODE */
171	RegSetValueEx(ihk, TEXT("adapter"), 0, REG_SZ,
172		      (LPBYTE) ifname.toLocal8Bit(), ifname.length() + 1);
173#endif /* UNICODE */
174	RegSetValueEx(ihk, TEXT("config"), 0, REG_SZ,
175		      (LPBYTE) TEXT("default"), 8 * sizeof(TCHAR));
176	RegSetValueEx(ihk, TEXT("ctrl_interface"), 0, REG_SZ,
177		      (LPBYTE) TEXT(""), 1 * sizeof(TCHAR));
178	val = 1;
179	RegSetValueEx(ihk, TEXT("skip_on_error"), 0, REG_DWORD, (LPBYTE) &val,
180		      sizeof(val));
181
182	RegCloseKey(ihk);
183	return true;
184}
185#endif /* CONFIG_NATIVE_WINDOWS */
186
187
188void AddInterface::interfaceSelected(QTreeWidgetItem *sel)
189{
190	if (!sel)
191		return;
192
193#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
194	struct wpa_ctrl *ctrl;
195	int ret;
196	char buf[20], cmd[256];
197	size_t len;
198
199	/*
200	 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
201	 * <driver_param>TAB<bridge_name>
202	 */
203	snprintf(cmd, sizeof(cmd),
204		 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
205		 sel->text(1).toAscii().constData(),
206		 "default",
207		 sel->text(0).toAscii().constData(),
208		 "yes", "", "");
209	cmd[sizeof(cmd) - 1] = '\0';
210
211	ctrl = wpa_ctrl_open(NULL);
212	if (ctrl == NULL)
213		return;
214
215	len = sizeof(buf) - 1;
216	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, NULL);
217	wpa_ctrl_close(ctrl);
218
219	if (ret < 0) {
220		QMessageBox::warning(this, "wpa_gui",
221				     "Add interface command could not be "
222				     "completed.");
223		return;
224	}
225
226	buf[len] = '\0';
227	if (buf[0] != 'O' || buf[1] != 'K') {
228		QMessageBox::warning(this, "wpa_gui",
229				     "Failed to add the interface.");
230		return;
231	}
232
233#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
234
235#ifdef CONFIG_NATIVE_WINDOWS
236	if (!addRegistryInterface(sel->text(1))) {
237		QMessageBox::information(this, "wpa_gui",
238					 "Failed to add the interface into "
239					 "registry.");
240	}
241#endif /* CONFIG_NATIVE_WINDOWS */
242
243	wpagui->selectAdapter(sel->text(1));
244	close();
245}
246