wpa_ctrl.c

Go to the documentation of this file.
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 /* CONFIG_CTRL_IFACE_UNIX */
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 /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
00050 #ifdef CONFIG_CTRL_IFACE_UNIX
00051         int s;
00052         struct sockaddr_un local;
00053         struct sockaddr_un dest;
00054 #endif /* CONFIG_CTRL_IFACE_UNIX */
00055 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
00056         HANDLE pipe;
00057 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
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                          * getpid() returns unique identifier for this instance
00098                          * of wpa_ctrl, so the existing socket file must have
00099                          * been left by unclean termination of an earlier run.
00100                          * Remove the file and try again.
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 /* CONFIG_CTRL_IFACE_UNIX */
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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                                 /* This is an unsolicited message from
00250                                  * wpa_supplicant, not the reply to the
00251                                  * request. Use msg_cb to report this to the
00252                                  * caller. */
00253                                 if (msg_cb) {
00254                                         /* Make sure the message is nul
00255                                          * terminated. */
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 /* CTRL_IFACE_SOCKET */
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 /* CTRL_IFACE_SOCKET */
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 /* UNICODE */
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 /* UNICODE */
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                  * Current named pipe server side in wpa_supplicant is
00379                  * re-opening the pipe for new clients only after the previous
00380                  * one is taken into use. This leaves a small window for race
00381                  * conditions when two connections are being opened at almost
00382                  * the same time. Retry if that was the case.
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 /* CONFIG_CTRL_IFACE_NAMED_PIPE */
00456 
00457 #endif /* CONFIG_CTRL_IFACE */
00458 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:49 2009 for hostapd by  doxygen 1.6.1