$search
00001 /* 00002 * WPA Supplicant / privileged helper program 00003 * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 #ifdef __linux__ 00017 #include <fcntl.h> 00018 #endif /* __linux__ */ 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 /* TODO: add support for multiple l2 connections */ 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 /* When started from pcmcia-cs scripts, wpa_supplicant might start with 00930 * fd 0, 1, and 2 closed. This will cause some issues because many 00931 * places in wpa_supplicant are still printing out to stdout. As a 00932 * workaround, make sure that fd's 0, 1, and 2 are not used for other 00933 * sockets. */ 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 /* __linux__ */ 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 }