1*dd0948b3SAndroid Build Coastguard Worker /*
2*dd0948b3SAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
3*dd0948b3SAndroid Build Coastguard Worker *
4*dd0948b3SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*dd0948b3SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*dd0948b3SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*dd0948b3SAndroid Build Coastguard Worker *
8*dd0948b3SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*dd0948b3SAndroid Build Coastguard Worker *
10*dd0948b3SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*dd0948b3SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*dd0948b3SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*dd0948b3SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*dd0948b3SAndroid Build Coastguard Worker * limitations under the License.
15*dd0948b3SAndroid Build Coastguard Worker */
16*dd0948b3SAndroid Build Coastguard Worker
17*dd0948b3SAndroid Build Coastguard Worker #include <errno.h>
18*dd0948b3SAndroid Build Coastguard Worker #include <iostream>
19*dd0948b3SAndroid Build Coastguard Worker #include <stdlib.h>
20*dd0948b3SAndroid Build Coastguard Worker #include <string.h>
21*dd0948b3SAndroid Build Coastguard Worker #include <sys/select.h>
22*dd0948b3SAndroid Build Coastguard Worker #include <sys/socket.h>
23*dd0948b3SAndroid Build Coastguard Worker #include <thread>
24*dd0948b3SAndroid Build Coastguard Worker #include <unistd.h>
25*dd0948b3SAndroid Build Coastguard Worker
26*dd0948b3SAndroid Build Coastguard Worker #include <libProxyConfig/libProxyConfig.h>
27*dd0948b3SAndroid Build Coastguard Worker
28*dd0948b3SAndroid Build Coastguard Worker #include <linux/vm_sockets.h>
29*dd0948b3SAndroid Build Coastguard Worker
30*dd0948b3SAndroid Build Coastguard Worker #define MAX(x, y) (((x) > (y)) ? (x) : (y))
31*dd0948b3SAndroid Build Coastguard Worker #define BUFFER_SIZE 16384
32*dd0948b3SAndroid Build Coastguard Worker #define CLIENT_QUEUE_SIZE 128
33*dd0948b3SAndroid Build Coastguard Worker
setupServerSocket(sockaddr_vm & addr)34*dd0948b3SAndroid Build Coastguard Worker int setupServerSocket(sockaddr_vm& addr) {
35*dd0948b3SAndroid Build Coastguard Worker int vsock_socket = socket(AF_VSOCK, SOCK_STREAM, 0);
36*dd0948b3SAndroid Build Coastguard Worker
37*dd0948b3SAndroid Build Coastguard Worker if (vsock_socket == -1) {
38*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Failed to create server VSOCK socket, ERROR = "
39*dd0948b3SAndroid Build Coastguard Worker << strerror(errno) << std::endl;
40*dd0948b3SAndroid Build Coastguard Worker return -1;
41*dd0948b3SAndroid Build Coastguard Worker }
42*dd0948b3SAndroid Build Coastguard Worker
43*dd0948b3SAndroid Build Coastguard Worker if (bind(vsock_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) != 0) {
44*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Failed to bind to server VSOCK socket, ERROR = "
45*dd0948b3SAndroid Build Coastguard Worker << strerror(errno) << std::endl;
46*dd0948b3SAndroid Build Coastguard Worker return -1;
47*dd0948b3SAndroid Build Coastguard Worker }
48*dd0948b3SAndroid Build Coastguard Worker
49*dd0948b3SAndroid Build Coastguard Worker if (listen(vsock_socket, CLIENT_QUEUE_SIZE) != 0) {
50*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Failed to listen on server VSOCK socket, ERROR = "
51*dd0948b3SAndroid Build Coastguard Worker << strerror(errno) << std::endl;
52*dd0948b3SAndroid Build Coastguard Worker return -1;
53*dd0948b3SAndroid Build Coastguard Worker }
54*dd0948b3SAndroid Build Coastguard Worker
55*dd0948b3SAndroid Build Coastguard Worker return vsock_socket;
56*dd0948b3SAndroid Build Coastguard Worker }
57*dd0948b3SAndroid Build Coastguard Worker
closeFileDescriptor(int fd)58*dd0948b3SAndroid Build Coastguard Worker void closeFileDescriptor(int fd) {
59*dd0948b3SAndroid Build Coastguard Worker close(fd);
60*dd0948b3SAndroid Build Coastguard Worker shutdown(fd, SHUT_RDWR);
61*dd0948b3SAndroid Build Coastguard Worker }
62*dd0948b3SAndroid Build Coastguard Worker
63*dd0948b3SAndroid Build Coastguard Worker // transfers a max of BUFFER_SIZE bytes between a source file descriptor and a
64*dd0948b3SAndroid Build Coastguard Worker // destination file descriptor. Returns true on success, false otherwise
transferBytes(int src_fd,int dst_fd)65*dd0948b3SAndroid Build Coastguard Worker bool transferBytes(int src_fd, int dst_fd) {
66*dd0948b3SAndroid Build Coastguard Worker char buf[BUFFER_SIZE];
67*dd0948b3SAndroid Build Coastguard Worker int readBytes = read(src_fd, buf, BUFFER_SIZE);
68*dd0948b3SAndroid Build Coastguard Worker if (readBytes <= 0) {
69*dd0948b3SAndroid Build Coastguard Worker return false;
70*dd0948b3SAndroid Build Coastguard Worker }
71*dd0948b3SAndroid Build Coastguard Worker int writtenBytes = write(dst_fd, buf, readBytes);
72*dd0948b3SAndroid Build Coastguard Worker return writtenBytes >= 0;
73*dd0948b3SAndroid Build Coastguard Worker }
74*dd0948b3SAndroid Build Coastguard Worker
75*dd0948b3SAndroid Build Coastguard Worker // Handles a client requesting to connect with the forwarding address
handleConnection(int client_sock,int fwd_cid,int fwd_port)76*dd0948b3SAndroid Build Coastguard Worker void* handleConnection(int client_sock, int fwd_cid, int fwd_port) {
77*dd0948b3SAndroid Build Coastguard Worker int server_sock = socket(AF_VSOCK, SOCK_STREAM, 0);
78*dd0948b3SAndroid Build Coastguard Worker
79*dd0948b3SAndroid Build Coastguard Worker if (server_sock < 0) {
80*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Failed to create forwarding VSOCK socket, ERROR = "
81*dd0948b3SAndroid Build Coastguard Worker << strerror(errno) << std::endl;
82*dd0948b3SAndroid Build Coastguard Worker closeFileDescriptor(server_sock);
83*dd0948b3SAndroid Build Coastguard Worker closeFileDescriptor(client_sock);
84*dd0948b3SAndroid Build Coastguard Worker return nullptr;
85*dd0948b3SAndroid Build Coastguard Worker }
86*dd0948b3SAndroid Build Coastguard Worker
87*dd0948b3SAndroid Build Coastguard Worker sockaddr_vm fwd_addr{};
88*dd0948b3SAndroid Build Coastguard Worker fwd_addr.svm_family = AF_VSOCK;
89*dd0948b3SAndroid Build Coastguard Worker fwd_addr.svm_cid = fwd_cid;
90*dd0948b3SAndroid Build Coastguard Worker fwd_addr.svm_port = fwd_port;
91*dd0948b3SAndroid Build Coastguard Worker
92*dd0948b3SAndroid Build Coastguard Worker if (connect(server_sock, reinterpret_cast<sockaddr*>(&fwd_addr),
93*dd0948b3SAndroid Build Coastguard Worker sizeof(fwd_addr)) < 0) {
94*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Failed to connect to forwarding vsock socket, ERROR = "
95*dd0948b3SAndroid Build Coastguard Worker << strerror(errno) << std::endl;
96*dd0948b3SAndroid Build Coastguard Worker closeFileDescriptor(server_sock);
97*dd0948b3SAndroid Build Coastguard Worker closeFileDescriptor(client_sock);
98*dd0948b3SAndroid Build Coastguard Worker return nullptr;
99*dd0948b3SAndroid Build Coastguard Worker }
100*dd0948b3SAndroid Build Coastguard Worker
101*dd0948b3SAndroid Build Coastguard Worker bool connected = true;
102*dd0948b3SAndroid Build Coastguard Worker while (connected) {
103*dd0948b3SAndroid Build Coastguard Worker fd_set file_descriptors;
104*dd0948b3SAndroid Build Coastguard Worker FD_ZERO(&file_descriptors);
105*dd0948b3SAndroid Build Coastguard Worker FD_SET(client_sock, &file_descriptors);
106*dd0948b3SAndroid Build Coastguard Worker FD_SET(server_sock, &file_descriptors);
107*dd0948b3SAndroid Build Coastguard Worker
108*dd0948b3SAndroid Build Coastguard Worker int rv = select(MAX(client_sock, server_sock) + 1, &file_descriptors, nullptr, nullptr,
109*dd0948b3SAndroid Build Coastguard Worker nullptr);
110*dd0948b3SAndroid Build Coastguard Worker if (rv == -1) {
111*dd0948b3SAndroid Build Coastguard Worker std::cerr << "ERROR in Select!. Error = " << strerror(errno) << std::endl;
112*dd0948b3SAndroid Build Coastguard Worker break;
113*dd0948b3SAndroid Build Coastguard Worker }
114*dd0948b3SAndroid Build Coastguard Worker
115*dd0948b3SAndroid Build Coastguard Worker if (FD_ISSET(client_sock, &file_descriptors)) {
116*dd0948b3SAndroid Build Coastguard Worker // transfer bytes from client to forward address
117*dd0948b3SAndroid Build Coastguard Worker connected = transferBytes(client_sock, server_sock);
118*dd0948b3SAndroid Build Coastguard Worker }
119*dd0948b3SAndroid Build Coastguard Worker
120*dd0948b3SAndroid Build Coastguard Worker if (FD_ISSET(server_sock, &file_descriptors)) {
121*dd0948b3SAndroid Build Coastguard Worker // transfer bytes from forward address to client
122*dd0948b3SAndroid Build Coastguard Worker connected = transferBytes(server_sock, client_sock);
123*dd0948b3SAndroid Build Coastguard Worker }
124*dd0948b3SAndroid Build Coastguard Worker }
125*dd0948b3SAndroid Build Coastguard Worker
126*dd0948b3SAndroid Build Coastguard Worker closeFileDescriptor(client_sock);
127*dd0948b3SAndroid Build Coastguard Worker closeFileDescriptor(server_sock);
128*dd0948b3SAndroid Build Coastguard Worker
129*dd0948b3SAndroid Build Coastguard Worker return nullptr;
130*dd0948b3SAndroid Build Coastguard Worker }
131*dd0948b3SAndroid Build Coastguard Worker
setupRoute(int cid,const android::automotive::proxyconfig::Service & service)132*dd0948b3SAndroid Build Coastguard Worker void setupRoute(int cid, const android::automotive::proxyconfig::Service& service) {
133*dd0948b3SAndroid Build Coastguard Worker
134*dd0948b3SAndroid Build Coastguard Worker sockaddr_vm addr{};
135*dd0948b3SAndroid Build Coastguard Worker addr.svm_family = AF_VSOCK;
136*dd0948b3SAndroid Build Coastguard Worker addr.svm_cid = 2;
137*dd0948b3SAndroid Build Coastguard Worker addr.svm_port = service.port;
138*dd0948b3SAndroid Build Coastguard Worker
139*dd0948b3SAndroid Build Coastguard Worker int fwd_cid = cid;
140*dd0948b3SAndroid Build Coastguard Worker int fwd_port = service.port;
141*dd0948b3SAndroid Build Coastguard Worker
142*dd0948b3SAndroid Build Coastguard Worker int proxy_socket = setupServerSocket(addr);
143*dd0948b3SAndroid Build Coastguard Worker
144*dd0948b3SAndroid Build Coastguard Worker if (proxy_socket == -1) {
145*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Failed to set up proxy server VSOCK socket, ERROR = " <<
146*dd0948b3SAndroid Build Coastguard Worker strerror(errno) << std::endl;
147*dd0948b3SAndroid Build Coastguard Worker return;
148*dd0948b3SAndroid Build Coastguard Worker }
149*dd0948b3SAndroid Build Coastguard Worker
150*dd0948b3SAndroid Build Coastguard Worker int client_sock;
151*dd0948b3SAndroid Build Coastguard Worker int len = sizeof(addr);
152*dd0948b3SAndroid Build Coastguard Worker
153*dd0948b3SAndroid Build Coastguard Worker while (true) {
154*dd0948b3SAndroid Build Coastguard Worker if ((client_sock = accept(proxy_socket, reinterpret_cast<sockaddr*>(&addr),
155*dd0948b3SAndroid Build Coastguard Worker reinterpret_cast<socklen_t*>(&len))) < 0) {
156*dd0948b3SAndroid Build Coastguard Worker std::cerr << "Failed to accept VSOCK connection, ERROR = " <<
157*dd0948b3SAndroid Build Coastguard Worker strerror(errno) << std::endl;
158*dd0948b3SAndroid Build Coastguard Worker closeFileDescriptor(client_sock);
159*dd0948b3SAndroid Build Coastguard Worker continue;
160*dd0948b3SAndroid Build Coastguard Worker }
161*dd0948b3SAndroid Build Coastguard Worker
162*dd0948b3SAndroid Build Coastguard Worker std::thread t(handleConnection, client_sock, fwd_cid, fwd_port);
163*dd0948b3SAndroid Build Coastguard Worker t.detach();
164*dd0948b3SAndroid Build Coastguard Worker }
165*dd0948b3SAndroid Build Coastguard Worker
166*dd0948b3SAndroid Build Coastguard Worker closeFileDescriptor(proxy_socket);
167*dd0948b3SAndroid Build Coastguard Worker }
168*dd0948b3SAndroid Build Coastguard Worker
169*dd0948b3SAndroid Build Coastguard Worker
170*dd0948b3SAndroid Build Coastguard Worker static constexpr const char *kProxyConfigFile =
171*dd0948b3SAndroid Build Coastguard Worker "../etc/automotive/proxy_config.json";
172*dd0948b3SAndroid Build Coastguard Worker
main(int argc,char ** argv)173*dd0948b3SAndroid Build Coastguard Worker int main(int argc, char **argv ) {
174*dd0948b3SAndroid Build Coastguard Worker android::automotive::proxyconfig::setProxyConfigFile(
175*dd0948b3SAndroid Build Coastguard Worker (argc >= 2)?argv[1]:kProxyConfigFile);
176*dd0948b3SAndroid Build Coastguard Worker
177*dd0948b3SAndroid Build Coastguard Worker auto vmConfigs = android::automotive::proxyconfig::getAllVmProxyConfigs();
178*dd0948b3SAndroid Build Coastguard Worker
179*dd0948b3SAndroid Build Coastguard Worker std::vector<std::thread> routeThreads;
180*dd0948b3SAndroid Build Coastguard Worker for (const auto& vmConfig: vmConfigs) {
181*dd0948b3SAndroid Build Coastguard Worker for (const auto& service: vmConfig.services) {
182*dd0948b3SAndroid Build Coastguard Worker routeThreads.push_back(std::thread(setupRoute, vmConfig.cid, service));
183*dd0948b3SAndroid Build Coastguard Worker }
184*dd0948b3SAndroid Build Coastguard Worker }
185*dd0948b3SAndroid Build Coastguard Worker
186*dd0948b3SAndroid Build Coastguard Worker for(auto& t: routeThreads) {
187*dd0948b3SAndroid Build Coastguard Worker t.join();
188*dd0948b3SAndroid Build Coastguard Worker }
189*dd0948b3SAndroid Build Coastguard Worker
190*dd0948b3SAndroid Build Coastguard Worker return 0;
191*dd0948b3SAndroid Build Coastguard Worker }
192