1611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati/****************************************************************************** 2611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * 3611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * Copyright (C) 2013 Google, Inc. 4611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * 5611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * Licensed under the Apache License, Version 2.0 (the "License"); 6611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * you may not use this file except in compliance with the License. 7611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * You may obtain a copy of the License at: 8611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * 9611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * http://www.apache.org/licenses/LICENSE-2.0 10611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * 11611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * Unless required by applicable law or agreed to in writing, software 12611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * distributed under the License is distributed on an "AS IS" BASIS, 13611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * See the License for the specific language governing permissions and 15611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * limitations under the License. 16611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati * 17611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati ******************************************************************************/ 18611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 19f8027005333c88a2f097cfd70d15c3d54c7764aeChris Manton#define LOG_TAG "bt_snoop_net" 20a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati 21f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He#include <base/logging.h> 22611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati#include <errno.h> 23611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati#include <netinet/in.h> 24611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati#include <pthread.h> 25611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati#include <stdbool.h> 266aee1e82aa0bf44d7e382f1b01448fe31c490763Mark Salyzyn#include <stdio.h> 27611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati#include <string.h> 28611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati#include <sys/prctl.h> 29611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati#include <sys/socket.h> 30611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati#include <sys/types.h> 31a2647d0f5b0078d95d547a96548462b910bd453cArman Uguray#include <unistd.h> 32611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 3321da63773cb7734e699a4dad662b5b84d2f3dfa8Marie Janssen#include <mutex> 3421da63773cb7734e699a4dad662b5b84d2f3dfa8Marie Janssen 3544802768c447ab480d4227b3a852a97d923b816dSharvil Nanavati#include "osi/include/log.h" 3649a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen#include "osi/include/osi.h" 37611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 385ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void safe_close_(int* fd); 395ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void* listen_fn_(void* context); 40611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 415ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic const char* LISTEN_THREAD_NAME_ = "btsnoop_net_listen"; 42611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavatistatic const int LOCALHOST_ = 0x7F000001; 43611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavatistatic const int LISTEN_PORT_ = 8872; 44611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 45611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavatistatic pthread_t listen_thread_; 46611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavatistatic bool listen_thread_valid_ = false; 4721da63773cb7734e699a4dad662b5b84d2f3dfa8Marie Janssenstatic std::mutex client_socket_mutex_; 48611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavatistatic int listen_socket_ = -1; 49611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavatistatic int client_socket_ = -1; 50611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 51a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavativoid btsnoop_net_open() { 52d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BT_NET_DEBUG != TRUE) 535ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson return; // Disable using network sockets for security reasons 544cac544da367d7458129631ddef6db4e3312cef7Pavlin Radoslavov#endif 554cac544da367d7458129631ddef6db4e3312cef7Pavlin Radoslavov 565ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson listen_thread_valid_ = 575ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson (pthread_create(&listen_thread_, NULL, listen_fn_, NULL) == 0); 58ec728d3136aabcd7675aba4a672d932e0709c509Myles Watson if (!listen_thread_valid_) 595ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson LOG_ERROR(LOG_TAG, "%s pthread_create failed: %s", __func__, 605ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson strerror(errno)); 61611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati} 62611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 63a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavativoid btsnoop_net_close() { 64d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BT_NET_DEBUG != TRUE) 655ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson return; // Disable using network sockets for security reasons 664cac544da367d7458129631ddef6db4e3312cef7Pavlin Radoslavov#endif 674cac544da367d7458129631ddef6db4e3312cef7Pavlin Radoslavov 68611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati if (listen_thread_valid_) { 69611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati shutdown(listen_socket_, SHUT_RDWR); 70611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati pthread_join(listen_thread_, NULL); 71611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati safe_close_(&client_socket_); 72611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati listen_thread_valid_ = false; 73611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 74611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati} 75611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 765ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonvoid btsnoop_net_write(const void* data, size_t length) { 77d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BT_NET_DEBUG != TRUE) 785ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson return; // Disable using network sockets for security reasons 794cac544da367d7458129631ddef6db4e3312cef7Pavlin Radoslavov#endif 804cac544da367d7458129631ddef6db4e3312cef7Pavlin Radoslavov 8121da63773cb7734e699a4dad662b5b84d2f3dfa8Marie Janssen std::lock_guard<std::mutex> lock(client_socket_mutex_); 82611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati if (client_socket_ != -1) { 83d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov ssize_t ret; 84d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov OSI_NO_INTR(ret = send(client_socket_, data, length, 0)); 85d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov 86d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov if (ret == -1 && errno == ECONNRESET) { 87611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati safe_close_(&client_socket_); 88611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 89611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 90611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati} 91611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 925ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void* listen_fn_(UNUSED_ATTR void* context) { 93b2a292b5d8df2f359c38b0787bc01181225a9bc9Pavlin Radoslavov int enable = 1; 94a7d7eb78b826cde99adb67fb7078aca85ea61da3Sharvil Nanavati 95611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati prctl(PR_SET_NAME, (unsigned long)LISTEN_THREAD_NAME_, 0, 0, 0); 96611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 97611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati listen_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 98611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati if (listen_socket_ == -1) { 995ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson LOG_ERROR(LOG_TAG, "%s socket creation failed: %s", __func__, 1005ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson strerror(errno)); 101611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati goto cleanup; 102611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 103611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 1045ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson if (setsockopt(listen_socket_, SOL_SOCKET, SO_REUSEADDR, &enable, 1055ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson sizeof(enable)) == -1) { 1065ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson LOG_ERROR(LOG_TAG, "%s unable to set SO_REUSEADDR: %s", __func__, 1075ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson strerror(errno)); 108611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati goto cleanup; 109611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 110611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 111611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati struct sockaddr_in addr; 112611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati addr.sin_family = AF_INET; 113611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati addr.sin_addr.s_addr = htonl(LOCALHOST_); 114611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati addr.sin_port = htons(LISTEN_PORT_); 1155ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson if (bind(listen_socket_, (struct sockaddr*)&addr, sizeof(addr)) == -1) { 1165ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson LOG_ERROR(LOG_TAG, "%s unable to bind listen socket: %s", __func__, 1175ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson strerror(errno)); 118611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati goto cleanup; 119611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 120611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 121611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati if (listen(listen_socket_, 10) == -1) { 122db554581079863974af8e1289646f5deea6fc044Marie Janssen LOG_ERROR(LOG_TAG, "%s unable to listen: %s", __func__, strerror(errno)); 123611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati goto cleanup; 124611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 125611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 126611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati for (;;) { 127d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov int client_socket; 128d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov OSI_NO_INTR(client_socket = accept(listen_socket_, NULL, NULL)); 129611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati if (client_socket == -1) { 130611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati if (errno == EINVAL || errno == EBADF) { 131611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati break; 132611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 1335ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson LOG_WARN(LOG_TAG, "%s error accepting socket: %s", __func__, 1345ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson strerror(errno)); 135611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati continue; 136611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 137611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 1385ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson /* When a new client connects, we have to send the btsnoop file header. This 13929483137606d358f72ee544127ec8d052afe0ab0Myles Watson * allows a decoder to treat the session as a new, valid btsnoop file. */ 14021da63773cb7734e699a4dad662b5b84d2f3dfa8Marie Janssen std::lock_guard<std::mutex> lock(client_socket_mutex_); 141611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati safe_close_(&client_socket_); 142611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati client_socket_ = client_socket; 143d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov 144d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov OSI_NO_INTR(send(client_socket_, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16, 0)); 145611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 146611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 147611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavaticleanup: 148611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati safe_close_(&listen_socket_); 149611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati return NULL; 150611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati} 151611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati 1525ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void safe_close_(int* fd) { 153f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(fd != NULL); 154611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati if (*fd != -1) { 155611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati close(*fd); 156611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati *fd = -1; 157611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati } 158611f3abf1c12a9f568114e46a21e70c74eaf6a60Sharvil Nanavati} 159