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