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
00027
00028 #include "wpa_ctrl.h"
00029 #ifdef CONFIG_NATIVE_WINDOWS
00030 #include "common.h"
00031 #endif
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
00050 struct sockaddr_un local;
00051 struct sockaddr_un dest;
00052 #endif
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
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
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
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
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
00161
00162
00163
00164 if (msg_cb) {
00165
00166
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