1 /****************************************************************************** 2 * 3 * Copyright 2013 Google, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 #define LOG_TAG "bt_snoop_net" 20 21 #include <base/logging.h> 22 #include <errno.h> 23 #include <netinet/in.h> 24 #include <pthread.h> 25 #include <stdbool.h> 26 #include <stdio.h> 27 #include <string.h> 28 #include <sys/prctl.h> 29 #include <sys/socket.h> 30 #include <sys/types.h> 31 #include <unistd.h> 32 33 #include <mutex> 34 35 #include "osi/include/log.h" 36 #include "osi/include/osi.h" 37 38 static void safe_close_(int* fd); 39 static void* listen_fn_(void* context); 40 41 static const char* LISTEN_THREAD_NAME_ = "btsnoop_net_listen"; 42 static const int LOCALHOST_ = 0x7F000001; 43 static const int LISTEN_PORT_ = 8872; 44 45 static pthread_t listen_thread_; 46 static bool listen_thread_valid_ = false; 47 static std::mutex client_socket_mutex_; 48 static int listen_socket_ = -1; 49 static int client_socket_ = -1; 50 51 void btsnoop_net_open() { 52 #if (BT_NET_DEBUG != TRUE) 53 return; // Disable using network sockets for security reasons 54 #endif 55 56 listen_thread_valid_ = 57 (pthread_create(&listen_thread_, NULL, listen_fn_, NULL) == 0); 58 if (!listen_thread_valid_) 59 LOG_ERROR(LOG_TAG, "%s pthread_create failed: %s", __func__, 60 strerror(errno)); 61 } 62 63 void btsnoop_net_close() { 64 #if (BT_NET_DEBUG != TRUE) 65 return; // Disable using network sockets for security reasons 66 #endif 67 68 if (listen_thread_valid_) { 69 shutdown(listen_socket_, SHUT_RDWR); 70 pthread_join(listen_thread_, NULL); 71 safe_close_(&client_socket_); 72 listen_thread_valid_ = false; 73 } 74 } 75 76 void btsnoop_net_write(const void* data, size_t length) { 77 #if (BT_NET_DEBUG != TRUE) 78 return; // Disable using network sockets for security reasons 79 #endif 80 81 std::lock_guard<std::mutex> lock(client_socket_mutex_); 82 if (client_socket_ != -1) { 83 ssize_t ret; 84 OSI_NO_INTR(ret = send(client_socket_, data, length, 0)); 85 86 if (ret == -1 && errno == ECONNRESET) { 87 safe_close_(&client_socket_); 88 } 89 } 90 } 91 92 static void* listen_fn_(UNUSED_ATTR void* context) { 93 int enable = 1; 94 95 prctl(PR_SET_NAME, (unsigned long)LISTEN_THREAD_NAME_, 0, 0, 0); 96 97 listen_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 98 if (listen_socket_ == -1) { 99 LOG_ERROR(LOG_TAG, "%s socket creation failed: %s", __func__, 100 strerror(errno)); 101 goto cleanup; 102 } 103 104 if (setsockopt(listen_socket_, SOL_SOCKET, SO_REUSEADDR, &enable, 105 sizeof(enable)) == -1) { 106 LOG_ERROR(LOG_TAG, "%s unable to set SO_REUSEADDR: %s", __func__, 107 strerror(errno)); 108 goto cleanup; 109 } 110 111 struct sockaddr_in addr; 112 addr.sin_family = AF_INET; 113 addr.sin_addr.s_addr = htonl(LOCALHOST_); 114 addr.sin_port = htons(LISTEN_PORT_); 115 if (bind(listen_socket_, (struct sockaddr*)&addr, sizeof(addr)) == -1) { 116 LOG_ERROR(LOG_TAG, "%s unable to bind listen socket: %s", __func__, 117 strerror(errno)); 118 goto cleanup; 119 } 120 121 if (listen(listen_socket_, 10) == -1) { 122 LOG_ERROR(LOG_TAG, "%s unable to listen: %s", __func__, strerror(errno)); 123 goto cleanup; 124 } 125 126 for (;;) { 127 int client_socket; 128 OSI_NO_INTR(client_socket = accept(listen_socket_, NULL, NULL)); 129 if (client_socket == -1) { 130 if (errno == EINVAL || errno == EBADF) { 131 break; 132 } 133 LOG_WARN(LOG_TAG, "%s error accepting socket: %s", __func__, 134 strerror(errno)); 135 continue; 136 } 137 138 /* When a new client connects, we have to send the btsnoop file header. This 139 * allows a decoder to treat the session as a new, valid btsnoop file. */ 140 std::lock_guard<std::mutex> lock(client_socket_mutex_); 141 safe_close_(&client_socket_); 142 client_socket_ = client_socket; 143 144 OSI_NO_INTR(send(client_socket_, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16, 0)); 145 } 146 147 cleanup: 148 safe_close_(&listen_socket_); 149 return NULL; 150 } 151 152 static void safe_close_(int* fd) { 153 CHECK(fd != NULL); 154 if (*fd != -1) { 155 close(*fd); 156 *fd = -1; 157 } 158 } 159