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 "bt_types.h"
36 #include "osi/include/log.h"
37 #include "osi/include/osi.h"
38
39 static void safe_close_(int* fd);
40 static void* listen_fn_(void* context);
41
42 static const char* LISTEN_THREAD_NAME_ = "btsnoop_net_listen";
43 static const int LOCALHOST_ = 0x7F000001;
44 static const int LISTEN_PORT_ = 8872;
45
46 static pthread_t listen_thread_;
47 static bool listen_thread_valid_ = false;
48 static std::mutex client_socket_mutex_;
49 static int listen_socket_ = -1;
50 static int client_socket_ = -1;
51
btsnoop_net_open()52 void btsnoop_net_open() {
53 #if (BT_NET_DEBUG != true)
54 return; // Disable using network sockets for security reasons
55 #endif
56
57 listen_thread_valid_ =
58 (pthread_create(&listen_thread_, NULL, listen_fn_, NULL) == 0);
59 if (!listen_thread_valid_)
60 LOG_ERROR("%s pthread_create failed: %s", __func__, strerror(errno));
61 }
62
btsnoop_net_close()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
btsnoop_net_write(const void * data,size_t length)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
listen_fn_(UNUSED_ATTR void * context)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("%s socket creation failed: %s", __func__, strerror(errno));
100 goto cleanup;
101 }
102
103 if (setsockopt(listen_socket_, SOL_SOCKET, SO_REUSEADDR, &enable,
104 sizeof(enable)) == -1) {
105 LOG_ERROR("%s unable to set SO_REUSEADDR: %s", __func__, strerror(errno));
106 goto cleanup;
107 }
108
109 struct sockaddr_in addr;
110 addr.sin_family = AF_INET;
111 addr.sin_addr.s_addr = htonl(LOCALHOST_);
112 addr.sin_port = htons(LISTEN_PORT_);
113 if (bind(listen_socket_, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
114 LOG_ERROR("%s unable to bind listen socket: %s", __func__, strerror(errno));
115 goto cleanup;
116 }
117
118 if (listen(listen_socket_, 10) == -1) {
119 LOG_ERROR("%s unable to listen: %s", __func__, strerror(errno));
120 goto cleanup;
121 }
122
123 for (;;) {
124 int client_socket;
125 OSI_NO_INTR(client_socket = accept(listen_socket_, NULL, NULL));
126 if (client_socket == -1) {
127 if (errno == EINVAL || errno == EBADF) {
128 break;
129 }
130 LOG_WARN("%s error accepting socket: %s", __func__, strerror(errno));
131 continue;
132 }
133
134 /* When a new client connects, we have to send the btsnoop file header. This
135 * allows a decoder to treat the session as a new, valid btsnoop file. */
136 std::lock_guard<std::mutex> lock(client_socket_mutex_);
137 safe_close_(&client_socket_);
138 client_socket_ = client_socket;
139
140 OSI_NO_INTR(send(client_socket_, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16, 0));
141 }
142
143 cleanup:
144 safe_close_(&listen_socket_);
145 return NULL;
146 }
147
safe_close_(int * fd)148 static void safe_close_(int* fd) {
149 CHECK(fd != NULL);
150 if (*fd != -1) {
151 close(*fd);
152 *fd = -1;
153 }
154 }
155