00001
00016 #include "includes.h"
00017
00018 #ifdef CONFIG_CTRL_IFACE
00019
00020 #ifdef CONFIG_CTRL_IFACE_UNIX
00021 #include <sys/un.h>
00022 #endif
00023
00024 #include "wpa_ctrl.h"
00025 #include "common.h"
00026
00027
00028 #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
00029 #define CTRL_IFACE_SOCKET
00030 #endif
00031
00032
00043 struct wpa_ctrl {
00044 #ifdef CONFIG_CTRL_IFACE_UDP
00045 int s;
00046 struct sockaddr_in local;
00047 struct sockaddr_in dest;
00048 char *cookie;
00049 #endif
00050 #ifdef CONFIG_CTRL_IFACE_UNIX
00051 int s;
00052 struct sockaddr_un local;
00053 struct sockaddr_un dest;
00054 #endif
00055 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
00056 HANDLE pipe;
00057 #endif
00058 };
00059
00060
00061 #ifdef CONFIG_CTRL_IFACE_UNIX
00062
00063 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
00064 {
00065 struct wpa_ctrl *ctrl;
00066 static int counter = 0;
00067 int ret;
00068 size_t res;
00069 int tries = 0;
00070
00071 ctrl = os_malloc(sizeof(*ctrl));
00072 if (ctrl == NULL)
00073 return NULL;
00074 os_memset(ctrl, 0, sizeof(*ctrl));
00075
00076 ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
00077 if (ctrl->s < 0) {
00078 os_free(ctrl);
00079 return NULL;
00080 }
00081
00082 ctrl->local.sun_family = AF_UNIX;
00083 counter++;
00084 try_again:
00085 ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
00086 "/tmp/wpa_ctrl_%d-%d", getpid(), counter);
00087 if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
00088 close(ctrl->s);
00089 os_free(ctrl);
00090 return NULL;
00091 }
00092 tries++;
00093 if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
00094 sizeof(ctrl->local)) < 0) {
00095 if (errno == EADDRINUSE && tries < 2) {
00096
00097
00098
00099
00100
00101
00102 unlink(ctrl->local.sun_path);
00103 goto try_again;
00104 }
00105 close(ctrl->s);
00106 os_free(ctrl);
00107 return NULL;
00108 }
00109
00110 ctrl->dest.sun_family = AF_UNIX;
00111 res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
00112 sizeof(ctrl->dest.sun_path));
00113 if (res >= sizeof(ctrl->dest.sun_path)) {
00114 close(ctrl->s);
00115 os_free(ctrl);
00116 return NULL;
00117 }
00118 if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
00119 sizeof(ctrl->dest)) < 0) {
00120 close(ctrl->s);
00121 unlink(ctrl->local.sun_path);
00122 os_free(ctrl);
00123 return NULL;
00124 }
00125
00126 return ctrl;
00127 }
00128
00129
00130 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
00131 {
00132 unlink(ctrl->local.sun_path);
00133 close(ctrl->s);
00134 os_free(ctrl);
00135 }
00136
00137 #endif
00138
00139
00140 #ifdef CONFIG_CTRL_IFACE_UDP
00141
00142 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
00143 {
00144 struct wpa_ctrl *ctrl;
00145 char buf[128];
00146 size_t len;
00147
00148 ctrl = os_malloc(sizeof(*ctrl));
00149 if (ctrl == NULL)
00150 return NULL;
00151 os_memset(ctrl, 0, sizeof(*ctrl));
00152
00153 ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
00154 if (ctrl->s < 0) {
00155 perror("socket");
00156 os_free(ctrl);
00157 return NULL;
00158 }
00159
00160 ctrl->local.sin_family = AF_INET;
00161 ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
00162 if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
00163 sizeof(ctrl->local)) < 0) {
00164 close(ctrl->s);
00165 os_free(ctrl);
00166 return NULL;
00167 }
00168
00169 ctrl->dest.sin_family = AF_INET;
00170 ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
00171 ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
00172 if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
00173 sizeof(ctrl->dest)) < 0) {
00174 perror("connect");
00175 close(ctrl->s);
00176 os_free(ctrl);
00177 return NULL;
00178 }
00179
00180 len = sizeof(buf) - 1;
00181 if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
00182 buf[len] = '\0';
00183 ctrl->cookie = os_strdup(buf);
00184 }
00185
00186 return ctrl;
00187 }
00188
00189
00190 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
00191 {
00192 close(ctrl->s);
00193 os_free(ctrl->cookie);
00194 os_free(ctrl);
00195 }
00196
00197 #endif
00198
00199
00200 #ifdef CTRL_IFACE_SOCKET
00201 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
00202 char *reply, size_t *reply_len,
00203 void (*msg_cb)(char *msg, size_t len))
00204 {
00205 struct timeval tv;
00206 int res;
00207 fd_set rfds;
00208 const char *_cmd;
00209 char *cmd_buf = NULL;
00210 size_t _cmd_len;
00211
00212 #ifdef CONFIG_CTRL_IFACE_UDP
00213 if (ctrl->cookie) {
00214 char *pos;
00215 _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len;
00216 cmd_buf = os_malloc(_cmd_len);
00217 if (cmd_buf == NULL)
00218 return -1;
00219 _cmd = cmd_buf;
00220 pos = cmd_buf;
00221 os_strlcpy(pos, ctrl->cookie, _cmd_len);
00222 pos += os_strlen(ctrl->cookie);
00223 *pos++ = ' ';
00224 os_memcpy(pos, cmd, cmd_len);
00225 } else
00226 #endif
00227 {
00228 _cmd = cmd;
00229 _cmd_len = cmd_len;
00230 }
00231
00232 if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
00233 os_free(cmd_buf);
00234 return -1;
00235 }
00236 os_free(cmd_buf);
00237
00238 for (;;) {
00239 tv.tv_sec = 2;
00240 tv.tv_usec = 0;
00241 FD_ZERO(&rfds);
00242 FD_SET(ctrl->s, &rfds);
00243 res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
00244 if (FD_ISSET(ctrl->s, &rfds)) {
00245 res = recv(ctrl->s, reply, *reply_len, 0);
00246 if (res < 0)
00247 return res;
00248 if (res > 0 && reply[0] == '<') {
00249
00250
00251
00252
00253 if (msg_cb) {
00254
00255
00256 if ((size_t) res == *reply_len)
00257 res = (*reply_len) - 1;
00258 reply[res] = '\0';
00259 msg_cb(reply, res);
00260 }
00261 continue;
00262 }
00263 *reply_len = res;
00264 break;
00265 } else {
00266 return -2;
00267 }
00268 }
00269 return 0;
00270 }
00271 #endif
00272
00273
00274 static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
00275 {
00276 char buf[10];
00277 int ret;
00278 size_t len = 10;
00279
00280 ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
00281 buf, &len, NULL);
00282 if (ret < 0)
00283 return ret;
00284 if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
00285 return 0;
00286 return -1;
00287 }
00288
00289
00290 int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
00291 {
00292 return wpa_ctrl_attach_helper(ctrl, 1);
00293 }
00294
00295
00296 int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
00297 {
00298 return wpa_ctrl_attach_helper(ctrl, 0);
00299 }
00300
00301
00302 #ifdef CTRL_IFACE_SOCKET
00303
00304 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
00305 {
00306 int res;
00307
00308 res = recv(ctrl->s, reply, *reply_len, 0);
00309 if (res < 0)
00310 return res;
00311 *reply_len = res;
00312 return 0;
00313 }
00314
00315
00316 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
00317 {
00318 struct timeval tv;
00319 fd_set rfds;
00320 tv.tv_sec = 0;
00321 tv.tv_usec = 0;
00322 FD_ZERO(&rfds);
00323 FD_SET(ctrl->s, &rfds);
00324 select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
00325 return FD_ISSET(ctrl->s, &rfds);
00326 }
00327
00328
00329 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
00330 {
00331 return ctrl->s;
00332 }
00333
00334 #endif
00335
00336
00337 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
00338
00339 #ifndef WPA_SUPPLICANT_NAMED_PIPE
00340 #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
00341 #endif
00342 #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
00343
00344 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
00345 {
00346 struct wpa_ctrl *ctrl;
00347 DWORD mode;
00348 TCHAR name[256];
00349 int i, ret;
00350
00351 ctrl = os_malloc(sizeof(*ctrl));
00352 if (ctrl == NULL)
00353 return NULL;
00354 os_memset(ctrl, 0, sizeof(*ctrl));
00355
00356 #ifdef UNICODE
00357 if (ctrl_path == NULL)
00358 ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX);
00359 else
00360 ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
00361 ctrl_path);
00362 #else
00363 if (ctrl_path == NULL)
00364 ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX);
00365 else
00366 ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
00367 ctrl_path);
00368 #endif
00369 if (ret < 0 || ret >= 256) {
00370 os_free(ctrl);
00371 return NULL;
00372 }
00373
00374 for (i = 0; i < 10; i++) {
00375 ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
00376 NULL, OPEN_EXISTING, 0, NULL);
00377
00378
00379
00380
00381
00382
00383
00384 if (ctrl->pipe != INVALID_HANDLE_VALUE ||
00385 GetLastError() != ERROR_PIPE_BUSY)
00386 break;
00387 WaitNamedPipe(name, 1000);
00388 }
00389 if (ctrl->pipe == INVALID_HANDLE_VALUE) {
00390 os_free(ctrl);
00391 return NULL;
00392 }
00393
00394 mode = PIPE_READMODE_MESSAGE;
00395 if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
00396 CloseHandle(ctrl->pipe);
00397 os_free(ctrl);
00398 return NULL;
00399 }
00400
00401 return ctrl;
00402 }
00403
00404
00405 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
00406 {
00407 CloseHandle(ctrl->pipe);
00408 os_free(ctrl);
00409 }
00410
00411
00412 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
00413 char *reply, size_t *reply_len,
00414 void (*msg_cb)(char *msg, size_t len))
00415 {
00416 DWORD written;
00417 DWORD readlen = *reply_len;
00418
00419 if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
00420 return -1;
00421
00422 if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
00423 return -1;
00424 *reply_len = readlen;
00425
00426 return 0;
00427 }
00428
00429
00430 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
00431 {
00432 DWORD len = *reply_len;
00433 if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
00434 return -1;
00435 *reply_len = len;
00436 return 0;
00437 }
00438
00439
00440 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
00441 {
00442 DWORD left;
00443
00444 if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
00445 return -1;
00446 return left ? 1 : 0;
00447 }
00448
00449
00450 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
00451 {
00452 return -1;
00453 }
00454
00455 #endif
00456
00457 #endif
00458