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
28int gListenAll = 0; /* Not static because it is used in commandline.c. */
29
30static alistener listener_list = {
31    .next = &listener_list,
32    .prev = &listener_list,
33};
34
35static 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
56static 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
84static 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
107static void listener_disconnect(void* arg, atransport*) {
108    alistener* listener = reinterpret_cast<alistener*>(arg);
109    listener->transport = nullptr;
110    free_listener(listener);
111}
112
113static 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.
141std::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
157InstallStatus 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
169void 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
181InstallStatus 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
267nomem:
268    fatal("cannot allocate listener");
269    return INSTALL_STATUS_INTERNAL_ERROR;
270}
271