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 
00068         ctrl = os_malloc(sizeof(*ctrl));
00069         if (ctrl == NULL)
00070                 return NULL;
00071         os_memset(ctrl, 0, sizeof(*ctrl));
00072 
00073         ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
00074         if (ctrl->s < 0) {
00075                 os_free(ctrl);
00076                 return NULL;
00077         }
00078 
00079         ctrl->local.sun_family = AF_UNIX;
00080         os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
00081                     "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
00082         if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
00083                     sizeof(ctrl->local)) < 0) {
00084                 close(ctrl->s);
00085                 os_free(ctrl);
00086                 return NULL;
00087         }
00088 
00089         ctrl->dest.sun_family = AF_UNIX;
00090         os_snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "%s",
00091                     ctrl_path);
00092         if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
00093                     sizeof(ctrl->dest)) < 0) {
00094                 close(ctrl->s);
00095                 unlink(ctrl->local.sun_path);
00096                 os_free(ctrl);
00097                 return NULL;
00098         }
00099 
00100         return ctrl;
00101 }
00102 
00103 
00104 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
00105 {
00106         unlink(ctrl->local.sun_path);
00107         close(ctrl->s);
00108         os_free(ctrl);
00109 }
00110 
00111 #endif /* CONFIG_CTRL_IFACE_UNIX */
00112 
00113 
00114 #ifdef CONFIG_CTRL_IFACE_UDP
00115 
00116 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
00117 {
00118         struct wpa_ctrl *ctrl;
00119         char buf[128];
00120         size_t len;
00121 
00122         ctrl = os_malloc(sizeof(*ctrl));
00123         if (ctrl == NULL)
00124                 return NULL;
00125         os_memset(ctrl, 0, sizeof(*ctrl));
00126 
00127         ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
00128         if (ctrl->s < 0) {
00129                 perror("socket");
00130                 os_free(ctrl);
00131                 return NULL;
00132         }
00133 
00134         ctrl->local.sin_family = AF_INET;
00135         ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
00136         if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
00137                  sizeof(ctrl->local)) < 0) {
00138                 close(ctrl->s);
00139                 os_free(ctrl);
00140                 return NULL;
00141         }
00142 
00143         ctrl->dest.sin_family = AF_INET;
00144         ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
00145         ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
00146         if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
00147                     sizeof(ctrl->dest)) < 0) {
00148                 perror("connect");
00149                 close(ctrl->s);
00150                 os_free(ctrl);
00151                 return NULL;
00152         }
00153 
00154         len = sizeof(buf) - 1;
00155         if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
00156                 buf[len] = '\0';
00157                 ctrl->cookie = strdup(buf);
00158         }
00159 
00160         return ctrl;
00161 }
00162 
00163 
00164 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
00165 {
00166         close(ctrl->s);
00167         os_free(ctrl->cookie);
00168         os_free(ctrl);
00169 }
00170 
00171 #endif /* CONFIG_CTRL_IFACE_UDP */
00172 
00173 
00174 #ifdef CTRL_IFACE_SOCKET
00175 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
00176                      char *reply, size_t *reply_len,
00177                      void (*msg_cb)(char *msg, size_t len))
00178 {
00179         struct timeval tv;
00180         int res;
00181         fd_set rfds;
00182         const char *_cmd;
00183         char *cmd_buf = NULL;
00184         size_t _cmd_len;
00185 
00186 #ifdef CONFIG_CTRL_IFACE_UDP
00187         if (ctrl->cookie) {
00188                 char *pos;
00189                 _cmd_len = strlen(ctrl->cookie) + 1 + cmd_len;
00190                 cmd_buf = os_malloc(_cmd_len );
00191                 if (cmd_buf == NULL)
00192                         return -1;
00193                 _cmd = cmd_buf;
00194                 pos = cmd_buf;
00195                 strcpy(pos, ctrl->cookie);
00196                 pos += strlen(ctrl->cookie);
00197                 *pos++ = ' ';
00198                 memcpy(pos, cmd, cmd_len);
00199         } else
00200 #endif /* CONFIG_CTRL_IFACE_UDP */
00201         {
00202                 _cmd = cmd;
00203                 _cmd_len = cmd_len;
00204         }
00205 
00206         if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
00207                 os_free(cmd_buf);
00208                 return -1;
00209         }
00210         os_free(cmd_buf);
00211 
00212         for (;;) {
00213                 tv.tv_sec = 2;
00214                 tv.tv_usec = 0;
00215                 FD_ZERO(&rfds);
00216                 FD_SET(ctrl->s, &rfds);
00217                 res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
00218                 if (FD_ISSET(ctrl->s, &rfds)) {
00219                         res = recv(ctrl->s, reply, *reply_len, 0);
00220                         if (res < 0)
00221                                 return res;
00222                         if (res > 0 && reply[0] == '<') {
00223                                 /* This is an unsolicited message from
00224                                  * wpa_supplicant, not the reply to the
00225                                  * request. Use msg_cb to report this to the
00226                                  * caller. */
00227                                 if (msg_cb) {
00228                                         /* Make sure the message is nul
00229                                          * terminated. */
00230                                         if ((size_t) res == *reply_len)
00231                                                 res = (*reply_len) - 1;
00232                                         reply[res] = '\0';
00233                                         msg_cb(reply, res);
00234                                 }
00235                                 continue;
00236                         }
00237                         *reply_len = res;
00238                         break;
00239                 } else {
00240                         return -2;
00241                 }
00242         }
00243         return 0;
00244 }
00245 #endif /* CTRL_IFACE_SOCKET */
00246 
00247 
00248 static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
00249 {
00250         char buf[10];
00251         int ret;
00252         size_t len = 10;
00253 
00254         ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
00255                                buf, &len, NULL);
00256         if (ret < 0)
00257                 return ret;
00258         if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
00259                 return 0;
00260         return -1;
00261 }
00262 
00263 
00264 int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
00265 {
00266         return wpa_ctrl_attach_helper(ctrl, 1);
00267 }
00268 
00269 
00270 int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
00271 {
00272         return wpa_ctrl_attach_helper(ctrl, 0);
00273 }
00274 
00275 
00276 #ifdef CTRL_IFACE_SOCKET
00277 
00278 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
00279 {
00280         int res;
00281 
00282         res = recv(ctrl->s, reply, *reply_len, 0);
00283         if (res < 0)
00284                 return res;
00285         *reply_len = res;
00286         return 0;
00287 }
00288 
00289 
00290 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
00291 {
00292         struct timeval tv;
00293         int res;
00294         fd_set rfds;
00295         tv.tv_sec = 0;
00296         tv.tv_usec = 0;
00297         FD_ZERO(&rfds);
00298         FD_SET(ctrl->s, &rfds);
00299         res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
00300         return FD_ISSET(ctrl->s, &rfds);
00301 }
00302 
00303 
00304 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
00305 {
00306         return ctrl->s;
00307 }
00308 
00309 #endif /* CTRL_IFACE_SOCKET */
00310 
00311 
00312 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
00313 
00314 #ifndef WPA_SUPPLICANT_NAMED_PIPE
00315 #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
00316 #endif
00317 #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
00318 
00319 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
00320 {
00321         struct wpa_ctrl *ctrl;
00322         DWORD mode;
00323         TCHAR name[256];
00324         int i;
00325 
00326         ctrl = os_malloc(sizeof(*ctrl));
00327         if (ctrl == NULL)
00328                 return NULL;
00329         os_memset(ctrl, 0, sizeof(*ctrl));
00330 
00331 #ifdef UNICODE
00332         if (ctrl_path == NULL)
00333                 _snwprintf(name, 256, NAMED_PIPE_PREFIX);
00334         else
00335                 _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
00336                            ctrl_path);
00337 #else /* UNICODE */
00338         if (ctrl_path == NULL)
00339                 os_snprintf(name, 256, NAMED_PIPE_PREFIX);
00340         else
00341                 os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
00342                             ctrl_path);
00343 #endif /* UNICODE */
00344 
00345         for (i = 0; i < 10; i++) {
00346                 ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
00347                                         NULL, OPEN_EXISTING, 0, NULL);
00348                 /*
00349                  * Current named pipe server side in wpa_supplicant is
00350                  * re-opening the pipe for new clients only after the previous
00351                  * one is taken into use. This leaves a small window for race
00352                  * conditions when two connections are being opened at almost
00353                  * the same time. Retry if that was the case.
00354                  */
00355                 if (ctrl->pipe != INVALID_HANDLE_VALUE ||
00356                     GetLastError() != ERROR_PIPE_BUSY)
00357                         break;
00358                 WaitNamedPipe(name, 1000);
00359         }
00360         if (ctrl->pipe == INVALID_HANDLE_VALUE) {
00361                 os_free(ctrl);
00362                 return NULL;
00363         }
00364 
00365         mode = PIPE_READMODE_MESSAGE;
00366         if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
00367                 CloseHandle(ctrl->pipe);
00368                 os_free(ctrl);
00369                 return NULL;
00370         }
00371 
00372         return ctrl;
00373 }
00374 
00375 
00376 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
00377 {
00378         CloseHandle(ctrl->pipe);
00379         os_free(ctrl);
00380 }
00381 
00382 
00383 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
00384                      char *reply, size_t *reply_len,
00385                      void (*msg_cb)(char *msg, size_t len))
00386 {
00387         DWORD written;
00388         DWORD readlen = *reply_len;
00389 
00390         if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
00391                 return -1;
00392 
00393         if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
00394                 return -1;
00395         *reply_len = readlen;
00396 
00397         return 0;
00398 }
00399 
00400 
00401 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
00402 {
00403         DWORD len = *reply_len;
00404         if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
00405                 return -1;
00406         *reply_len = len;
00407         return 0;
00408 }
00409 
00410 
00411 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
00412 {
00413         DWORD left;
00414 
00415         if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
00416                 return -1;
00417         return left ? 1 : 0;
00418 }
00419 
00420 
00421 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
00422 {
00423         return -1;
00424 }
00425 
00426 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
00427 
00428 #endif /* CONFIG_CTRL_IFACE */
00429 

Generated on Sun Dec 31 13:43:29 2006 for hostapd by  doxygen 1.4.2