1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdint.h> 18 #include <fcntl.h> 19 #include <sys/socket.h> 20 #include <netlink/genl/genl.h> 21 #include <netlink/genl/family.h> 22 #include <netlink/genl/ctrl.h> 23 #include <linux/rtnetlink.h> 24 #include <netpacket/packet.h> 25 #include <linux/filter.h> 26 #include <linux/errqueue.h> 27 28 #include <linux/pkt_sched.h> 29 #include <netlink/object-api.h> 30 #include <netlink/netlink.h> 31 #include <netlink/socket.h> 32 #include <netlink-types.h> 33 34 #include "nl80211_copy.h" 35 36 #include <dirent.h> 37 #include <net/if.h> 38 39 #include "sync.h" 40 41 #define LOG_TAG "WifiHAL" 42 43 #include <utils/Log.h> 44 45 #include "wifi_hal.h" 46 #include "common.h" 47 #include "cpp_bindings.h" 48 49 /* 50 BUGBUG: normally, libnl allocates ports for all connections it makes; but 51 being a static library, it doesn't really know how many other netlink connections 52 are made by the same process, if connections come from different shared libraries. 53 These port assignments exist to solve that problem - temporarily. We need to fix 54 libnl to try and allocate ports across the entire process. 55 */ 56 57 #define WIFI_HAL_CMD_SOCK_PORT 644 58 #define WIFI_HAL_EVENT_SOCK_PORT 645 59 60 static void internal_event_handler(wifi_handle handle, int events); 61 static int internal_valid_message_handler(nl_msg *msg, void *arg); 62 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group); 63 static int wifi_add_membership(wifi_handle handle, const char *group); 64 static wifi_error wifi_init_interfaces(wifi_handle handle); 65 66 /* Initialize/Cleanup */ 67 68 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port) 69 { 70 uint32_t pid = getpid() & 0x3FFFFF; 71 72 if (port == 0) { 73 sock->s_flags &= ~NL_OWN_PORT; 74 } else { 75 sock->s_flags |= NL_OWN_PORT; 76 } 77 78 sock->s_local.nl_pid = pid + (port << 22); 79 } 80 81 static nl_sock * wifi_create_nl_socket(int port) 82 { 83 // ALOGI("Creating socket"); 84 struct nl_sock *sock = nl_socket_alloc(); 85 if (sock == NULL) { 86 ALOGE("Could not create handle"); 87 return NULL; 88 } 89 90 wifi_socket_set_local_port(sock, port); 91 92 struct sockaddr_nl *addr_nl = &(sock->s_local); 93 /* ALOGI("socket address is %d:%d:%d:%d", 94 addr_nl->nl_family, addr_nl->nl_pad, addr_nl->nl_pid, addr_nl->nl_groups); */ 95 96 struct sockaddr *addr = NULL; 97 // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl)); 98 99 // ALOGI("Connecting socket"); 100 if (nl_connect(sock, NETLINK_GENERIC)) { 101 ALOGE("Could not connect handle"); 102 nl_socket_free(sock); 103 return NULL; 104 } 105 106 ALOGI("Socket Value:%p", sock); 107 return sock; 108 } 109 110 int ack_handler(struct nl_msg *msg, void *arg) 111 { 112 int *err = (int *)arg; 113 *err = 0; 114 ALOGD("%s invoked",__func__); 115 return NL_STOP; 116 } 117 118 int finish_handler(struct nl_msg *msg, void *arg) 119 { 120 int *ret = (int *)arg; 121 *ret = 0; 122 ALOGD("%s called",__func__); 123 return NL_SKIP; 124 } 125 126 int error_handler(struct sockaddr_nl *nla, 127 struct nlmsgerr *err, void *arg) 128 { 129 int *ret = (int *)arg; 130 *ret = err->error; 131 132 ALOGD("%s invoked with error: %d", __func__, err->error); 133 return NL_SKIP; 134 } 135 static int no_seq_check(struct nl_msg *msg, void *arg) 136 { 137 ALOGD("no_seq_check received"); 138 return NL_OK; 139 } 140 141 wifi_error wifi_initialize(wifi_handle *handle) 142 { 143 int err = 0; 144 srand(getpid()); 145 146 ALOGI("Initializing wifi"); 147 hal_info *info = (hal_info *)malloc(sizeof(hal_info)); 148 if (info == NULL) { 149 ALOGE("Could not allocate hal_info"); 150 return WIFI_ERROR_UNKNOWN; 151 } 152 153 memset(info, 0, sizeof(*info)); 154 155 ALOGI("Creating socket"); 156 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT); 157 if (cmd_sock == NULL) { 158 ALOGE("Could not create handle"); 159 return WIFI_ERROR_UNKNOWN; 160 } 161 162 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT); 163 if (event_sock == NULL) { 164 ALOGE("Could not create handle"); 165 nl_socket_free(cmd_sock); 166 return WIFI_ERROR_UNKNOWN; 167 } 168 169 struct nl_cb *cb = nl_socket_get_cb(event_sock); 170 if (cb == NULL) { 171 ALOGE("Could not create handle"); 172 return WIFI_ERROR_UNKNOWN; 173 } 174 175 err = 1; 176 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); 177 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); 178 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); 179 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); 180 181 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info); 182 nl_cb_put(cb); 183 184 info->cmd_sock = cmd_sock; 185 info->event_sock = event_sock; 186 info->clean_up = false; 187 info->in_event_loop = false; 188 189 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE); 190 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE; 191 info->num_event_cb = 0; 192 193 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE); 194 info->alloc_cmd = DEFAULT_CMD_SIZE; 195 info->num_cmd = 0; 196 197 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211"); 198 if (info->nl80211_family_id < 0) { 199 ALOGE("Could not resolve nl80211 familty id"); 200 nl_socket_free(cmd_sock); 201 nl_socket_free(event_sock); 202 free(info); 203 return WIFI_ERROR_UNKNOWN; 204 } 205 ALOGI("%s: family_id:%d", __func__, info->nl80211_family_id); 206 207 *handle = (wifi_handle) info; 208 209 wifi_add_membership(*handle, "scan"); 210 wifi_add_membership(*handle, "mlme"); 211 wifi_add_membership(*handle, "regulatory"); 212 wifi_add_membership(*handle, "vendor"); 213 214 wifi_init_interfaces(*handle); 215 // ALOGI("Found %d interfaces", info->num_interfaces); 216 217 ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d handle %p", NL80211_CMD_VENDOR , 218 *handle); 219 return WIFI_SUCCESS; 220 } 221 222 static int wifi_add_membership(wifi_handle handle, const char *group) 223 { 224 hal_info *info = getHalInfo(handle); 225 226 int id = wifi_get_multicast_id(handle, "nl80211", group); 227 if (id < 0) { 228 ALOGE("Could not find group %s", group); 229 return id; 230 } 231 232 int ret = nl_socket_add_membership(info->event_sock, id); 233 if (ret < 0) { 234 ALOGE("Could not add membership to group %s", group); 235 } 236 237 // ALOGI("Successfully added membership for group %s", group); 238 return ret; 239 } 240 241 static void internal_cleaned_up_handler(wifi_handle handle) 242 { 243 hal_info *info = getHalInfo(handle); 244 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler; 245 246 if (info->cmd_sock != 0) { 247 nl_socket_free(info->cmd_sock); 248 nl_socket_free(info->event_sock); 249 info->cmd_sock = NULL; 250 info->event_sock = NULL; 251 } 252 253 (*cleaned_up_handler)(handle); 254 free(info); 255 256 ALOGI("Internal cleanup completed"); 257 } 258 259 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler) 260 { 261 hal_info *info = getHalInfo(handle); 262 info->cleaned_up_handler = handler; 263 info->clean_up = true; 264 265 ALOGI("Wifi cleanup completed"); 266 } 267 268 static int internal_pollin_handler(wifi_handle handle) 269 { 270 hal_info *info = getHalInfo(handle); 271 struct nl_cb *cb = nl_socket_get_cb(info->event_sock); 272 int res = nl_recvmsgs(info->event_sock, cb); 273 nl_cb_put(cb); 274 return res; 275 } 276 277 static void internal_event_handler(wifi_handle handle, int events) 278 { 279 if (events & POLLERR) { 280 ALOGE("Error reading from socket"); 281 } else if (events & POLLHUP) { 282 ALOGE("Remote side hung up"); 283 } else if (events & POLLIN) { 284 ALOGI("Found some events!!!"); 285 internal_pollin_handler(handle); 286 } else { 287 ALOGE("Unknown event - %0x", events); 288 } 289 } 290 291 /* Run event handler */ 292 void wifi_event_loop(wifi_handle handle) 293 { 294 hal_info *info = getHalInfo(handle); 295 if (info->in_event_loop) { 296 return; 297 } else { 298 info->in_event_loop = true; 299 } 300 301 pollfd pfd; 302 memset(&pfd, 0, sizeof(pfd)); 303 304 pfd.fd = nl_socket_get_fd(info->event_sock); 305 pfd.events = POLLIN; 306 307 /* TODO: Add support for timeouts */ 308 309 do { 310 int timeout = -1; /* Infinite timeout */ 311 pfd.revents = 0; 312 //ALOGI("Polling socket"); 313 int result = poll(&pfd, 1, -1); 314 ALOGI("Poll result = %0x", result); 315 if (result < 0) { 316 ALOGE("Error polling socket"); 317 } else if (pfd.revents & (POLLIN | POLLHUP | POLLERR)) { 318 internal_event_handler(handle, pfd.revents); 319 } 320 } while (!info->clean_up); 321 322 323 ALOGI("Cleaning up"); 324 internal_cleaned_up_handler(handle); 325 } 326 327 /////////////////////////////////////////////////////////////////////////////////////// 328 329 static int internal_valid_message_handler(nl_msg *msg, void *arg) 330 { 331 wifi_handle handle = (wifi_handle)arg; 332 hal_info *info = getHalInfo(handle); 333 334 WifiEvent event(msg); 335 int res = event.parse(); 336 if (res < 0) { 337 ALOGE("Failed to parse event: %d", res); 338 return NL_SKIP; 339 } 340 341 int cmd = event.get_cmd(); 342 uint32_t vendor_id = 0; 343 int subcmd = 0; 344 345 if (cmd == NL80211_CMD_VENDOR) { 346 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID); 347 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD); 348 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x", 349 event.get_cmdString(), vendor_id, subcmd); 350 } else { 351 ALOGI("event received %s", event.get_cmdString()); 352 } 353 354 ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id); 355 // event.log(); 356 357 bool dispatched = false; 358 for (int i = 0; i < info->num_event_cb; i++) { 359 if (cmd == info->event_cb[i].nl_cmd) { 360 if (cmd == NL80211_CMD_VENDOR 361 && ((vendor_id != info->event_cb[i].vendor_id) 362 || (subcmd != info->event_cb[i].vendor_subcmd))) 363 { 364 /* event for a different vendor, ignore it */ 365 continue; 366 } 367 368 cb_info *cbi = &(info->event_cb[i]); 369 (*(cbi->cb_func))(msg, cbi->cb_arg); 370 dispatched = true; 371 } 372 } 373 374 if (!dispatched) { 375 ALOGI("event ignored!!"); 376 } 377 378 return NL_OK; 379 } 380 381 /////////////////////////////////////////////////////////////////////////////////////// 382 383 class GetMulticastIdCommand : public WifiCommand 384 { 385 private: 386 const char *mName; 387 const char *mGroup; 388 int mId; 389 public: 390 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group) 391 : WifiCommand(handle, 0) 392 { 393 mName = name; 394 mGroup = group; 395 mId = -1; 396 } 397 398 int getId() { 399 return mId; 400 } 401 402 virtual int create() { 403 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl"); 404 // ALOGI("ctrl family = %d", nlctrlFamily); 405 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0); 406 if (ret < 0) { 407 return ret; 408 } 409 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName); 410 return ret; 411 } 412 413 virtual int handleResponse(WifiEvent& reply) { 414 415 // ALOGI("handling reponse in %s", __func__); 416 417 struct nlattr **tb = reply.attributes(); 418 struct genlmsghdr *gnlh = reply.header(); 419 struct nlattr *mcgrp = NULL; 420 int i; 421 422 if (!tb[CTRL_ATTR_MCAST_GROUPS]) { 423 ALOGI("No multicast groups found"); 424 return NL_SKIP; 425 } else { 426 // ALOGI("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS])); 427 } 428 429 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { 430 431 // ALOGI("Processing group"); 432 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; 433 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp), 434 nla_len(mcgrp), NULL); 435 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) { 436 continue; 437 } 438 439 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]); 440 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]); 441 442 // ALOGI("Found group name %s", grpName); 443 444 if (strncmp(grpName, mGroup, grpNameLen) != 0) 445 continue; 446 447 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); 448 break; 449 } 450 451 return NL_SKIP; 452 } 453 454 }; 455 456 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group) 457 { 458 GetMulticastIdCommand cmd(handle, name, group); 459 int res = cmd.requestResponse(); 460 if (res < 0) 461 return res; 462 else 463 return cmd.getId(); 464 } 465 466 ///////////////////////////////////////////////////////////////////////// 467 468 static bool is_wifi_interface(const char *name) 469 { 470 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) { 471 /* not a wifi interface; ignore it */ 472 return false; 473 } else { 474 return true; 475 } 476 } 477 478 static int get_interface(const char *name, interface_info *info) 479 { 480 strcpy(info->name, name); 481 info->id = if_nametoindex(name); 482 // ALOGI("found an interface : %s, id = %d", name, info->id); 483 return WIFI_SUCCESS; 484 } 485 486 wifi_error wifi_init_interfaces(wifi_handle handle) 487 { 488 hal_info *info = (hal_info *)handle; 489 490 struct dirent *de; 491 492 DIR *d = opendir("/sys/class/net"); 493 if (d == 0) 494 return WIFI_ERROR_UNKNOWN; 495 496 int n = 0; 497 while ((de = readdir(d))) { 498 if (de->d_name[0] == '.') 499 continue; 500 if (is_wifi_interface(de->d_name) ) { 501 n++; 502 } 503 } 504 505 closedir(d); 506 507 d = opendir("/sys/class/net"); 508 if (d == 0) 509 return WIFI_ERROR_UNKNOWN; 510 511 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n); 512 513 int i = 0; 514 while ((de = readdir(d))) { 515 if (de->d_name[0] == '.') 516 continue; 517 if (is_wifi_interface(de->d_name)) { 518 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info)); 519 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) { 520 free(ifinfo); 521 continue; 522 } 523 ifinfo->handle = handle; 524 info->interfaces[i] = ifinfo; 525 i++; 526 } 527 } 528 529 closedir(d); 530 531 info->num_interfaces = n; 532 return WIFI_SUCCESS; 533 } 534 535 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces) 536 { 537 hal_info *info = (hal_info *)handle; 538 539 *interfaces = (wifi_interface_handle *)info->interfaces; 540 *num = info->num_interfaces; 541 542 return WIFI_SUCCESS; 543 } 544 545 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size) 546 { 547 interface_info *info = (interface_info *)handle; 548 strcpy(name, info->name); 549 return WIFI_SUCCESS; 550 } 551 552 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name) 553 { 554 hal_info *info = (hal_info *)handle; 555 for (int i=0;i<info->num_interfaces;i++) 556 { 557 if (!strcmp(info->interfaces[i]->name, name)) 558 { 559 return ((wifi_interface_handle )(info->interfaces)[i]); 560 } 561 } 562 return NULL; 563 } 564 565 ///////////////////////////////////////////////////////////////////////////// 566 567 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set) { 568 return WIFI_ERROR_NOT_SUPPORTED; 569 } 570 571 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int max_size, 572 feature_set *matrix, int *size) { 573 return WIFI_ERROR_NOT_SUPPORTED; 574 } 575 576