wpa_ctrl.c

Go to the documentation of this file.
00001 
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <unistd.h>
00020 #include <sys/types.h>
00021 #include <sys/time.h>
00022 #ifndef CONFIG_NATIVE_WINDOWS
00023 #include <sys/socket.h>
00024 #include <netinet/in.h>
00025 #include <sys/un.h>
00026 #endif /* CONFIG_NATIVE_WINDOWS */
00027 
00028 #include "wpa_ctrl.h"
00029 #ifdef CONFIG_NATIVE_WINDOWS
00030 #include "common.h"
00031 #endif /* CONFIG_NATIVE_WINDOWS */
00032 
00033 
00044 struct wpa_ctrl {
00045         int s;
00046 #ifdef CONFIG_CTRL_IFACE_UDP
00047         struct sockaddr_in local;
00048         struct sockaddr_in dest;
00049 #else /* CONFIG_CTRL_IFACE_UDP */
00050         struct sockaddr_un local;
00051         struct sockaddr_un dest;
00052 #endif /* CONFIG_CTRL_IFACE_UDP */
00053 };
00054 
00055 
00056 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
00057 {
00058         struct wpa_ctrl *ctrl;
00059 #ifndef CONFIG_CTRL_IFACE_UDP
00060         static int counter = 0;
00061 #endif /* CONFIG_CTRL_IFACE_UDP */
00062 
00063         ctrl = malloc(sizeof(*ctrl));
00064         if (ctrl == NULL)
00065                 return NULL;
00066         memset(ctrl, 0, sizeof(*ctrl));
00067 
00068 #ifdef CONFIG_CTRL_IFACE_UDP
00069         ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
00070         if (ctrl->s < 0) {
00071                 perror("socket");
00072                 free(ctrl);
00073                 return NULL;
00074         }
00075 
00076         ctrl->local.sin_family = AF_INET;
00077         ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
00078         if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
00079                  sizeof(ctrl->local)) < 0) {
00080                 close(ctrl->s);
00081                 free(ctrl);
00082                 return NULL;
00083         }
00084 
00085         ctrl->dest.sin_family = AF_INET;
00086         ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
00087         ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
00088         if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
00089                     sizeof(ctrl->dest)) < 0) {
00090                 perror("connect");
00091                 close(ctrl->s);
00092                 free(ctrl);
00093                 return NULL;
00094         }
00095 #else /* CONFIG_CTRL_IFACE_UDP */
00096         ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
00097         if (ctrl->s < 0) {
00098                 free(ctrl);
00099                 return NULL;
00100         }
00101 
00102         ctrl->local.sun_family = AF_UNIX;
00103         snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
00104                  "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
00105         if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
00106                     sizeof(ctrl->local)) < 0) {
00107                 close(ctrl->s);
00108                 free(ctrl);
00109                 return NULL;
00110         }
00111 
00112         ctrl->dest.sun_family = AF_UNIX;
00113         snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "%s",
00114                  ctrl_path);
00115         if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
00116                     sizeof(ctrl->dest)) < 0) {
00117                 close(ctrl->s);
00118                 unlink(ctrl->local.sun_path);
00119                 free(ctrl);
00120                 return NULL;
00121         }
00122 #endif /* CONFIG_CTRL_IFACE_UDP */
00123 
00124         return ctrl;
00125 }
00126 
00127 
00128 void wpa_ctrl_close(struct wpa_ctrl *ctrl)
00129 {
00130 #ifndef CONFIG_CTRL_IFACE_UDP
00131         unlink(ctrl->local.sun_path);
00132 #endif /* CONFIG_CTRL_IFACE_UDP */
00133         close(ctrl->s);
00134         free(ctrl);
00135 }
00136 
00137 
00138 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
00139                      char *reply, size_t *reply_len,
00140                      void (*msg_cb)(char *msg, size_t len))
00141 {
00142         struct timeval tv;
00143         int res;
00144         fd_set rfds;
00145 
00146         if (send(ctrl->s, cmd, cmd_len, 0) < 0)
00147                 return -1;
00148 
00149         for (;;) {
00150                 tv.tv_sec = 2;
00151                 tv.tv_usec = 0;
00152                 FD_ZERO(&rfds);
00153                 FD_SET(ctrl->s, &rfds);
00154                 res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
00155                 if (FD_ISSET(ctrl->s, &rfds)) {
00156                         res = recv(ctrl->s, reply, *reply_len, 0);
00157                         if (res < 0)
00158                                 return res;
00159                         if (res > 0 && reply[0] == '<') {
00160                                 /* This is an unsolicited message from
00161                                  * wpa_supplicant, not the reply to the
00162                                  * request. Use msg_cb to report this to the
00163                                  * caller. */
00164                                 if (msg_cb) {
00165                                         /* Make sure the message is nul
00166                                          * terminated. */
00167                                         if ((size_t) res == *reply_len)
00168                                                 res = (*reply_len) - 1;
00169                                         reply[res] = '\0';
00170                                         msg_cb(reply, res);
00171                                 }
00172                                 continue;
00173                         }
00174                         *reply_len = res;
00175                         break;
00176                 } else {
00177                         return -2;
00178                 }
00179         }
00180         return 0;
00181 }
00182 
00183 
00184 static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
00185 {
00186         char buf[10];
00187         int ret;
00188         size_t len = 10;
00189 
00190         ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
00191                                buf, &len, NULL);
00192         if (ret < 0)
00193                 return ret;
00194         if (len == 3 && memcmp(buf, "OK\n", 3) == 0)
00195                 return 0;
00196         return -1;
00197 }
00198 
00199 
00200 int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
00201 {
00202         return wpa_ctrl_attach_helper(ctrl, 1);
00203 }
00204 
00205 
00206 int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
00207 {
00208         return wpa_ctrl_attach_helper(ctrl, 0);
00209 }
00210 
00211 
00212 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
00213 {
00214         int res;
00215 
00216         res = recv(ctrl->s, reply, *reply_len, 0);
00217         if (res < 0)
00218                 return res;
00219         *reply_len = res;
00220         return 0;
00221 }
00222 
00223 
00224 int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
00225 {
00226         struct timeval tv;
00227         int res;
00228         fd_set rfds;
00229         tv.tv_sec = 0;
00230         tv.tv_usec = 0;
00231         FD_ZERO(&rfds);
00232         FD_SET(ctrl->s, &rfds);
00233         res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
00234         return FD_ISSET(ctrl->s, &rfds);
00235 }
00236 
00237 
00238 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
00239 {
00240         return ctrl->s;
00241 }
00242 

Generated on Sat May 6 21:13:41 2006 for wpa_supplicant by  doxygen 1.4.2