1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "adb_listeners.h"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21
22 #include <android-base/stringprintf.h>
23 #include <cutils/sockets.h>
24
25 #include "sysdeps.h"
26 #include "transport.h"
27
28 int gListenAll = 0; /* Not static because it is used in commandline.c. */
29
30 static alistener listener_list = {
31 .next = &listener_list,
32 .prev = &listener_list,
33 };
34
ss_listener_event_func(int _fd,unsigned ev,void * _l)35 static void ss_listener_event_func(int _fd, unsigned ev, void *_l) {
36 if (ev & FDE_READ) {
37 sockaddr_storage ss;
38 sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
39 socklen_t alen = sizeof(ss);
40 int fd = adb_socket_accept(_fd, addrp, &alen);
41 if (fd < 0) return;
42
43 int rcv_buf_size = CHUNK_SIZE;
44 adb_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcv_buf_size, sizeof(rcv_buf_size));
45
46 asocket* s = create_local_socket(fd);
47 if (s) {
48 connect_to_smartsocket(s);
49 return;
50 }
51
52 adb_close(fd);
53 }
54 }
55
listener_event_func(int _fd,unsigned ev,void * _l)56 static void listener_event_func(int _fd, unsigned ev, void* _l)
57 {
58 alistener* listener = reinterpret_cast<alistener*>(_l);
59 asocket *s;
60
61 if (ev & FDE_READ) {
62 sockaddr_storage ss;
63 sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
64 socklen_t alen;
65 int fd;
66
67 alen = sizeof(ss);
68 fd = adb_socket_accept(_fd, addrp, &alen);
69 if (fd < 0) {
70 return;
71 }
72
73 s = create_local_socket(fd);
74 if (s) {
75 s->transport = listener->transport;
76 connect_to_remote(s, listener->connect_to);
77 return;
78 }
79
80 adb_close(fd);
81 }
82 }
83
free_listener(alistener * l)84 static void free_listener(alistener* l)
85 {
86 if (l->next) {
87 l->next->prev = l->prev;
88 l->prev->next = l->next;
89 l->next = l->prev = l;
90 }
91
92 // closes the corresponding fd
93 fdevent_remove(&l->fde);
94
95 if (l->local_name)
96 free((char*)l->local_name);
97
98 if (l->connect_to)
99 free((char*)l->connect_to);
100
101 if (l->transport) {
102 l->transport->RemoveDisconnect(&l->disconnect);
103 }
104 free(l);
105 }
106
listener_disconnect(void * arg,atransport *)107 static void listener_disconnect(void* arg, atransport*) {
108 alistener* listener = reinterpret_cast<alistener*>(arg);
109 listener->transport = nullptr;
110 free_listener(listener);
111 }
112
local_name_to_fd(const char * name,std::string * error)113 static int local_name_to_fd(const char* name, std::string* error) {
114 if (!strncmp("tcp:", name, 4)) {
115 int port = atoi(name + 4);
116 if (gListenAll > 0) {
117 return network_inaddr_any_server(port, SOCK_STREAM, error);
118 } else {
119 return network_loopback_server(port, SOCK_STREAM, error);
120 }
121 }
122 #if !defined(_WIN32) // No Unix-domain sockets on Windows.
123 // It's nonsensical to support the "reserved" space on the adb host side
124 if (!strncmp(name, "local:", 6)) {
125 return network_local_server(name + 6,
126 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
127 } else if (!strncmp(name, "localabstract:", 14)) {
128 return network_local_server(name + 14,
129 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
130 } else if (!strncmp(name, "localfilesystem:", 16)) {
131 return network_local_server(name + 16,
132 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM, error);
133 }
134
135 #endif
136 *error = android::base::StringPrintf("unknown local portname '%s'", name);
137 return -1;
138 }
139
140 // Write the list of current listeners (network redirections) into a string.
format_listeners()141 std::string format_listeners() {
142 std::string result;
143 for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
144 // Ignore special listeners like those for *smartsocket*
145 if (l->connect_to[0] == '*') {
146 continue;
147 }
148 // <device-serial> " " <local-name> " " <remote-name> "\n"
149 // Entries from "adb reverse" have no serial.
150 android::base::StringAppendF(&result, "%s %s %s\n",
151 l->transport->serial ? l->transport->serial : "(reverse)",
152 l->local_name, l->connect_to);
153 }
154 return result;
155 }
156
remove_listener(const char * local_name,atransport * transport)157 InstallStatus remove_listener(const char *local_name, atransport* transport) {
158 alistener *l;
159
160 for (l = listener_list.next; l != &listener_list; l = l->next) {
161 if (!strcmp(local_name, l->local_name)) {
162 free_listener(l);
163 return INSTALL_STATUS_OK;
164 }
165 }
166 return INSTALL_STATUS_LISTENER_NOT_FOUND;
167 }
168
remove_all_listeners(void)169 void remove_all_listeners(void)
170 {
171 alistener *l, *l_next;
172 for (l = listener_list.next; l != &listener_list; l = l_next) {
173 l_next = l->next;
174 // Never remove smart sockets.
175 if (l->connect_to[0] == '*')
176 continue;
177 free_listener(l);
178 }
179 }
180
install_listener(const std::string & local_name,const char * connect_to,atransport * transport,int no_rebind,std::string * error)181 InstallStatus install_listener(const std::string& local_name,
182 const char *connect_to,
183 atransport* transport,
184 int no_rebind,
185 std::string* error)
186 {
187 for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
188 if (local_name == l->local_name) {
189 char* cto;
190
191 /* can't repurpose a smartsocket */
192 if(l->connect_to[0] == '*') {
193 *error = "cannot repurpose smartsocket";
194 return INSTALL_STATUS_INTERNAL_ERROR;
195 }
196
197 /* can't repurpose a listener if 'no_rebind' is true */
198 if (no_rebind) {
199 *error = "cannot rebind";
200 return INSTALL_STATUS_CANNOT_REBIND;
201 }
202
203 cto = strdup(connect_to);
204 if(cto == 0) {
205 *error = "cannot duplicate string";
206 return INSTALL_STATUS_INTERNAL_ERROR;
207 }
208
209 free((void*) l->connect_to);
210 l->connect_to = cto;
211 if (l->transport != transport) {
212 l->transport->RemoveDisconnect(&l->disconnect);
213 l->transport = transport;
214 l->transport->AddDisconnect(&l->disconnect);
215 }
216 return INSTALL_STATUS_OK;
217 }
218 }
219
220 alistener* listener = reinterpret_cast<alistener*>(
221 calloc(1, sizeof(alistener)));
222 if (listener == nullptr) {
223 goto nomem;
224 }
225
226 listener->local_name = strdup(local_name.c_str());
227 if (listener->local_name == nullptr) {
228 goto nomem;
229 }
230
231 listener->connect_to = strdup(connect_to);
232 if (listener->connect_to == nullptr) {
233 goto nomem;
234 }
235
236 listener->fd = local_name_to_fd(listener->local_name, error);
237 if (listener->fd < 0) {
238 free(listener->local_name);
239 free(listener->connect_to);
240 free(listener);
241 return INSTALL_STATUS_CANNOT_BIND;
242 }
243
244 close_on_exec(listener->fd);
245 if (!strcmp(listener->connect_to, "*smartsocket*")) {
246 fdevent_install(&listener->fde, listener->fd, ss_listener_event_func,
247 listener);
248 } else {
249 fdevent_install(&listener->fde, listener->fd, listener_event_func,
250 listener);
251 }
252 fdevent_set(&listener->fde, FDE_READ);
253
254 listener->next = &listener_list;
255 listener->prev = listener_list.prev;
256 listener->next->prev = listener;
257 listener->prev->next = listener;
258 listener->transport = transport;
259
260 if (transport) {
261 listener->disconnect.opaque = listener;
262 listener->disconnect.func = listener_disconnect;
263 transport->AddDisconnect(&listener->disconnect);
264 }
265 return INSTALL_STATUS_OK;
266
267 nomem:
268 fatal("cannot allocate listener");
269 return INSTALL_STATUS_INTERNAL_ERROR;
270 }
271