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