• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
btsnoop_net_open()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 
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(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 
safe_close_(int * fd)152 static void safe_close_(int* fd) {
153   CHECK(fd != NULL);
154   if (*fd != -1) {
155     close(*fd);
156     *fd = -1;
157   }
158 }
159