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 29AddInterface::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 56void 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 102bool 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 182void 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