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


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:39