00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "includes.h"
00016 #ifdef __linux__
00017 #include <fcntl.h>
00018 #endif
00019 #include <sys/un.h>
00020 #include <sys/stat.h>
00021
00022 #include "common.h"
00023 #include "eloop.h"
00024 #include "common/version.h"
00025 #include "drivers/driver.h"
00026 #include "l2_packet/l2_packet.h"
00027 #include "common/privsep_commands.h"
00028 #include "common/ieee802_11_defs.h"
00029
00030
00031 struct wpa_priv_interface {
00032 struct wpa_priv_interface *next;
00033 char *driver_name;
00034 char *ifname;
00035 char *sock_name;
00036 int fd;
00037
00038 struct wpa_driver_ops *driver;
00039 void *drv_priv;
00040 struct sockaddr_un drv_addr;
00041 int wpas_registered;
00042
00043
00044 struct l2_packet_data *l2;
00045 struct sockaddr_un l2_addr;
00046 };
00047
00048
00049 static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
00050 struct sockaddr_un *from)
00051 {
00052 if (iface->drv_priv) {
00053 wpa_printf(MSG_DEBUG, "Cleaning up forgotten driver instance");
00054 if (iface->driver->deinit)
00055 iface->driver->deinit(iface->drv_priv);
00056 iface->drv_priv = NULL;
00057 iface->wpas_registered = 0;
00058 }
00059
00060 if (iface->l2) {
00061 wpa_printf(MSG_DEBUG, "Cleaning up forgotten l2_packet "
00062 "instance");
00063 l2_packet_deinit(iface->l2);
00064 iface->l2 = NULL;
00065 }
00066
00067 if (iface->driver->init == NULL)
00068 return;
00069
00070 iface->drv_priv = iface->driver->init(iface, iface->ifname);
00071 if (iface->drv_priv == NULL) {
00072 wpa_printf(MSG_DEBUG, "Failed to initialize driver wrapper");
00073 return;
00074 }
00075
00076 wpa_printf(MSG_DEBUG, "Driver wrapper '%s' initialized for interface "
00077 "'%s'", iface->driver_name, iface->ifname);
00078
00079 os_memcpy(&iface->drv_addr, from, sizeof(iface->drv_addr));
00080 iface->wpas_registered = 1;
00081
00082 if (iface->driver->set_param &&
00083 iface->driver->set_param(iface->drv_priv, NULL) < 0) {
00084 wpa_printf(MSG_ERROR, "Driver interface rejected param");
00085 }
00086 }
00087
00088
00089 static void wpa_priv_cmd_unregister(struct wpa_priv_interface *iface,
00090 struct sockaddr_un *from)
00091 {
00092 if (iface->drv_priv) {
00093 if (iface->driver->deinit)
00094 iface->driver->deinit(iface->drv_priv);
00095 iface->drv_priv = NULL;
00096 iface->wpas_registered = 0;
00097 }
00098 }
00099
00100
00101 static void wpa_priv_cmd_scan(struct wpa_priv_interface *iface,
00102 char *buf, size_t len)
00103 {
00104 struct wpa_driver_scan_params params;
00105
00106 if (iface->drv_priv == NULL)
00107 return;
00108
00109 os_memset(¶ms, 0, sizeof(params));
00110 if (len) {
00111 params.ssids[0].ssid = (u8 *) buf;
00112 params.ssids[0].ssid_len = len;
00113 params.num_ssids = 1;
00114 }
00115
00116 if (iface->driver->scan2)
00117 iface->driver->scan2(iface->drv_priv, ¶ms);
00118 }
00119
00120
00121 static void wpa_priv_get_scan_results2(struct wpa_priv_interface *iface,
00122 struct sockaddr_un *from)
00123 {
00124 struct wpa_scan_results *res;
00125 u8 *buf = NULL, *pos, *end;
00126 int val;
00127 size_t i;
00128
00129 res = iface->driver->get_scan_results2(iface->drv_priv);
00130 if (res == NULL)
00131 goto fail;
00132
00133 buf = os_malloc(60000);
00134 if (buf == NULL)
00135 goto fail;
00136 pos = buf;
00137 end = buf + 60000;
00138 val = res->num;
00139 os_memcpy(pos, &val, sizeof(int));
00140 pos += sizeof(int);
00141
00142 for (i = 0; i < res->num; i++) {
00143 struct wpa_scan_res *r = res->res[i];
00144 val = sizeof(*r) + r->ie_len;
00145 if (end - pos < (int) sizeof(int) + val)
00146 break;
00147 os_memcpy(pos, &val, sizeof(int));
00148 pos += sizeof(int);
00149 os_memcpy(pos, r, val);
00150 pos += val;
00151 }
00152
00153 sendto(iface->fd, buf, pos - buf, 0, (struct sockaddr *) from,
00154 sizeof(*from));
00155
00156 os_free(buf);
00157 wpa_scan_results_free(res);
00158 return;
00159
00160 fail:
00161 os_free(buf);
00162 wpa_scan_results_free(res);
00163 sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from));
00164 }
00165
00166
00167 static void wpa_priv_cmd_get_scan_results(struct wpa_priv_interface *iface,
00168 struct sockaddr_un *from)
00169 {
00170 if (iface->drv_priv == NULL)
00171 return;
00172
00173 if (iface->driver->get_scan_results2)
00174 wpa_priv_get_scan_results2(iface, from);
00175 else
00176 sendto(iface->fd, "", 0, 0, (struct sockaddr *) from,
00177 sizeof(*from));
00178 }
00179
00180
00181 static void wpa_priv_cmd_associate(struct wpa_priv_interface *iface,
00182 void *buf, size_t len)
00183 {
00184 struct wpa_driver_associate_params params;
00185 struct privsep_cmd_associate *assoc;
00186 u8 *bssid;
00187 int res;
00188
00189 if (iface->drv_priv == NULL || iface->driver->associate == NULL)
00190 return;
00191
00192 if (len < sizeof(*assoc)) {
00193 wpa_printf(MSG_DEBUG, "Invalid association request");
00194 return;
00195 }
00196
00197 assoc = buf;
00198 if (sizeof(*assoc) + assoc->wpa_ie_len > len) {
00199 wpa_printf(MSG_DEBUG, "Association request overflow");
00200 return;
00201 }
00202
00203 os_memset(¶ms, 0, sizeof(params));
00204 bssid = assoc->bssid;
00205 if (bssid[0] | bssid[1] | bssid[2] | bssid[3] | bssid[4] | bssid[5])
00206 params.bssid = bssid;
00207 params.ssid = assoc->ssid;
00208 if (assoc->ssid_len > 32)
00209 return;
00210 params.ssid_len = assoc->ssid_len;
00211 params.freq = assoc->freq;
00212 if (assoc->wpa_ie_len) {
00213 params.wpa_ie = (u8 *) (assoc + 1);
00214 params.wpa_ie_len = assoc->wpa_ie_len;
00215 }
00216 params.pairwise_suite = assoc->pairwise_suite;
00217 params.group_suite = assoc->group_suite;
00218 params.key_mgmt_suite = assoc->key_mgmt_suite;
00219 params.auth_alg = assoc->auth_alg;
00220 params.mode = assoc->mode;
00221
00222 res = iface->driver->associate(iface->drv_priv, ¶ms);
00223 wpa_printf(MSG_DEBUG, "drv->associate: res=%d", res);
00224 }
00225
00226
00227 static void wpa_priv_cmd_get_bssid(struct wpa_priv_interface *iface,
00228 struct sockaddr_un *from)
00229 {
00230 u8 bssid[ETH_ALEN];
00231
00232 if (iface->drv_priv == NULL)
00233 goto fail;
00234
00235 if (iface->driver->get_bssid == NULL ||
00236 iface->driver->get_bssid(iface->drv_priv, bssid) < 0)
00237 goto fail;
00238
00239 sendto(iface->fd, bssid, ETH_ALEN, 0, (struct sockaddr *) from,
00240 sizeof(*from));
00241 return;
00242
00243 fail:
00244 sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from));
00245 }
00246
00247
00248 static void wpa_priv_cmd_get_ssid(struct wpa_priv_interface *iface,
00249 struct sockaddr_un *from)
00250 {
00251 u8 ssid[sizeof(int) + 32];
00252 int res;
00253
00254 if (iface->drv_priv == NULL)
00255 goto fail;
00256
00257 if (iface->driver->get_ssid == NULL)
00258 goto fail;
00259
00260 res = iface->driver->get_ssid(iface->drv_priv, &ssid[sizeof(int)]);
00261 if (res < 0 || res > 32)
00262 goto fail;
00263 os_memcpy(ssid, &res, sizeof(int));
00264
00265 sendto(iface->fd, ssid, sizeof(ssid), 0, (struct sockaddr *) from,
00266 sizeof(*from));
00267 return;
00268
00269 fail:
00270 sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from));
00271 }
00272
00273
00274 static void wpa_priv_cmd_set_key(struct wpa_priv_interface *iface,
00275 void *buf, size_t len)
00276 {
00277 struct privsep_cmd_set_key *params;
00278 int res;
00279
00280 if (iface->drv_priv == NULL || iface->driver->set_key == NULL)
00281 return;
00282
00283 if (len != sizeof(*params)) {
00284 wpa_printf(MSG_DEBUG, "Invalid set_key request");
00285 return;
00286 }
00287
00288 params = buf;
00289
00290 res = iface->driver->set_key(iface->ifname, iface->drv_priv,
00291 params->alg,
00292 params->addr, params->key_idx,
00293 params->set_tx,
00294 params->seq_len ? params->seq : NULL,
00295 params->seq_len,
00296 params->key_len ? params->key : NULL,
00297 params->key_len);
00298 wpa_printf(MSG_DEBUG, "drv->set_key: res=%d", res);
00299 }
00300
00301
00302 static void wpa_priv_cmd_get_capa(struct wpa_priv_interface *iface,
00303 struct sockaddr_un *from)
00304 {
00305 struct wpa_driver_capa capa;
00306
00307 if (iface->drv_priv == NULL)
00308 goto fail;
00309
00310 if (iface->driver->get_capa == NULL ||
00311 iface->driver->get_capa(iface->drv_priv, &capa) < 0)
00312 goto fail;
00313
00314 sendto(iface->fd, &capa, sizeof(capa), 0, (struct sockaddr *) from,
00315 sizeof(*from));
00316 return;
00317
00318 fail:
00319 sendto(iface->fd, "", 0, 0, (struct sockaddr *) from, sizeof(*from));
00320 }
00321
00322
00323 static void wpa_priv_l2_rx(void *ctx, const u8 *src_addr, const u8 *buf,
00324 size_t len)
00325 {
00326 struct wpa_priv_interface *iface = ctx;
00327 struct msghdr msg;
00328 struct iovec io[2];
00329
00330 io[0].iov_base = (u8 *) src_addr;
00331 io[0].iov_len = ETH_ALEN;
00332 io[1].iov_base = (u8 *) buf;
00333 io[1].iov_len = len;
00334
00335 os_memset(&msg, 0, sizeof(msg));
00336 msg.msg_iov = io;
00337 msg.msg_iovlen = 2;
00338 msg.msg_name = &iface->l2_addr;
00339 msg.msg_namelen = sizeof(iface->l2_addr);
00340
00341 if (sendmsg(iface->fd, &msg, 0) < 0) {
00342 perror("sendmsg(l2 rx)");
00343 }
00344 }
00345
00346
00347 static void wpa_priv_cmd_l2_register(struct wpa_priv_interface *iface,
00348 struct sockaddr_un *from,
00349 void *buf, size_t len)
00350 {
00351 int *reg_cmd = buf;
00352 u8 own_addr[ETH_ALEN];
00353 int res;
00354 u16 proto;
00355
00356 if (len != 2 * sizeof(int)) {
00357 wpa_printf(MSG_DEBUG, "Invalid l2_register length %lu",
00358 (unsigned long) len);
00359 return;
00360 }
00361
00362 proto = reg_cmd[0];
00363 if (proto != ETH_P_EAPOL && proto != ETH_P_RSN_PREAUTH) {
00364 wpa_printf(MSG_DEBUG, "Refused l2_packet connection for "
00365 "ethertype 0x%x", proto);
00366 return;
00367 }
00368
00369 if (iface->l2) {
00370 wpa_printf(MSG_DEBUG, "Cleaning up forgotten l2_packet "
00371 "instance");
00372 l2_packet_deinit(iface->l2);
00373 iface->l2 = NULL;
00374 }
00375
00376 os_memcpy(&iface->l2_addr, from, sizeof(iface->l2_addr));
00377
00378 iface->l2 = l2_packet_init(iface->ifname, NULL, proto,
00379 wpa_priv_l2_rx, iface, reg_cmd[1]);
00380 if (iface->l2 == NULL) {
00381 wpa_printf(MSG_DEBUG, "Failed to initialize l2_packet "
00382 "instance for protocol %d", proto);
00383 return;
00384 }
00385
00386 if (l2_packet_get_own_addr(iface->l2, own_addr) < 0) {
00387 wpa_printf(MSG_DEBUG, "Failed to get own address from "
00388 "l2_packet");
00389 l2_packet_deinit(iface->l2);
00390 iface->l2 = NULL;
00391 return;
00392 }
00393
00394 res = sendto(iface->fd, own_addr, ETH_ALEN, 0,
00395 (struct sockaddr *) from, sizeof(*from));
00396 wpa_printf(MSG_DEBUG, "L2 registration: res=%d", res);
00397 }
00398
00399
00400 static void wpa_priv_cmd_l2_unregister(struct wpa_priv_interface *iface,
00401 struct sockaddr_un *from)
00402 {
00403 if (iface->l2) {
00404 l2_packet_deinit(iface->l2);
00405 iface->l2 = NULL;
00406 }
00407 }
00408
00409
00410 static void wpa_priv_cmd_l2_notify_auth_start(struct wpa_priv_interface *iface,
00411 struct sockaddr_un *from)
00412 {
00413 if (iface->l2)
00414 l2_packet_notify_auth_start(iface->l2);
00415 }
00416
00417
00418 static void wpa_priv_cmd_l2_send(struct wpa_priv_interface *iface,
00419 struct sockaddr_un *from,
00420 void *buf, size_t len)
00421 {
00422 u8 *dst_addr;
00423 u16 proto;
00424 int res;
00425
00426 if (iface->l2 == NULL)
00427 return;
00428
00429 if (len < ETH_ALEN + 2) {
00430 wpa_printf(MSG_DEBUG, "Too short L2 send packet (len=%lu)",
00431 (unsigned long) len);
00432 return;
00433 }
00434
00435 dst_addr = buf;
00436 os_memcpy(&proto, buf + ETH_ALEN, 2);
00437
00438 if (proto != ETH_P_EAPOL && proto != ETH_P_RSN_PREAUTH) {
00439 wpa_printf(MSG_DEBUG, "Refused l2_packet send for ethertype "
00440 "0x%x", proto);
00441 return;
00442 }
00443
00444 res = l2_packet_send(iface->l2, dst_addr, proto, buf + ETH_ALEN + 2,
00445 len - ETH_ALEN - 2);
00446 wpa_printf(MSG_DEBUG, "L2 send: res=%d", res);
00447 }
00448
00449
00450 static void wpa_priv_cmd_set_country(struct wpa_priv_interface *iface,
00451 char *buf)
00452 {
00453 if (iface->drv_priv == NULL || iface->driver->set_country == NULL ||
00454 *buf == '\0')
00455 return;
00456
00457 iface->driver->set_country(iface->drv_priv, buf);
00458 }
00459
00460
00461 static void wpa_priv_receive(int sock, void *eloop_ctx, void *sock_ctx)
00462 {
00463 struct wpa_priv_interface *iface = eloop_ctx;
00464 char buf[2000], *pos;
00465 void *cmd_buf;
00466 size_t cmd_len;
00467 int res, cmd;
00468 struct sockaddr_un from;
00469 socklen_t fromlen = sizeof(from);
00470
00471 res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &from,
00472 &fromlen);
00473 if (res < 0) {
00474 perror("recvfrom");
00475 return;
00476 }
00477
00478 if (res < (int) sizeof(int)) {
00479 wpa_printf(MSG_DEBUG, "Too short command (len=%d)", res);
00480 return;
00481 }
00482
00483 os_memcpy(&cmd, buf, sizeof(int));
00484 wpa_printf(MSG_DEBUG, "Command %d for interface %s",
00485 cmd, iface->ifname);
00486 cmd_buf = &buf[sizeof(int)];
00487 cmd_len = res - sizeof(int);
00488
00489 switch (cmd) {
00490 case PRIVSEP_CMD_REGISTER:
00491 wpa_priv_cmd_register(iface, &from);
00492 break;
00493 case PRIVSEP_CMD_UNREGISTER:
00494 wpa_priv_cmd_unregister(iface, &from);
00495 break;
00496 case PRIVSEP_CMD_SCAN:
00497 wpa_priv_cmd_scan(iface, cmd_buf, cmd_len);
00498 break;
00499 case PRIVSEP_CMD_GET_SCAN_RESULTS:
00500 wpa_priv_cmd_get_scan_results(iface, &from);
00501 break;
00502 case PRIVSEP_CMD_ASSOCIATE:
00503 wpa_priv_cmd_associate(iface, cmd_buf, cmd_len);
00504 break;
00505 case PRIVSEP_CMD_GET_BSSID:
00506 wpa_priv_cmd_get_bssid(iface, &from);
00507 break;
00508 case PRIVSEP_CMD_GET_SSID:
00509 wpa_priv_cmd_get_ssid(iface, &from);
00510 break;
00511 case PRIVSEP_CMD_SET_KEY:
00512 wpa_priv_cmd_set_key(iface, cmd_buf, cmd_len);
00513 break;
00514 case PRIVSEP_CMD_GET_CAPA:
00515 wpa_priv_cmd_get_capa(iface, &from);
00516 break;
00517 case PRIVSEP_CMD_L2_REGISTER:
00518 wpa_priv_cmd_l2_register(iface, &from, cmd_buf, cmd_len);
00519 break;
00520 case PRIVSEP_CMD_L2_UNREGISTER:
00521 wpa_priv_cmd_l2_unregister(iface, &from);
00522 break;
00523 case PRIVSEP_CMD_L2_NOTIFY_AUTH_START:
00524 wpa_priv_cmd_l2_notify_auth_start(iface, &from);
00525 break;
00526 case PRIVSEP_CMD_L2_SEND:
00527 wpa_priv_cmd_l2_send(iface, &from, cmd_buf, cmd_len);
00528 break;
00529 case PRIVSEP_CMD_SET_COUNTRY:
00530 pos = cmd_buf;
00531 if (pos + cmd_len >= buf + sizeof(buf))
00532 break;
00533 pos[cmd_len] = '\0';
00534 wpa_priv_cmd_set_country(iface, pos);
00535 break;
00536 }
00537 }
00538
00539
00540 static void wpa_priv_interface_deinit(struct wpa_priv_interface *iface)
00541 {
00542 if (iface->drv_priv && iface->driver->deinit)
00543 iface->driver->deinit(iface->drv_priv);
00544
00545 if (iface->fd >= 0) {
00546 eloop_unregister_read_sock(iface->fd);
00547 close(iface->fd);
00548 unlink(iface->sock_name);
00549 }
00550
00551 if (iface->l2)
00552 l2_packet_deinit(iface->l2);
00553
00554 os_free(iface->ifname);
00555 os_free(iface->driver_name);
00556 os_free(iface->sock_name);
00557 os_free(iface);
00558 }
00559
00560
00561 extern struct wpa_driver_ops *wpa_drivers[];
00562
00563 static struct wpa_priv_interface *
00564 wpa_priv_interface_init(const char *dir, const char *params)
00565 {
00566 struct wpa_priv_interface *iface;
00567 char *pos;
00568 size_t len;
00569 struct sockaddr_un addr;
00570 int i;
00571
00572 pos = os_strchr(params, ':');
00573 if (pos == NULL)
00574 return NULL;
00575
00576 iface = os_zalloc(sizeof(*iface));
00577 if (iface == NULL)
00578 return NULL;
00579 iface->fd = -1;
00580
00581 len = pos - params;
00582 iface->driver_name = os_malloc(len + 1);
00583 if (iface->driver_name == NULL) {
00584 wpa_priv_interface_deinit(iface);
00585 return NULL;
00586 }
00587 os_memcpy(iface->driver_name, params, len);
00588 iface->driver_name[len] = '\0';
00589
00590 for (i = 0; wpa_drivers[i]; i++) {
00591 if (os_strcmp(iface->driver_name,
00592 wpa_drivers[i]->name) == 0) {
00593 iface->driver = wpa_drivers[i];
00594 break;
00595 }
00596 }
00597 if (iface->driver == NULL) {
00598 wpa_printf(MSG_ERROR, "Unsupported driver '%s'",
00599 iface->driver_name);
00600 wpa_priv_interface_deinit(iface);
00601 return NULL;
00602 }
00603
00604 pos++;
00605 iface->ifname = os_strdup(pos);
00606 if (iface->ifname == NULL) {
00607 wpa_priv_interface_deinit(iface);
00608 return NULL;
00609 }
00610
00611 len = os_strlen(dir) + 1 + os_strlen(iface->ifname);
00612 iface->sock_name = os_malloc(len + 1);
00613 if (iface->sock_name == NULL) {
00614 wpa_priv_interface_deinit(iface);
00615 return NULL;
00616 }
00617
00618 os_snprintf(iface->sock_name, len + 1, "%s/%s", dir, iface->ifname);
00619 if (os_strlen(iface->sock_name) >= sizeof(addr.sun_path)) {
00620 wpa_priv_interface_deinit(iface);
00621 return NULL;
00622 }
00623
00624 iface->fd = socket(PF_UNIX, SOCK_DGRAM, 0);
00625 if (iface->fd < 0) {
00626 perror("socket(PF_UNIX)");
00627 wpa_priv_interface_deinit(iface);
00628 return NULL;
00629 }
00630
00631 os_memset(&addr, 0, sizeof(addr));
00632 addr.sun_family = AF_UNIX;
00633 os_strlcpy(addr.sun_path, iface->sock_name, sizeof(addr.sun_path));
00634
00635 if (bind(iface->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00636 wpa_printf(MSG_DEBUG, "bind(PF_UNIX) failed: %s",
00637 strerror(errno));
00638 if (connect(iface->fd, (struct sockaddr *) &addr,
00639 sizeof(addr)) < 0) {
00640 wpa_printf(MSG_DEBUG, "Socket exists, but does not "
00641 "allow connections - assuming it was "
00642 "leftover from forced program termination");
00643 if (unlink(iface->sock_name) < 0) {
00644 perror("unlink[ctrl_iface]");
00645 wpa_printf(MSG_ERROR, "Could not unlink "
00646 "existing ctrl_iface socket '%s'",
00647 iface->sock_name);
00648 goto fail;
00649 }
00650 if (bind(iface->fd, (struct sockaddr *) &addr,
00651 sizeof(addr)) < 0) {
00652 perror("bind(PF_UNIX)");
00653 goto fail;
00654 }
00655 wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
00656 "socket '%s'", iface->sock_name);
00657 } else {
00658 wpa_printf(MSG_INFO, "Socket exists and seems to be "
00659 "in use - cannot override it");
00660 wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
00661 "not used anymore", iface->sock_name);
00662 goto fail;
00663 }
00664 }
00665
00666 if (chmod(iface->sock_name, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
00667 perror("chmod");
00668 goto fail;
00669 }
00670
00671 eloop_register_read_sock(iface->fd, wpa_priv_receive, iface, NULL);
00672
00673 return iface;
00674
00675 fail:
00676 wpa_priv_interface_deinit(iface);
00677 return NULL;
00678 }
00679
00680
00681 static int wpa_priv_send_event(struct wpa_priv_interface *iface, int event,
00682 const void *data, size_t data_len)
00683 {
00684 struct msghdr msg;
00685 struct iovec io[2];
00686
00687 io[0].iov_base = &event;
00688 io[0].iov_len = sizeof(event);
00689 io[1].iov_base = (u8 *) data;
00690 io[1].iov_len = data_len;
00691
00692 os_memset(&msg, 0, sizeof(msg));
00693 msg.msg_iov = io;
00694 msg.msg_iovlen = data ? 2 : 1;
00695 msg.msg_name = &iface->drv_addr;
00696 msg.msg_namelen = sizeof(iface->drv_addr);
00697
00698 if (sendmsg(iface->fd, &msg, 0) < 0) {
00699 perror("sendmsg(wpas_socket)");
00700 return -1;
00701 }
00702
00703 return 0;
00704 }
00705
00706
00707 static void wpa_priv_send_assoc(struct wpa_priv_interface *iface, int event,
00708 union wpa_event_data *data)
00709 {
00710 size_t buflen = 3 * sizeof(int);
00711 u8 *buf, *pos;
00712 int len;
00713
00714 if (data) {
00715 buflen += data->assoc_info.req_ies_len +
00716 data->assoc_info.resp_ies_len +
00717 data->assoc_info.beacon_ies_len;
00718 }
00719
00720 buf = os_malloc(buflen);
00721 if (buf == NULL)
00722 return;
00723
00724 pos = buf;
00725
00726 if (data && data->assoc_info.req_ies) {
00727 len = data->assoc_info.req_ies_len;
00728 os_memcpy(pos, &len, sizeof(int));
00729 pos += sizeof(int);
00730 os_memcpy(pos, data->assoc_info.req_ies, len);
00731 pos += len;
00732 } else {
00733 len = 0;
00734 os_memcpy(pos, &len, sizeof(int));
00735 pos += sizeof(int);
00736 }
00737
00738 if (data && data->assoc_info.resp_ies) {
00739 len = data->assoc_info.resp_ies_len;
00740 os_memcpy(pos, &len, sizeof(int));
00741 pos += sizeof(int);
00742 os_memcpy(pos, data->assoc_info.resp_ies, len);
00743 pos += len;
00744 } else {
00745 len = 0;
00746 os_memcpy(pos, &len, sizeof(int));
00747 pos += sizeof(int);
00748 }
00749
00750 if (data && data->assoc_info.beacon_ies) {
00751 len = data->assoc_info.beacon_ies_len;
00752 os_memcpy(pos, &len, sizeof(int));
00753 pos += sizeof(int);
00754 os_memcpy(pos, data->assoc_info.beacon_ies, len);
00755 pos += len;
00756 } else {
00757 len = 0;
00758 os_memcpy(pos, &len, sizeof(int));
00759 pos += sizeof(int);
00760 }
00761
00762 wpa_priv_send_event(iface, event, buf, buflen);
00763
00764 os_free(buf);
00765 }
00766
00767
00768 static void wpa_priv_send_interface_status(struct wpa_priv_interface *iface,
00769 union wpa_event_data *data)
00770 {
00771 int ievent;
00772 size_t len, maxlen;
00773 u8 *buf;
00774 char *ifname;
00775
00776 if (data == NULL)
00777 return;
00778
00779 ievent = data->interface_status.ievent;
00780 maxlen = sizeof(data->interface_status.ifname);
00781 ifname = data->interface_status.ifname;
00782 for (len = 0; len < maxlen && ifname[len]; len++)
00783 ;
00784
00785 buf = os_malloc(sizeof(int) + len);
00786 if (buf == NULL)
00787 return;
00788
00789 os_memcpy(buf, &ievent, sizeof(int));
00790 os_memcpy(buf + sizeof(int), ifname, len);
00791
00792 wpa_priv_send_event(iface, PRIVSEP_EVENT_INTERFACE_STATUS,
00793 buf, sizeof(int) + len);
00794
00795 os_free(buf);
00796
00797 }
00798
00799
00800 static void wpa_priv_send_ft_response(struct wpa_priv_interface *iface,
00801 union wpa_event_data *data)
00802 {
00803 size_t len;
00804 u8 *buf, *pos;
00805
00806 if (data == NULL || data->ft_ies.ies == NULL)
00807 return;
00808
00809 len = sizeof(int) + ETH_ALEN + data->ft_ies.ies_len;
00810 buf = os_malloc(len);
00811 if (buf == NULL)
00812 return;
00813
00814 pos = buf;
00815 os_memcpy(pos, &data->ft_ies.ft_action, sizeof(int));
00816 pos += sizeof(int);
00817 os_memcpy(pos, data->ft_ies.target_ap, ETH_ALEN);
00818 pos += ETH_ALEN;
00819 os_memcpy(pos, data->ft_ies.ies, data->ft_ies.ies_len);
00820
00821 wpa_priv_send_event(iface, PRIVSEP_EVENT_FT_RESPONSE, buf, len);
00822
00823 os_free(buf);
00824
00825 }
00826
00827
00828 void wpa_supplicant_event(void *ctx, wpa_event_type event,
00829 union wpa_event_data *data)
00830 {
00831 struct wpa_priv_interface *iface = ctx;
00832
00833 wpa_printf(MSG_DEBUG, "%s - event=%d", __func__, event);
00834
00835 if (!iface->wpas_registered) {
00836 wpa_printf(MSG_DEBUG, "Driver event received, but "
00837 "wpa_supplicant not registered");
00838 return;
00839 }
00840
00841 switch (event) {
00842 case EVENT_ASSOC:
00843 wpa_priv_send_assoc(iface, PRIVSEP_EVENT_ASSOC, data);
00844 break;
00845 case EVENT_DISASSOC:
00846 wpa_priv_send_event(iface, PRIVSEP_EVENT_DISASSOC, NULL, 0);
00847 break;
00848 case EVENT_ASSOCINFO:
00849 if (data == NULL)
00850 return;
00851 wpa_priv_send_assoc(iface, PRIVSEP_EVENT_ASSOCINFO, data);
00852 break;
00853 case EVENT_MICHAEL_MIC_FAILURE:
00854 if (data == NULL)
00855 return;
00856 wpa_priv_send_event(iface, PRIVSEP_EVENT_MICHAEL_MIC_FAILURE,
00857 &data->michael_mic_failure.unicast,
00858 sizeof(int));
00859 break;
00860 case EVENT_SCAN_RESULTS:
00861 wpa_priv_send_event(iface, PRIVSEP_EVENT_SCAN_RESULTS, NULL,
00862 0);
00863 break;
00864 case EVENT_INTERFACE_STATUS:
00865 wpa_priv_send_interface_status(iface, data);
00866 break;
00867 case EVENT_PMKID_CANDIDATE:
00868 if (data == NULL)
00869 return;
00870 wpa_priv_send_event(iface, PRIVSEP_EVENT_PMKID_CANDIDATE,
00871 &data->pmkid_candidate,
00872 sizeof(struct pmkid_candidate));
00873 break;
00874 case EVENT_STKSTART:
00875 if (data == NULL)
00876 return;
00877 wpa_priv_send_event(iface, PRIVSEP_EVENT_STKSTART,
00878 &data->stkstart.peer, ETH_ALEN);
00879 break;
00880 case EVENT_FT_RESPONSE:
00881 wpa_priv_send_ft_response(iface, data);
00882 break;
00883 default:
00884 wpa_printf(MSG_DEBUG, "Unsupported driver event %d - TODO",
00885 event);
00886 break;
00887 }
00888 }
00889
00890
00891 void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
00892 const u8 *buf, size_t len)
00893 {
00894 struct wpa_priv_interface *iface = ctx;
00895 struct msghdr msg;
00896 struct iovec io[3];
00897 int event = PRIVSEP_EVENT_RX_EAPOL;
00898
00899 wpa_printf(MSG_DEBUG, "RX EAPOL from driver");
00900 io[0].iov_base = &event;
00901 io[0].iov_len = sizeof(event);
00902 io[1].iov_base = (u8 *) src_addr;
00903 io[1].iov_len = ETH_ALEN;
00904 io[2].iov_base = (u8 *) buf;
00905 io[2].iov_len = len;
00906
00907 os_memset(&msg, 0, sizeof(msg));
00908 msg.msg_iov = io;
00909 msg.msg_iovlen = 3;
00910 msg.msg_name = &iface->drv_addr;
00911 msg.msg_namelen = sizeof(iface->drv_addr);
00912
00913 if (sendmsg(iface->fd, &msg, 0) < 0)
00914 perror("sendmsg(wpas_socket)");
00915 }
00916
00917
00918 static void wpa_priv_terminate(int sig, void *eloop_ctx, void *signal_ctx)
00919 {
00920 wpa_printf(MSG_DEBUG, "wpa_priv termination requested");
00921 eloop_terminate();
00922 }
00923
00924
00925 static void wpa_priv_fd_workaround(void)
00926 {
00927 #ifdef __linux__
00928 int s, i;
00929
00930
00931
00932
00933
00934 for (i = 0; i < 3; i++) {
00935 s = open("/dev/null", O_RDWR);
00936 if (s > 2) {
00937 close(s);
00938 break;
00939 }
00940 }
00941 #endif
00942 }
00943
00944
00945 static void usage(void)
00946 {
00947 printf("wpa_priv v" VERSION_STR "\n"
00948 "Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi> and "
00949 "contributors\n"
00950 "\n"
00951 "usage:\n"
00952 " wpa_priv [-Bdd] [-P<pid file>] <driver:ifname> "
00953 "[driver:ifname ...]\n");
00954 }
00955
00956
00957 extern int wpa_debug_level;
00958
00959 int main(int argc, char *argv[])
00960 {
00961 int c, i;
00962 int ret = -1;
00963 char *pid_file = NULL;
00964 int daemonize = 0;
00965 char *ctrl_dir = "/var/run/wpa_priv";
00966 struct wpa_priv_interface *interfaces = NULL, *iface;
00967
00968 if (os_program_init())
00969 return -1;
00970
00971 wpa_priv_fd_workaround();
00972
00973 for (;;) {
00974 c = getopt(argc, argv, "Bc:dP:");
00975 if (c < 0)
00976 break;
00977 switch (c) {
00978 case 'B':
00979 daemonize++;
00980 break;
00981 case 'c':
00982 ctrl_dir = optarg;
00983 break;
00984 case 'd':
00985 wpa_debug_level--;
00986 break;
00987 case 'P':
00988 pid_file = os_rel2abs_path(optarg);
00989 break;
00990 default:
00991 usage();
00992 goto out;
00993 }
00994 }
00995
00996 if (optind >= argc) {
00997 usage();
00998 goto out;
00999 }
01000
01001 wpa_printf(MSG_DEBUG, "wpa_priv control directory: '%s'", ctrl_dir);
01002
01003 if (eloop_init()) {
01004 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
01005 goto out;
01006 }
01007
01008 for (i = optind; i < argc; i++) {
01009 wpa_printf(MSG_DEBUG, "Adding driver:interface %s", argv[i]);
01010 iface = wpa_priv_interface_init(ctrl_dir, argv[i]);
01011 if (iface == NULL)
01012 goto out;
01013 iface->next = interfaces;
01014 interfaces = iface;
01015 }
01016
01017 if (daemonize && os_daemonize(pid_file))
01018 goto out;
01019
01020 eloop_register_signal_terminate(wpa_priv_terminate, NULL);
01021 eloop_run();
01022
01023 ret = 0;
01024
01025 out:
01026 iface = interfaces;
01027 while (iface) {
01028 struct wpa_priv_interface *prev = iface;
01029 iface = iface->next;
01030 wpa_priv_interface_deinit(prev);
01031 }
01032
01033 eloop_destroy();
01034
01035 os_daemonize_terminate(pid_file);
01036 os_free(pid_file);
01037 os_program_deinit();
01038
01039 return ret;
01040 }