xref: /aosp_15_r20/development/samples/ToyVpn/server/linux/ToyVpnServer.cpp (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1*90c8c64dSAndroid Build Coastguard Worker /*
2*90c8c64dSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*90c8c64dSAndroid Build Coastguard Worker  *
4*90c8c64dSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*90c8c64dSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*90c8c64dSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*90c8c64dSAndroid Build Coastguard Worker  *
8*90c8c64dSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*90c8c64dSAndroid Build Coastguard Worker  *
10*90c8c64dSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*90c8c64dSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*90c8c64dSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*90c8c64dSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*90c8c64dSAndroid Build Coastguard Worker  * limitations under the License.
15*90c8c64dSAndroid Build Coastguard Worker  */
16*90c8c64dSAndroid Build Coastguard Worker 
17*90c8c64dSAndroid Build Coastguard Worker #include <stdio.h>
18*90c8c64dSAndroid Build Coastguard Worker #include <stdlib.h>
19*90c8c64dSAndroid Build Coastguard Worker #include <string.h>
20*90c8c64dSAndroid Build Coastguard Worker #include <unistd.h>
21*90c8c64dSAndroid Build Coastguard Worker #include <arpa/inet.h>
22*90c8c64dSAndroid Build Coastguard Worker #include <netinet/in.h>
23*90c8c64dSAndroid Build Coastguard Worker #include <sys/ioctl.h>
24*90c8c64dSAndroid Build Coastguard Worker #include <sys/socket.h>
25*90c8c64dSAndroid Build Coastguard Worker #include <sys/stat.h>
26*90c8c64dSAndroid Build Coastguard Worker #include <sys/types.h>
27*90c8c64dSAndroid Build Coastguard Worker #include <errno.h>
28*90c8c64dSAndroid Build Coastguard Worker #include <fcntl.h>
29*90c8c64dSAndroid Build Coastguard Worker 
30*90c8c64dSAndroid Build Coastguard Worker #ifdef __linux__
31*90c8c64dSAndroid Build Coastguard Worker 
32*90c8c64dSAndroid Build Coastguard Worker // There are several ways to play with this program. Here we just give an
33*90c8c64dSAndroid Build Coastguard Worker // example for the simplest scenario. Let us say that a Linux box has a
34*90c8c64dSAndroid Build Coastguard Worker // public IPv4 address on eth0. Please try the following steps and adjust
35*90c8c64dSAndroid Build Coastguard Worker // the parameters when necessary.
36*90c8c64dSAndroid Build Coastguard Worker //
37*90c8c64dSAndroid Build Coastguard Worker // # Enable IP forwarding
38*90c8c64dSAndroid Build Coastguard Worker // echo 1 > /proc/sys/net/ipv4/ip_forward
39*90c8c64dSAndroid Build Coastguard Worker //
40*90c8c64dSAndroid Build Coastguard Worker // # Pick a range of private addresses and perform NAT over eth0.
41*90c8c64dSAndroid Build Coastguard Worker // iptables -t nat -A POSTROUTING -s 10.0.0.0/8 -o eth0 -j MASQUERADE
42*90c8c64dSAndroid Build Coastguard Worker //
43*90c8c64dSAndroid Build Coastguard Worker // # Create a TUN interface.
44*90c8c64dSAndroid Build Coastguard Worker // ip tuntap add dev tun0 mode tun
45*90c8c64dSAndroid Build Coastguard Worker //
46*90c8c64dSAndroid Build Coastguard Worker // # Set the addresses and bring up the interface.
47*90c8c64dSAndroid Build Coastguard Worker // ifconfig tun0 10.0.0.1 dstaddr 10.0.0.2 up
48*90c8c64dSAndroid Build Coastguard Worker //
49*90c8c64dSAndroid Build Coastguard Worker // # Create a server on port 8000 with shared secret "test".
50*90c8c64dSAndroid Build Coastguard Worker // ./ToyVpnServer tun0 8000 test -m 1400 -a 10.0.0.2 32 -d 8.8.8.8 -r 0.0.0.0 0
51*90c8c64dSAndroid Build Coastguard Worker //
52*90c8c64dSAndroid Build Coastguard Worker // This program only handles a session at a time. To allow multiple sessions,
53*90c8c64dSAndroid Build Coastguard Worker // multiple servers can be created on the same port, but each of them requires
54*90c8c64dSAndroid Build Coastguard Worker // its own TUN interface. A short shell script will be sufficient. Since this
55*90c8c64dSAndroid Build Coastguard Worker // program is designed for demonstration purpose, it performs neither strong
56*90c8c64dSAndroid Build Coastguard Worker // authentication nor encryption. DO NOT USE IT IN PRODUCTION!
57*90c8c64dSAndroid Build Coastguard Worker 
58*90c8c64dSAndroid Build Coastguard Worker #include <net/if.h>
59*90c8c64dSAndroid Build Coastguard Worker #include <linux/if_tun.h>
60*90c8c64dSAndroid Build Coastguard Worker 
get_interface(char * name)61*90c8c64dSAndroid Build Coastguard Worker static int get_interface(char *name)
62*90c8c64dSAndroid Build Coastguard Worker {
63*90c8c64dSAndroid Build Coastguard Worker     int interface = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
64*90c8c64dSAndroid Build Coastguard Worker 
65*90c8c64dSAndroid Build Coastguard Worker     ifreq ifr;
66*90c8c64dSAndroid Build Coastguard Worker     memset(&ifr, 0, sizeof(ifr));
67*90c8c64dSAndroid Build Coastguard Worker     ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
68*90c8c64dSAndroid Build Coastguard Worker     strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
69*90c8c64dSAndroid Build Coastguard Worker 
70*90c8c64dSAndroid Build Coastguard Worker     if (ioctl(interface, TUNSETIFF, &ifr)) {
71*90c8c64dSAndroid Build Coastguard Worker         perror("Cannot get TUN interface");
72*90c8c64dSAndroid Build Coastguard Worker         exit(1);
73*90c8c64dSAndroid Build Coastguard Worker     }
74*90c8c64dSAndroid Build Coastguard Worker 
75*90c8c64dSAndroid Build Coastguard Worker     return interface;
76*90c8c64dSAndroid Build Coastguard Worker }
77*90c8c64dSAndroid Build Coastguard Worker 
78*90c8c64dSAndroid Build Coastguard Worker #else
79*90c8c64dSAndroid Build Coastguard Worker 
80*90c8c64dSAndroid Build Coastguard Worker #error Sorry, you have to implement this part by yourself.
81*90c8c64dSAndroid Build Coastguard Worker 
82*90c8c64dSAndroid Build Coastguard Worker #endif
83*90c8c64dSAndroid Build Coastguard Worker 
get_tunnel(char * port,char * secret)84*90c8c64dSAndroid Build Coastguard Worker static int get_tunnel(char *port, char *secret)
85*90c8c64dSAndroid Build Coastguard Worker {
86*90c8c64dSAndroid Build Coastguard Worker     // We use an IPv6 socket to cover both IPv4 and IPv6.
87*90c8c64dSAndroid Build Coastguard Worker     int tunnel = socket(AF_INET6, SOCK_DGRAM, 0);
88*90c8c64dSAndroid Build Coastguard Worker     int flag = 1;
89*90c8c64dSAndroid Build Coastguard Worker     setsockopt(tunnel, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
90*90c8c64dSAndroid Build Coastguard Worker     flag = 0;
91*90c8c64dSAndroid Build Coastguard Worker     setsockopt(tunnel, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag));
92*90c8c64dSAndroid Build Coastguard Worker 
93*90c8c64dSAndroid Build Coastguard Worker     // Accept packets received on any local address.
94*90c8c64dSAndroid Build Coastguard Worker     sockaddr_in6 addr;
95*90c8c64dSAndroid Build Coastguard Worker     memset(&addr, 0, sizeof(addr));
96*90c8c64dSAndroid Build Coastguard Worker     addr.sin6_family = AF_INET6;
97*90c8c64dSAndroid Build Coastguard Worker     addr.sin6_port = htons(atoi(port));
98*90c8c64dSAndroid Build Coastguard Worker 
99*90c8c64dSAndroid Build Coastguard Worker     // Call bind(2) in a loop since Linux does not have SO_REUSEPORT.
100*90c8c64dSAndroid Build Coastguard Worker     while (bind(tunnel, (sockaddr *)&addr, sizeof(addr))) {
101*90c8c64dSAndroid Build Coastguard Worker         if (errno != EADDRINUSE) {
102*90c8c64dSAndroid Build Coastguard Worker             return -1;
103*90c8c64dSAndroid Build Coastguard Worker         }
104*90c8c64dSAndroid Build Coastguard Worker         usleep(100000);
105*90c8c64dSAndroid Build Coastguard Worker     }
106*90c8c64dSAndroid Build Coastguard Worker 
107*90c8c64dSAndroid Build Coastguard Worker     // Receive packets till the secret matches.
108*90c8c64dSAndroid Build Coastguard Worker     char packet[1024];
109*90c8c64dSAndroid Build Coastguard Worker     socklen_t addrlen;
110*90c8c64dSAndroid Build Coastguard Worker     do {
111*90c8c64dSAndroid Build Coastguard Worker         addrlen = sizeof(addr);
112*90c8c64dSAndroid Build Coastguard Worker         int n = recvfrom(tunnel, packet, sizeof(packet), 0,
113*90c8c64dSAndroid Build Coastguard Worker                 (sockaddr *)&addr, &addrlen);
114*90c8c64dSAndroid Build Coastguard Worker         if (n <= 0) {
115*90c8c64dSAndroid Build Coastguard Worker             return -1;
116*90c8c64dSAndroid Build Coastguard Worker         }
117*90c8c64dSAndroid Build Coastguard Worker         packet[n] = 0;
118*90c8c64dSAndroid Build Coastguard Worker     } while (packet[0] != 0 || strcmp(secret, &packet[1]));
119*90c8c64dSAndroid Build Coastguard Worker 
120*90c8c64dSAndroid Build Coastguard Worker     // Connect to the client as we only handle one client at a time.
121*90c8c64dSAndroid Build Coastguard Worker     connect(tunnel, (sockaddr *)&addr, addrlen);
122*90c8c64dSAndroid Build Coastguard Worker     return tunnel;
123*90c8c64dSAndroid Build Coastguard Worker }
124*90c8c64dSAndroid Build Coastguard Worker 
build_parameters(char * parameters,int size,int argc,char ** argv)125*90c8c64dSAndroid Build Coastguard Worker static void build_parameters(char *parameters, int size, int argc, char **argv)
126*90c8c64dSAndroid Build Coastguard Worker {
127*90c8c64dSAndroid Build Coastguard Worker     // Well, for simplicity, we just concatenate them (almost) blindly.
128*90c8c64dSAndroid Build Coastguard Worker     int offset = 0;
129*90c8c64dSAndroid Build Coastguard Worker     for (int i = 4; i < argc; ++i) {
130*90c8c64dSAndroid Build Coastguard Worker         char *parameter = argv[i];
131*90c8c64dSAndroid Build Coastguard Worker         int length = strlen(parameter);
132*90c8c64dSAndroid Build Coastguard Worker         char delimiter = ',';
133*90c8c64dSAndroid Build Coastguard Worker 
134*90c8c64dSAndroid Build Coastguard Worker         // If it looks like an option, prepend a space instead of a comma.
135*90c8c64dSAndroid Build Coastguard Worker         if (length == 2 && parameter[0] == '-') {
136*90c8c64dSAndroid Build Coastguard Worker             ++parameter;
137*90c8c64dSAndroid Build Coastguard Worker             --length;
138*90c8c64dSAndroid Build Coastguard Worker             delimiter = ' ';
139*90c8c64dSAndroid Build Coastguard Worker         }
140*90c8c64dSAndroid Build Coastguard Worker 
141*90c8c64dSAndroid Build Coastguard Worker         // This is just a demo app, really.
142*90c8c64dSAndroid Build Coastguard Worker         if (offset + length >= size) {
143*90c8c64dSAndroid Build Coastguard Worker             puts("Parameters are too large");
144*90c8c64dSAndroid Build Coastguard Worker             exit(1);
145*90c8c64dSAndroid Build Coastguard Worker         }
146*90c8c64dSAndroid Build Coastguard Worker 
147*90c8c64dSAndroid Build Coastguard Worker         // Append the delimiter and the parameter.
148*90c8c64dSAndroid Build Coastguard Worker         parameters[offset] = delimiter;
149*90c8c64dSAndroid Build Coastguard Worker         memcpy(&parameters[offset + 1], parameter, length);
150*90c8c64dSAndroid Build Coastguard Worker         offset += 1 + length;
151*90c8c64dSAndroid Build Coastguard Worker     }
152*90c8c64dSAndroid Build Coastguard Worker 
153*90c8c64dSAndroid Build Coastguard Worker     // Fill the rest of the space with spaces.
154*90c8c64dSAndroid Build Coastguard Worker     memset(&parameters[offset], ' ', size - offset);
155*90c8c64dSAndroid Build Coastguard Worker 
156*90c8c64dSAndroid Build Coastguard Worker     // Control messages always start with zero.
157*90c8c64dSAndroid Build Coastguard Worker     parameters[0] = 0;
158*90c8c64dSAndroid Build Coastguard Worker }
159*90c8c64dSAndroid Build Coastguard Worker 
160*90c8c64dSAndroid Build Coastguard Worker //-----------------------------------------------------------------------------
161*90c8c64dSAndroid Build Coastguard Worker 
main(int argc,char ** argv)162*90c8c64dSAndroid Build Coastguard Worker int main(int argc, char **argv)
163*90c8c64dSAndroid Build Coastguard Worker {
164*90c8c64dSAndroid Build Coastguard Worker     if (argc < 5) {
165*90c8c64dSAndroid Build Coastguard Worker         printf("Usage: %s <tunN> <port> <secret> options...\n"
166*90c8c64dSAndroid Build Coastguard Worker                "\n"
167*90c8c64dSAndroid Build Coastguard Worker                "Options:\n"
168*90c8c64dSAndroid Build Coastguard Worker                "  -m <MTU> for the maximum transmission unit\n"
169*90c8c64dSAndroid Build Coastguard Worker                "  -a <address> <prefix-length> for the private address\n"
170*90c8c64dSAndroid Build Coastguard Worker                "  -r <address> <prefix-length> for the forwarding route\n"
171*90c8c64dSAndroid Build Coastguard Worker                "  -d <address> for the domain name server\n"
172*90c8c64dSAndroid Build Coastguard Worker                "  -s <domain> for the search domain\n"
173*90c8c64dSAndroid Build Coastguard Worker                "\n"
174*90c8c64dSAndroid Build Coastguard Worker                "Note that TUN interface needs to be configured properly\n"
175*90c8c64dSAndroid Build Coastguard Worker                "BEFORE running this program. For more information, please\n"
176*90c8c64dSAndroid Build Coastguard Worker                "read the comments in the source code.\n\n", argv[0]);
177*90c8c64dSAndroid Build Coastguard Worker         exit(1);
178*90c8c64dSAndroid Build Coastguard Worker     }
179*90c8c64dSAndroid Build Coastguard Worker 
180*90c8c64dSAndroid Build Coastguard Worker     // Parse the arguments and set the parameters.
181*90c8c64dSAndroid Build Coastguard Worker     char parameters[1024];
182*90c8c64dSAndroid Build Coastguard Worker     build_parameters(parameters, sizeof(parameters), argc, argv);
183*90c8c64dSAndroid Build Coastguard Worker 
184*90c8c64dSAndroid Build Coastguard Worker     // Get TUN interface.
185*90c8c64dSAndroid Build Coastguard Worker     int interface = get_interface(argv[1]);
186*90c8c64dSAndroid Build Coastguard Worker 
187*90c8c64dSAndroid Build Coastguard Worker     // Wait for a tunnel.
188*90c8c64dSAndroid Build Coastguard Worker     int tunnel;
189*90c8c64dSAndroid Build Coastguard Worker     while ((tunnel = get_tunnel(argv[2], argv[3])) != -1) {
190*90c8c64dSAndroid Build Coastguard Worker         printf("%s: Here comes a new tunnel\n", argv[1]);
191*90c8c64dSAndroid Build Coastguard Worker 
192*90c8c64dSAndroid Build Coastguard Worker         // On UN*X, there are many ways to deal with multiple file
193*90c8c64dSAndroid Build Coastguard Worker         // descriptors, such as poll(2), select(2), epoll(7) on Linux,
194*90c8c64dSAndroid Build Coastguard Worker         // kqueue(2) on FreeBSD, pthread(3), or even fork(2). Here we
195*90c8c64dSAndroid Build Coastguard Worker         // mimic everything from the client, so their source code can
196*90c8c64dSAndroid Build Coastguard Worker         // be easily compared side by side.
197*90c8c64dSAndroid Build Coastguard Worker 
198*90c8c64dSAndroid Build Coastguard Worker         // Put the tunnel into non-blocking mode.
199*90c8c64dSAndroid Build Coastguard Worker         fcntl(tunnel, F_SETFL, O_NONBLOCK);
200*90c8c64dSAndroid Build Coastguard Worker 
201*90c8c64dSAndroid Build Coastguard Worker         // Send the parameters several times in case of packet loss.
202*90c8c64dSAndroid Build Coastguard Worker         for (int i = 0; i < 3; ++i) {
203*90c8c64dSAndroid Build Coastguard Worker             send(tunnel, parameters, sizeof(parameters), MSG_NOSIGNAL);
204*90c8c64dSAndroid Build Coastguard Worker         }
205*90c8c64dSAndroid Build Coastguard Worker 
206*90c8c64dSAndroid Build Coastguard Worker         // Allocate the buffer for a single packet.
207*90c8c64dSAndroid Build Coastguard Worker         char packet[32767];
208*90c8c64dSAndroid Build Coastguard Worker 
209*90c8c64dSAndroid Build Coastguard Worker         // We use a timer to determine the status of the tunnel. It
210*90c8c64dSAndroid Build Coastguard Worker         // works on both sides. A positive value means sending, and
211*90c8c64dSAndroid Build Coastguard Worker         // any other means receiving. We start with receiving.
212*90c8c64dSAndroid Build Coastguard Worker         int timer = 0;
213*90c8c64dSAndroid Build Coastguard Worker 
214*90c8c64dSAndroid Build Coastguard Worker         // We keep forwarding packets till something goes wrong.
215*90c8c64dSAndroid Build Coastguard Worker         while (true) {
216*90c8c64dSAndroid Build Coastguard Worker             // Assume that we did not make any progress in this iteration.
217*90c8c64dSAndroid Build Coastguard Worker             bool idle = true;
218*90c8c64dSAndroid Build Coastguard Worker 
219*90c8c64dSAndroid Build Coastguard Worker             // Read the outgoing packet from the input stream.
220*90c8c64dSAndroid Build Coastguard Worker             int length = read(interface, packet, sizeof(packet));
221*90c8c64dSAndroid Build Coastguard Worker             if (length > 0) {
222*90c8c64dSAndroid Build Coastguard Worker                 // Write the outgoing packet to the tunnel.
223*90c8c64dSAndroid Build Coastguard Worker                 send(tunnel, packet, length, MSG_NOSIGNAL);
224*90c8c64dSAndroid Build Coastguard Worker 
225*90c8c64dSAndroid Build Coastguard Worker                 // There might be more outgoing packets.
226*90c8c64dSAndroid Build Coastguard Worker                 idle = false;
227*90c8c64dSAndroid Build Coastguard Worker 
228*90c8c64dSAndroid Build Coastguard Worker                 // If we were receiving, switch to sending.
229*90c8c64dSAndroid Build Coastguard Worker                 if (timer < 1) {
230*90c8c64dSAndroid Build Coastguard Worker                     timer = 1;
231*90c8c64dSAndroid Build Coastguard Worker                 }
232*90c8c64dSAndroid Build Coastguard Worker             }
233*90c8c64dSAndroid Build Coastguard Worker 
234*90c8c64dSAndroid Build Coastguard Worker             // Read the incoming packet from the tunnel.
235*90c8c64dSAndroid Build Coastguard Worker             length = recv(tunnel, packet, sizeof(packet), 0);
236*90c8c64dSAndroid Build Coastguard Worker             if (length == 0) {
237*90c8c64dSAndroid Build Coastguard Worker                 break;
238*90c8c64dSAndroid Build Coastguard Worker             }
239*90c8c64dSAndroid Build Coastguard Worker             if (length > 0) {
240*90c8c64dSAndroid Build Coastguard Worker                 // Ignore control messages, which start with zero.
241*90c8c64dSAndroid Build Coastguard Worker                 if (packet[0] != 0) {
242*90c8c64dSAndroid Build Coastguard Worker                     // Write the incoming packet to the output stream.
243*90c8c64dSAndroid Build Coastguard Worker                     write(interface, packet, length);
244*90c8c64dSAndroid Build Coastguard Worker                 }
245*90c8c64dSAndroid Build Coastguard Worker 
246*90c8c64dSAndroid Build Coastguard Worker                 // There might be more incoming packets.
247*90c8c64dSAndroid Build Coastguard Worker                 idle = false;
248*90c8c64dSAndroid Build Coastguard Worker 
249*90c8c64dSAndroid Build Coastguard Worker                 // If we were sending, switch to receiving.
250*90c8c64dSAndroid Build Coastguard Worker                 if (timer > 0) {
251*90c8c64dSAndroid Build Coastguard Worker                     timer = 0;
252*90c8c64dSAndroid Build Coastguard Worker                 }
253*90c8c64dSAndroid Build Coastguard Worker             }
254*90c8c64dSAndroid Build Coastguard Worker 
255*90c8c64dSAndroid Build Coastguard Worker             // If we are idle or waiting for the network, sleep for a
256*90c8c64dSAndroid Build Coastguard Worker             // fraction of time to avoid busy looping.
257*90c8c64dSAndroid Build Coastguard Worker             if (idle) {
258*90c8c64dSAndroid Build Coastguard Worker                 usleep(100000);
259*90c8c64dSAndroid Build Coastguard Worker 
260*90c8c64dSAndroid Build Coastguard Worker                 // Increase the timer. This is inaccurate but good enough,
261*90c8c64dSAndroid Build Coastguard Worker                 // since everything is operated in non-blocking mode.
262*90c8c64dSAndroid Build Coastguard Worker                 timer += (timer > 0) ? 100 : -100;
263*90c8c64dSAndroid Build Coastguard Worker 
264*90c8c64dSAndroid Build Coastguard Worker                 // We are receiving for a long time but not sending.
265*90c8c64dSAndroid Build Coastguard Worker                 // Can you figure out why we use a different value? :)
266*90c8c64dSAndroid Build Coastguard Worker                 if (timer < -16000) {
267*90c8c64dSAndroid Build Coastguard Worker                     // Send empty control messages.
268*90c8c64dSAndroid Build Coastguard Worker                     packet[0] = 0;
269*90c8c64dSAndroid Build Coastguard Worker                     for (int i = 0; i < 3; ++i) {
270*90c8c64dSAndroid Build Coastguard Worker                         send(tunnel, packet, 1, MSG_NOSIGNAL);
271*90c8c64dSAndroid Build Coastguard Worker                     }
272*90c8c64dSAndroid Build Coastguard Worker 
273*90c8c64dSAndroid Build Coastguard Worker                     // Switch to sending.
274*90c8c64dSAndroid Build Coastguard Worker                     timer = 1;
275*90c8c64dSAndroid Build Coastguard Worker                 }
276*90c8c64dSAndroid Build Coastguard Worker 
277*90c8c64dSAndroid Build Coastguard Worker                 // We are sending for a long time but not receiving.
278*90c8c64dSAndroid Build Coastguard Worker                 if (timer > 20000) {
279*90c8c64dSAndroid Build Coastguard Worker                     break;
280*90c8c64dSAndroid Build Coastguard Worker                 }
281*90c8c64dSAndroid Build Coastguard Worker             }
282*90c8c64dSAndroid Build Coastguard Worker         }
283*90c8c64dSAndroid Build Coastguard Worker         printf("%s: The tunnel is broken\n", argv[1]);
284*90c8c64dSAndroid Build Coastguard Worker         close(tunnel);
285*90c8c64dSAndroid Build Coastguard Worker     }
286*90c8c64dSAndroid Build Coastguard Worker     perror("Cannot create tunnels");
287*90c8c64dSAndroid Build Coastguard Worker     exit(1);
288*90c8c64dSAndroid Build Coastguard Worker }
289