1 /****************************************************************************** 2 * 3 * Copyright (C) 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 "btsnoop_net" 20 21 #include <assert.h> 22 #include <cutils/log.h> 23 #include <errno.h> 24 #include <netinet/in.h> 25 #include <pthread.h> 26 #include <stdbool.h> 27 #include <string.h> 28 #include <sys/prctl.h> 29 #include <sys/socket.h> 30 #include <sys/types.h> 31 32 #include "osi.h" 33 34 static void safe_close_(int *fd); 35 static void *listen_fn_(void *context); 36 37 static const char *LISTEN_THREAD_NAME_ = "btsnoop_net_listen"; 38 static const int LOCALHOST_ = 0x7F000001; 39 static const int LISTEN_PORT_ = 8872; 40 41 static pthread_t listen_thread_; 42 static bool listen_thread_valid_ = false; 43 static pthread_mutex_t client_socket_lock_ = PTHREAD_MUTEX_INITIALIZER; 44 static int listen_socket_ = -1; 45 static int client_socket_ = -1; 46 47 void btsnoop_net_open() { 48 listen_thread_valid_ = (pthread_create(&listen_thread_, NULL, listen_fn_, NULL) == 0); 49 if (!listen_thread_valid_) { 50 ALOGE("%s pthread_create failed: %s", __func__, strerror(errno)); 51 } else { 52 ALOGD("initialized"); 53 } 54 } 55 56 void btsnoop_net_close() { 57 if (listen_thread_valid_) { 58 shutdown(listen_socket_, SHUT_RDWR); 59 pthread_join(listen_thread_, NULL); 60 safe_close_(&client_socket_); 61 listen_thread_valid_ = false; 62 } 63 } 64 65 void btsnoop_net_write(const void *data, size_t length) { 66 pthread_mutex_lock(&client_socket_lock_); 67 if (client_socket_ != -1) { 68 if (send(client_socket_, data, length, 0) == -1 && errno == ECONNRESET) { 69 safe_close_(&client_socket_); 70 } 71 } 72 pthread_mutex_unlock(&client_socket_lock_); 73 } 74 75 static void *listen_fn_(UNUSED_ATTR void *context) { 76 77 prctl(PR_SET_NAME, (unsigned long)LISTEN_THREAD_NAME_, 0, 0, 0); 78 79 listen_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 80 if (listen_socket_ == -1) { 81 ALOGE("%s socket creation failed: %s", __func__, strerror(errno)); 82 goto cleanup; 83 } 84 85 int enable = 1; 86 if (setsockopt(listen_socket_, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == -1) { 87 ALOGE("%s unable to set SO_REUSEADDR: %s", __func__, strerror(errno)); 88 goto cleanup; 89 } 90 91 struct sockaddr_in addr; 92 addr.sin_family = AF_INET; 93 addr.sin_addr.s_addr = htonl(LOCALHOST_); 94 addr.sin_port = htons(LISTEN_PORT_); 95 if (bind(listen_socket_, (struct sockaddr *)&addr, sizeof(addr)) == -1) { 96 ALOGE("%s unable to bind listen socket: %s", __func__, strerror(errno)); 97 goto cleanup; 98 } 99 100 if (listen(listen_socket_, 10) == -1) { 101 ALOGE("%s unable to listen: %s", __func__, strerror(errno)); 102 goto cleanup; 103 } 104 105 for (;;) { 106 ALOGD("waiting for client connection"); 107 int client_socket = accept(listen_socket_, NULL, NULL); 108 if (client_socket == -1) { 109 if (errno == EINVAL || errno == EBADF) { 110 break; 111 } 112 ALOGW("%s error accepting socket: %s", __func__, strerror(errno)); 113 continue; 114 } 115 116 /* When a new client connects, we have to send the btsnoop file header. This allows 117 a decoder to treat the session as a new, valid btsnoop file. */ 118 ALOGI("client connected"); 119 pthread_mutex_lock(&client_socket_lock_); 120 safe_close_(&client_socket_); 121 client_socket_ = client_socket; 122 send(client_socket_, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16, 0); 123 pthread_mutex_unlock(&client_socket_lock_); 124 } 125 126 cleanup: 127 safe_close_(&listen_socket_); 128 return NULL; 129 } 130 131 static void safe_close_(int *fd) { 132 assert(fd != NULL); 133 if (*fd != -1) { 134 close(*fd); 135 *fd = -1; 136 } 137 } 138