• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "bt_snoop_net"
20 
21 #include <assert.h>
22 #include <errno.h>
23 #include <netinet/in.h>
24 #include <pthread.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <sys/prctl.h>
28 #include <sys/socket.h>
29 #include <sys/types.h>
30 
31 #include "osi/include/osi.h"
32 #include "osi/include/log.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 
btsnoop_net_open()47 void btsnoop_net_open() {
48 #if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE))
49   return;               // Disable using network sockets for security reasons
50 #endif
51 
52   listen_thread_valid_ = (pthread_create(&listen_thread_, NULL, listen_fn_, NULL) == 0);
53   if (!listen_thread_valid_) {
54     LOG_ERROR("%s pthread_create failed: %s", __func__, strerror(errno));
55   } else {
56     LOG_DEBUG("initialized");
57   }
58 }
59 
btsnoop_net_close()60 void btsnoop_net_close() {
61 #if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE))
62   return;               // Disable using network sockets for security reasons
63 #endif
64 
65   if (listen_thread_valid_) {
66     shutdown(listen_socket_, SHUT_RDWR);
67     pthread_join(listen_thread_, NULL);
68     safe_close_(&client_socket_);
69     listen_thread_valid_ = false;
70   }
71 }
72 
btsnoop_net_write(const void * data,size_t length)73 void btsnoop_net_write(const void *data, size_t length) {
74 #if (!defined(BT_NET_DEBUG) || (BT_NET_DEBUG != TRUE))
75   return;               // Disable using network sockets for security reasons
76 #endif
77 
78   pthread_mutex_lock(&client_socket_lock_);
79   if (client_socket_ != -1) {
80     if (TEMP_FAILURE_RETRY(send(client_socket_, data, length, 0)) == -1 && errno == ECONNRESET) {
81       safe_close_(&client_socket_);
82     }
83   }
84   pthread_mutex_unlock(&client_socket_lock_);
85 }
86 
listen_fn_(UNUSED_ATTR void * context)87 static void *listen_fn_(UNUSED_ATTR void *context) {
88 
89   prctl(PR_SET_NAME, (unsigned long)LISTEN_THREAD_NAME_, 0, 0, 0);
90 
91   listen_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
92   if (listen_socket_ == -1) {
93     LOG_ERROR("%s socket creation failed: %s", __func__, strerror(errno));
94     goto cleanup;
95   }
96 
97   int enable = 1;
98   if (setsockopt(listen_socket_, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == -1) {
99     LOG_ERROR("%s unable to set SO_REUSEADDR: %s", __func__, strerror(errno));
100     goto cleanup;
101   }
102 
103   struct sockaddr_in addr;
104   addr.sin_family = AF_INET;
105   addr.sin_addr.s_addr = htonl(LOCALHOST_);
106   addr.sin_port = htons(LISTEN_PORT_);
107   if (bind(listen_socket_, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
108     LOG_ERROR("%s unable to bind listen socket: %s", __func__, strerror(errno));
109     goto cleanup;
110   }
111 
112   if (listen(listen_socket_, 10) == -1) {
113     LOG_ERROR("%s unable to listen: %s", __func__, strerror(errno));
114     goto cleanup;
115   }
116 
117   for (;;) {
118     int client_socket = TEMP_FAILURE_RETRY(accept(listen_socket_, NULL, NULL));
119     if (client_socket == -1) {
120       if (errno == EINVAL || errno == EBADF) {
121         break;
122       }
123       LOG_WARN("%s error accepting socket: %s", __func__, strerror(errno));
124       continue;
125     }
126 
127     /* When a new client connects, we have to send the btsnoop file header. This allows
128        a decoder to treat the session as a new, valid btsnoop file. */
129     pthread_mutex_lock(&client_socket_lock_);
130     safe_close_(&client_socket_);
131     client_socket_ = client_socket;
132     TEMP_FAILURE_RETRY(send(client_socket_, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16, 0));
133     pthread_mutex_unlock(&client_socket_lock_);
134   }
135 
136 cleanup:
137   safe_close_(&listen_socket_);
138   return NULL;
139 }
140 
safe_close_(int * fd)141 static void safe_close_(int *fd) {
142   assert(fd != NULL);
143   if (*fd != -1) {
144     close(*fd);
145     *fd = -1;
146   }
147 }
148