xref: /aosp_15_r20/external/curl/tests/server/socksd.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "server_setup.h"
25*6236dae4SAndroid Build Coastguard Worker #include <stdlib.h>
26*6236dae4SAndroid Build Coastguard Worker 
27*6236dae4SAndroid Build Coastguard Worker /* Function
28*6236dae4SAndroid Build Coastguard Worker  *
29*6236dae4SAndroid Build Coastguard Worker  * Accepts a TCP connection on a custom port (IPv4 or IPv6). Connects to a
30*6236dae4SAndroid Build Coastguard Worker  * given addr + port backend (that is NOT extracted form the client's
31*6236dae4SAndroid Build Coastguard Worker  * request). The backend server default to connect to can be set with
32*6236dae4SAndroid Build Coastguard Worker  * --backend and --backendport.
33*6236dae4SAndroid Build Coastguard Worker  *
34*6236dae4SAndroid Build Coastguard Worker  * Read commands from FILE (set with --config). The commands control how to
35*6236dae4SAndroid Build Coastguard Worker  * act and is reset to defaults each client TCP connect.
36*6236dae4SAndroid Build Coastguard Worker  *
37*6236dae4SAndroid Build Coastguard Worker  * Config file keywords:
38*6236dae4SAndroid Build Coastguard Worker  *
39*6236dae4SAndroid Build Coastguard Worker  * "version [number: 5]" - requires the communication to use this version.
40*6236dae4SAndroid Build Coastguard Worker  * "nmethods_min [number: 1]" - the minimum numberf NMETHODS the client must
41*6236dae4SAndroid Build Coastguard Worker  *                              state
42*6236dae4SAndroid Build Coastguard Worker  * "nmethods_max [number: 3]" - the minimum numberf NMETHODS the client must
43*6236dae4SAndroid Build Coastguard Worker  *                              state
44*6236dae4SAndroid Build Coastguard Worker  * "user [string]" - the user name that must match (if method is 2)
45*6236dae4SAndroid Build Coastguard Worker  * "password [string]" - the password that must match (if method is 2)
46*6236dae4SAndroid Build Coastguard Worker  * "backend [IPv4]" - numerical IPv4 address of backend to connect to
47*6236dae4SAndroid Build Coastguard Worker  * "backendport [number:0]" - TCP port of backend to connect to. 0 means use
48*6236dae4SAndroid Build Coastguard Worker                               the client's specified port number.
49*6236dae4SAndroid Build Coastguard Worker  * "method [number: 0]" - connect method to respond with:
50*6236dae4SAndroid Build Coastguard Worker  *                        0 - no auth
51*6236dae4SAndroid Build Coastguard Worker  *                        1 - GSSAPI (not supported)
52*6236dae4SAndroid Build Coastguard Worker  *                        2 - user + password
53*6236dae4SAndroid Build Coastguard Worker  * "response [number]" - the decimal number to respond to a connect
54*6236dae4SAndroid Build Coastguard Worker  *                       SOCKS5: 0 is OK, SOCKS4: 90 is ok
55*6236dae4SAndroid Build Coastguard Worker  *
56*6236dae4SAndroid Build Coastguard Worker  */
57*6236dae4SAndroid Build Coastguard Worker 
58*6236dae4SAndroid Build Coastguard Worker /* based on sockfilt.c */
59*6236dae4SAndroid Build Coastguard Worker 
60*6236dae4SAndroid Build Coastguard Worker #include <signal.h>
61*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
62*6236dae4SAndroid Build Coastguard Worker #include <netinet/in.h>
63*6236dae4SAndroid Build Coastguard Worker #endif
64*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN6_H
65*6236dae4SAndroid Build Coastguard Worker #include <netinet/in6.h>
66*6236dae4SAndroid Build Coastguard Worker #endif
67*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
68*6236dae4SAndroid Build Coastguard Worker #include <arpa/inet.h>
69*6236dae4SAndroid Build Coastguard Worker #endif
70*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
71*6236dae4SAndroid Build Coastguard Worker #include <netdb.h>
72*6236dae4SAndroid Build Coastguard Worker #endif
73*6236dae4SAndroid Build Coastguard Worker 
74*6236dae4SAndroid Build Coastguard Worker #include "curlx.h" /* from the private lib dir */
75*6236dae4SAndroid Build Coastguard Worker #include "getpart.h"
76*6236dae4SAndroid Build Coastguard Worker #include "inet_pton.h"
77*6236dae4SAndroid Build Coastguard Worker #include "util.h"
78*6236dae4SAndroid Build Coastguard Worker #include "server_sockaddr.h"
79*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
80*6236dae4SAndroid Build Coastguard Worker 
81*6236dae4SAndroid Build Coastguard Worker /* include memdebug.h last */
82*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
83*6236dae4SAndroid Build Coastguard Worker 
84*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
85*6236dae4SAndroid Build Coastguard Worker #undef  EINTR
86*6236dae4SAndroid Build Coastguard Worker #define EINTR    4 /* errno.h value */
87*6236dae4SAndroid Build Coastguard Worker #undef  EAGAIN
88*6236dae4SAndroid Build Coastguard Worker #define EAGAIN  11 /* errno.h value */
89*6236dae4SAndroid Build Coastguard Worker #undef  ENOMEM
90*6236dae4SAndroid Build Coastguard Worker #define ENOMEM  12 /* errno.h value */
91*6236dae4SAndroid Build Coastguard Worker #undef  EINVAL
92*6236dae4SAndroid Build Coastguard Worker #define EINVAL  22 /* errno.h value */
93*6236dae4SAndroid Build Coastguard Worker #endif
94*6236dae4SAndroid Build Coastguard Worker 
95*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_PORT 8905
96*6236dae4SAndroid Build Coastguard Worker 
97*6236dae4SAndroid Build Coastguard Worker #ifndef DEFAULT_LOGFILE
98*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_LOGFILE "log/socksd.log"
99*6236dae4SAndroid Build Coastguard Worker #endif
100*6236dae4SAndroid Build Coastguard Worker 
101*6236dae4SAndroid Build Coastguard Worker #ifndef DEFAULT_REQFILE
102*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_REQFILE "log/socksd-request.log"
103*6236dae4SAndroid Build Coastguard Worker #endif
104*6236dae4SAndroid Build Coastguard Worker 
105*6236dae4SAndroid Build Coastguard Worker #ifndef DEFAULT_CONFIG
106*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_CONFIG "socksd.config"
107*6236dae4SAndroid Build Coastguard Worker #endif
108*6236dae4SAndroid Build Coastguard Worker 
109*6236dae4SAndroid Build Coastguard Worker static const char *backendaddr = "127.0.0.1";
110*6236dae4SAndroid Build Coastguard Worker static unsigned short backendport = 0; /* default is use client's */
111*6236dae4SAndroid Build Coastguard Worker 
112*6236dae4SAndroid Build Coastguard Worker struct configurable {
113*6236dae4SAndroid Build Coastguard Worker   unsigned char version; /* initial version byte in the request must match
114*6236dae4SAndroid Build Coastguard Worker                             this */
115*6236dae4SAndroid Build Coastguard Worker   unsigned char nmethods_min; /* minimum number of nmethods to expect */
116*6236dae4SAndroid Build Coastguard Worker   unsigned char nmethods_max; /* maximum number of nmethods to expect */
117*6236dae4SAndroid Build Coastguard Worker   unsigned char responseversion;
118*6236dae4SAndroid Build Coastguard Worker   unsigned char responsemethod;
119*6236dae4SAndroid Build Coastguard Worker   unsigned char reqcmd;
120*6236dae4SAndroid Build Coastguard Worker   unsigned char connectrep;
121*6236dae4SAndroid Build Coastguard Worker   unsigned short port; /* backend port */
122*6236dae4SAndroid Build Coastguard Worker   char addr[32]; /* backend IPv4 numerical */
123*6236dae4SAndroid Build Coastguard Worker   char user[256];
124*6236dae4SAndroid Build Coastguard Worker   char password[256];
125*6236dae4SAndroid Build Coastguard Worker };
126*6236dae4SAndroid Build Coastguard Worker 
127*6236dae4SAndroid Build Coastguard Worker #define CONFIG_VERSION 5
128*6236dae4SAndroid Build Coastguard Worker #define CONFIG_NMETHODS_MIN 1 /* unauth, gssapi, auth */
129*6236dae4SAndroid Build Coastguard Worker #define CONFIG_NMETHODS_MAX 3
130*6236dae4SAndroid Build Coastguard Worker #define CONFIG_RESPONSEVERSION CONFIG_VERSION
131*6236dae4SAndroid Build Coastguard Worker #define CONFIG_RESPONSEMETHOD 0 /* no auth */
132*6236dae4SAndroid Build Coastguard Worker #define CONFIG_REQCMD 1 /* CONNECT */
133*6236dae4SAndroid Build Coastguard Worker #define CONFIG_PORT backendport
134*6236dae4SAndroid Build Coastguard Worker #define CONFIG_ADDR backendaddr
135*6236dae4SAndroid Build Coastguard Worker #define CONFIG_CONNECTREP 0
136*6236dae4SAndroid Build Coastguard Worker 
137*6236dae4SAndroid Build Coastguard Worker static struct configurable config;
138*6236dae4SAndroid Build Coastguard Worker 
139*6236dae4SAndroid Build Coastguard Worker const char *serverlogfile = DEFAULT_LOGFILE;
140*6236dae4SAndroid Build Coastguard Worker static const char *reqlogfile = DEFAULT_REQFILE;
141*6236dae4SAndroid Build Coastguard Worker static const char *configfile = DEFAULT_CONFIG;
142*6236dae4SAndroid Build Coastguard Worker 
143*6236dae4SAndroid Build Coastguard Worker static const char *socket_type = "IPv4";
144*6236dae4SAndroid Build Coastguard Worker static unsigned short port = DEFAULT_PORT;
145*6236dae4SAndroid Build Coastguard Worker 
resetdefaults(void)146*6236dae4SAndroid Build Coastguard Worker static void resetdefaults(void)
147*6236dae4SAndroid Build Coastguard Worker {
148*6236dae4SAndroid Build Coastguard Worker   logmsg("Reset to defaults");
149*6236dae4SAndroid Build Coastguard Worker   config.version = CONFIG_VERSION;
150*6236dae4SAndroid Build Coastguard Worker   config.nmethods_min = CONFIG_NMETHODS_MIN;
151*6236dae4SAndroid Build Coastguard Worker   config.nmethods_max = CONFIG_NMETHODS_MAX;
152*6236dae4SAndroid Build Coastguard Worker   config.responseversion = CONFIG_RESPONSEVERSION;
153*6236dae4SAndroid Build Coastguard Worker   config.responsemethod = CONFIG_RESPONSEMETHOD;
154*6236dae4SAndroid Build Coastguard Worker   config.reqcmd = CONFIG_REQCMD;
155*6236dae4SAndroid Build Coastguard Worker   config.connectrep = CONFIG_CONNECTREP;
156*6236dae4SAndroid Build Coastguard Worker   config.port = CONFIG_PORT;
157*6236dae4SAndroid Build Coastguard Worker   strcpy(config.addr, CONFIG_ADDR);
158*6236dae4SAndroid Build Coastguard Worker   strcpy(config.user, "user");
159*6236dae4SAndroid Build Coastguard Worker   strcpy(config.password, "password");
160*6236dae4SAndroid Build Coastguard Worker }
161*6236dae4SAndroid Build Coastguard Worker 
byteval(char * value)162*6236dae4SAndroid Build Coastguard Worker static unsigned char byteval(char *value)
163*6236dae4SAndroid Build Coastguard Worker {
164*6236dae4SAndroid Build Coastguard Worker   unsigned long num = strtoul(value, NULL, 10);
165*6236dae4SAndroid Build Coastguard Worker   return num & 0xff;
166*6236dae4SAndroid Build Coastguard Worker }
167*6236dae4SAndroid Build Coastguard Worker 
shortval(char * value)168*6236dae4SAndroid Build Coastguard Worker static unsigned short shortval(char *value)
169*6236dae4SAndroid Build Coastguard Worker {
170*6236dae4SAndroid Build Coastguard Worker   unsigned long num = strtoul(value, NULL, 10);
171*6236dae4SAndroid Build Coastguard Worker   return num & 0xffff;
172*6236dae4SAndroid Build Coastguard Worker }
173*6236dae4SAndroid Build Coastguard Worker 
174*6236dae4SAndroid Build Coastguard Worker static enum {
175*6236dae4SAndroid Build Coastguard Worker   socket_domain_inet = AF_INET
176*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
177*6236dae4SAndroid Build Coastguard Worker   , socket_domain_inet6 = AF_INET6
178*6236dae4SAndroid Build Coastguard Worker #endif
179*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
180*6236dae4SAndroid Build Coastguard Worker   , socket_domain_unix = AF_UNIX
181*6236dae4SAndroid Build Coastguard Worker #endif
182*6236dae4SAndroid Build Coastguard Worker } socket_domain = AF_INET;
183*6236dae4SAndroid Build Coastguard Worker 
getconfig(void)184*6236dae4SAndroid Build Coastguard Worker static void getconfig(void)
185*6236dae4SAndroid Build Coastguard Worker {
186*6236dae4SAndroid Build Coastguard Worker   FILE *fp = fopen(configfile, FOPEN_READTEXT);
187*6236dae4SAndroid Build Coastguard Worker   resetdefaults();
188*6236dae4SAndroid Build Coastguard Worker   if(fp) {
189*6236dae4SAndroid Build Coastguard Worker     char buffer[512];
190*6236dae4SAndroid Build Coastguard Worker     logmsg("parse config file");
191*6236dae4SAndroid Build Coastguard Worker     while(fgets(buffer, sizeof(buffer), fp)) {
192*6236dae4SAndroid Build Coastguard Worker       char key[32];
193*6236dae4SAndroid Build Coastguard Worker       char value[260];
194*6236dae4SAndroid Build Coastguard Worker       if(2 == sscanf(buffer, "%31s %259s", key, value)) {
195*6236dae4SAndroid Build Coastguard Worker         if(!strcmp(key, "version")) {
196*6236dae4SAndroid Build Coastguard Worker           config.version = byteval(value);
197*6236dae4SAndroid Build Coastguard Worker           logmsg("version [%d] set", config.version);
198*6236dae4SAndroid Build Coastguard Worker         }
199*6236dae4SAndroid Build Coastguard Worker         else if(!strcmp(key, "nmethods_min")) {
200*6236dae4SAndroid Build Coastguard Worker           config.nmethods_min = byteval(value);
201*6236dae4SAndroid Build Coastguard Worker           logmsg("nmethods_min [%d] set", config.nmethods_min);
202*6236dae4SAndroid Build Coastguard Worker         }
203*6236dae4SAndroid Build Coastguard Worker         else if(!strcmp(key, "nmethods_max")) {
204*6236dae4SAndroid Build Coastguard Worker           config.nmethods_max = byteval(value);
205*6236dae4SAndroid Build Coastguard Worker           logmsg("nmethods_max [%d] set", config.nmethods_max);
206*6236dae4SAndroid Build Coastguard Worker         }
207*6236dae4SAndroid Build Coastguard Worker         else if(!strcmp(key, "backend")) {
208*6236dae4SAndroid Build Coastguard Worker           strcpy(config.addr, value);
209*6236dae4SAndroid Build Coastguard Worker           logmsg("backend [%s] set", config.addr);
210*6236dae4SAndroid Build Coastguard Worker         }
211*6236dae4SAndroid Build Coastguard Worker         else if(!strcmp(key, "backendport")) {
212*6236dae4SAndroid Build Coastguard Worker           config.port = shortval(value);
213*6236dae4SAndroid Build Coastguard Worker           logmsg("backendport [%d] set", config.port);
214*6236dae4SAndroid Build Coastguard Worker         }
215*6236dae4SAndroid Build Coastguard Worker         else if(!strcmp(key, "user")) {
216*6236dae4SAndroid Build Coastguard Worker           strcpy(config.user, value);
217*6236dae4SAndroid Build Coastguard Worker           logmsg("user [%s] set", config.user);
218*6236dae4SAndroid Build Coastguard Worker         }
219*6236dae4SAndroid Build Coastguard Worker         else if(!strcmp(key, "password")) {
220*6236dae4SAndroid Build Coastguard Worker           strcpy(config.password, value);
221*6236dae4SAndroid Build Coastguard Worker           logmsg("password [%s] set", config.password);
222*6236dae4SAndroid Build Coastguard Worker         }
223*6236dae4SAndroid Build Coastguard Worker         /* Methods:
224*6236dae4SAndroid Build Coastguard Worker            o  X'00' NO AUTHENTICATION REQUIRED
225*6236dae4SAndroid Build Coastguard Worker            o  X'01' GSSAPI
226*6236dae4SAndroid Build Coastguard Worker            o  X'02' USERNAME/PASSWORD
227*6236dae4SAndroid Build Coastguard Worker         */
228*6236dae4SAndroid Build Coastguard Worker         else if(!strcmp(key, "method")) {
229*6236dae4SAndroid Build Coastguard Worker           config.responsemethod = byteval(value);
230*6236dae4SAndroid Build Coastguard Worker           logmsg("method [%d] set", config.responsemethod);
231*6236dae4SAndroid Build Coastguard Worker         }
232*6236dae4SAndroid Build Coastguard Worker         else if(!strcmp(key, "response")) {
233*6236dae4SAndroid Build Coastguard Worker           config.connectrep = byteval(value);
234*6236dae4SAndroid Build Coastguard Worker           logmsg("response [%d] set", config.connectrep);
235*6236dae4SAndroid Build Coastguard Worker         }
236*6236dae4SAndroid Build Coastguard Worker       }
237*6236dae4SAndroid Build Coastguard Worker     }
238*6236dae4SAndroid Build Coastguard Worker     fclose(fp);
239*6236dae4SAndroid Build Coastguard Worker   }
240*6236dae4SAndroid Build Coastguard Worker }
241*6236dae4SAndroid Build Coastguard Worker 
loghex(unsigned char * buffer,ssize_t len)242*6236dae4SAndroid Build Coastguard Worker static void loghex(unsigned char *buffer, ssize_t len)
243*6236dae4SAndroid Build Coastguard Worker {
244*6236dae4SAndroid Build Coastguard Worker   char data[1200];
245*6236dae4SAndroid Build Coastguard Worker   ssize_t i;
246*6236dae4SAndroid Build Coastguard Worker   unsigned char *ptr = buffer;
247*6236dae4SAndroid Build Coastguard Worker   char *optr = data;
248*6236dae4SAndroid Build Coastguard Worker   ssize_t width = 0;
249*6236dae4SAndroid Build Coastguard Worker   int left = sizeof(data);
250*6236dae4SAndroid Build Coastguard Worker 
251*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < len && (left >= 0); i++) {
252*6236dae4SAndroid Build Coastguard Worker     msnprintf(optr, left, "%02x", ptr[i]);
253*6236dae4SAndroid Build Coastguard Worker     width += 2;
254*6236dae4SAndroid Build Coastguard Worker     optr += 2;
255*6236dae4SAndroid Build Coastguard Worker     left -= 2;
256*6236dae4SAndroid Build Coastguard Worker   }
257*6236dae4SAndroid Build Coastguard Worker   if(width)
258*6236dae4SAndroid Build Coastguard Worker     logmsg("'%s'", data);
259*6236dae4SAndroid Build Coastguard Worker }
260*6236dae4SAndroid Build Coastguard Worker 
261*6236dae4SAndroid Build Coastguard Worker /* RFC 1928, SOCKS5 byte index */
262*6236dae4SAndroid Build Coastguard Worker #define SOCKS5_VERSION 0
263*6236dae4SAndroid Build Coastguard Worker #define SOCKS5_NMETHODS 1 /* number of methods that is listed */
264*6236dae4SAndroid Build Coastguard Worker 
265*6236dae4SAndroid Build Coastguard Worker /* in the request: */
266*6236dae4SAndroid Build Coastguard Worker #define SOCKS5_REQCMD 1
267*6236dae4SAndroid Build Coastguard Worker #define SOCKS5_RESERVED 2
268*6236dae4SAndroid Build Coastguard Worker #define SOCKS5_ATYP 3
269*6236dae4SAndroid Build Coastguard Worker #define SOCKS5_DSTADDR 4
270*6236dae4SAndroid Build Coastguard Worker 
271*6236dae4SAndroid Build Coastguard Worker /* connect response */
272*6236dae4SAndroid Build Coastguard Worker #define SOCKS5_REP 1
273*6236dae4SAndroid Build Coastguard Worker #define SOCKS5_BNDADDR 4
274*6236dae4SAndroid Build Coastguard Worker 
275*6236dae4SAndroid Build Coastguard Worker /* auth request */
276*6236dae4SAndroid Build Coastguard Worker #define SOCKS5_ULEN 1
277*6236dae4SAndroid Build Coastguard Worker #define SOCKS5_UNAME 2
278*6236dae4SAndroid Build Coastguard Worker 
279*6236dae4SAndroid Build Coastguard Worker #define SOCKS4_CD 1
280*6236dae4SAndroid Build Coastguard Worker #define SOCKS4_DSTPORT 2
281*6236dae4SAndroid Build Coastguard Worker 
282*6236dae4SAndroid Build Coastguard Worker /* connect to a given IPv4 address, not the one asked for */
socksconnect(unsigned short connectport,const char * connectaddr)283*6236dae4SAndroid Build Coastguard Worker static curl_socket_t socksconnect(unsigned short connectport,
284*6236dae4SAndroid Build Coastguard Worker                                   const char *connectaddr)
285*6236dae4SAndroid Build Coastguard Worker {
286*6236dae4SAndroid Build Coastguard Worker   int rc;
287*6236dae4SAndroid Build Coastguard Worker   srvr_sockaddr_union_t me;
288*6236dae4SAndroid Build Coastguard Worker   curl_socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
289*6236dae4SAndroid Build Coastguard Worker   if(sock == CURL_SOCKET_BAD)
290*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
291*6236dae4SAndroid Build Coastguard Worker   memset(&me.sa4, 0, sizeof(me.sa4));
292*6236dae4SAndroid Build Coastguard Worker   me.sa4.sin_family = AF_INET;
293*6236dae4SAndroid Build Coastguard Worker   me.sa4.sin_port = htons(connectport);
294*6236dae4SAndroid Build Coastguard Worker   me.sa4.sin_addr.s_addr = INADDR_ANY;
295*6236dae4SAndroid Build Coastguard Worker   Curl_inet_pton(AF_INET, connectaddr, &me.sa4.sin_addr);
296*6236dae4SAndroid Build Coastguard Worker 
297*6236dae4SAndroid Build Coastguard Worker   rc = connect(sock, &me.sa, sizeof(me.sa4));
298*6236dae4SAndroid Build Coastguard Worker 
299*6236dae4SAndroid Build Coastguard Worker   if(rc) {
300*6236dae4SAndroid Build Coastguard Worker     int error = SOCKERRNO;
301*6236dae4SAndroid Build Coastguard Worker     logmsg("Error connecting to %s:%hu: (%d) %s",
302*6236dae4SAndroid Build Coastguard Worker            connectaddr, connectport, error, sstrerror(error));
303*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
304*6236dae4SAndroid Build Coastguard Worker   }
305*6236dae4SAndroid Build Coastguard Worker   logmsg("Connected fine to %s:%d", connectaddr, connectport);
306*6236dae4SAndroid Build Coastguard Worker   return sock;
307*6236dae4SAndroid Build Coastguard Worker }
308*6236dae4SAndroid Build Coastguard Worker 
socks4(curl_socket_t fd,unsigned char * buffer,ssize_t rc)309*6236dae4SAndroid Build Coastguard Worker static curl_socket_t socks4(curl_socket_t fd,
310*6236dae4SAndroid Build Coastguard Worker                             unsigned char *buffer,
311*6236dae4SAndroid Build Coastguard Worker                             ssize_t rc)
312*6236dae4SAndroid Build Coastguard Worker {
313*6236dae4SAndroid Build Coastguard Worker   unsigned char response[256 + 16];
314*6236dae4SAndroid Build Coastguard Worker   curl_socket_t connfd;
315*6236dae4SAndroid Build Coastguard Worker   unsigned char cd;
316*6236dae4SAndroid Build Coastguard Worker   unsigned short s4port;
317*6236dae4SAndroid Build Coastguard Worker 
318*6236dae4SAndroid Build Coastguard Worker   if(buffer[SOCKS4_CD] != 1) {
319*6236dae4SAndroid Build Coastguard Worker     logmsg("SOCKS4 CD is not 1: %d", buffer[SOCKS4_CD]);
320*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
321*6236dae4SAndroid Build Coastguard Worker   }
322*6236dae4SAndroid Build Coastguard Worker   if(rc < 9) {
323*6236dae4SAndroid Build Coastguard Worker     logmsg("SOCKS4 connect message too short: %zd", rc);
324*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
325*6236dae4SAndroid Build Coastguard Worker   }
326*6236dae4SAndroid Build Coastguard Worker   if(!config.port)
327*6236dae4SAndroid Build Coastguard Worker     s4port = (unsigned short)((buffer[SOCKS4_DSTPORT] << 8) |
328*6236dae4SAndroid Build Coastguard Worker                               (buffer[SOCKS4_DSTPORT + 1]));
329*6236dae4SAndroid Build Coastguard Worker   else
330*6236dae4SAndroid Build Coastguard Worker     s4port = config.port;
331*6236dae4SAndroid Build Coastguard Worker 
332*6236dae4SAndroid Build Coastguard Worker   connfd = socksconnect(s4port, config.addr);
333*6236dae4SAndroid Build Coastguard Worker   if(connfd == CURL_SOCKET_BAD) {
334*6236dae4SAndroid Build Coastguard Worker     /* failed */
335*6236dae4SAndroid Build Coastguard Worker     cd = 91;
336*6236dae4SAndroid Build Coastguard Worker   }
337*6236dae4SAndroid Build Coastguard Worker   else {
338*6236dae4SAndroid Build Coastguard Worker     /* success */
339*6236dae4SAndroid Build Coastguard Worker     cd = 90;
340*6236dae4SAndroid Build Coastguard Worker   }
341*6236dae4SAndroid Build Coastguard Worker   response[0] = 0; /* reply version 0 */
342*6236dae4SAndroid Build Coastguard Worker   response[1] = cd; /* result */
343*6236dae4SAndroid Build Coastguard Worker   /* copy port and address from connect request */
344*6236dae4SAndroid Build Coastguard Worker   memcpy(&response[2], &buffer[SOCKS4_DSTPORT], 6);
345*6236dae4SAndroid Build Coastguard Worker   rc = (send)(fd, (char *)response, 8, 0);
346*6236dae4SAndroid Build Coastguard Worker   if(rc != 8) {
347*6236dae4SAndroid Build Coastguard Worker     logmsg("Sending SOCKS4 response failed!");
348*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
349*6236dae4SAndroid Build Coastguard Worker   }
350*6236dae4SAndroid Build Coastguard Worker   logmsg("Sent %zd bytes", rc);
351*6236dae4SAndroid Build Coastguard Worker   loghex(response, rc);
352*6236dae4SAndroid Build Coastguard Worker 
353*6236dae4SAndroid Build Coastguard Worker   if(cd == 90)
354*6236dae4SAndroid Build Coastguard Worker     /* now do the transfer */
355*6236dae4SAndroid Build Coastguard Worker     return connfd;
356*6236dae4SAndroid Build Coastguard Worker 
357*6236dae4SAndroid Build Coastguard Worker   if(connfd != CURL_SOCKET_BAD)
358*6236dae4SAndroid Build Coastguard Worker     sclose(connfd);
359*6236dae4SAndroid Build Coastguard Worker 
360*6236dae4SAndroid Build Coastguard Worker   return CURL_SOCKET_BAD;
361*6236dae4SAndroid Build Coastguard Worker }
362*6236dae4SAndroid Build Coastguard Worker 
sockit(curl_socket_t fd)363*6236dae4SAndroid Build Coastguard Worker static curl_socket_t sockit(curl_socket_t fd)
364*6236dae4SAndroid Build Coastguard Worker {
365*6236dae4SAndroid Build Coastguard Worker   unsigned char buffer[2*256 + 16];
366*6236dae4SAndroid Build Coastguard Worker   unsigned char response[2*256 + 16];
367*6236dae4SAndroid Build Coastguard Worker   ssize_t rc;
368*6236dae4SAndroid Build Coastguard Worker   unsigned char len;
369*6236dae4SAndroid Build Coastguard Worker   unsigned char type;
370*6236dae4SAndroid Build Coastguard Worker   unsigned char rep = 0;
371*6236dae4SAndroid Build Coastguard Worker   unsigned char *address;
372*6236dae4SAndroid Build Coastguard Worker   unsigned short socksport;
373*6236dae4SAndroid Build Coastguard Worker   curl_socket_t connfd = CURL_SOCKET_BAD;
374*6236dae4SAndroid Build Coastguard Worker   unsigned short s5port;
375*6236dae4SAndroid Build Coastguard Worker 
376*6236dae4SAndroid Build Coastguard Worker   getconfig();
377*6236dae4SAndroid Build Coastguard Worker 
378*6236dae4SAndroid Build Coastguard Worker   rc = recv(fd, (char *)buffer, sizeof(buffer), 0);
379*6236dae4SAndroid Build Coastguard Worker   if(rc <= 0) {
380*6236dae4SAndroid Build Coastguard Worker     logmsg("SOCKS identifier message missing, recv returned %zd", rc);
381*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
382*6236dae4SAndroid Build Coastguard Worker   }
383*6236dae4SAndroid Build Coastguard Worker 
384*6236dae4SAndroid Build Coastguard Worker   logmsg("READ %zd bytes", rc);
385*6236dae4SAndroid Build Coastguard Worker   loghex(buffer, rc);
386*6236dae4SAndroid Build Coastguard Worker 
387*6236dae4SAndroid Build Coastguard Worker   if(buffer[SOCKS5_VERSION] == 4)
388*6236dae4SAndroid Build Coastguard Worker     return socks4(fd, buffer, rc);
389*6236dae4SAndroid Build Coastguard Worker 
390*6236dae4SAndroid Build Coastguard Worker   if(rc < 3) {
391*6236dae4SAndroid Build Coastguard Worker     logmsg("SOCKS5 identifier message too short: %zd", rc);
392*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
393*6236dae4SAndroid Build Coastguard Worker   }
394*6236dae4SAndroid Build Coastguard Worker 
395*6236dae4SAndroid Build Coastguard Worker   if(buffer[SOCKS5_VERSION] != config.version) {
396*6236dae4SAndroid Build Coastguard Worker     logmsg("VERSION byte not %d", config.version);
397*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
398*6236dae4SAndroid Build Coastguard Worker   }
399*6236dae4SAndroid Build Coastguard Worker   if((buffer[SOCKS5_NMETHODS] < config.nmethods_min) ||
400*6236dae4SAndroid Build Coastguard Worker      (buffer[SOCKS5_NMETHODS] > config.nmethods_max)) {
401*6236dae4SAndroid Build Coastguard Worker     logmsg("NMETHODS byte not within %d - %d ",
402*6236dae4SAndroid Build Coastguard Worker            config.nmethods_min, config.nmethods_max);
403*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
404*6236dae4SAndroid Build Coastguard Worker   }
405*6236dae4SAndroid Build Coastguard Worker   /* after NMETHODS follows that many bytes listing the methods the client
406*6236dae4SAndroid Build Coastguard Worker      says it supports */
407*6236dae4SAndroid Build Coastguard Worker   if(rc != (buffer[SOCKS5_NMETHODS] + 2)) {
408*6236dae4SAndroid Build Coastguard Worker     logmsg("Expected %d bytes, got %zd", buffer[SOCKS5_NMETHODS] + 2, rc);
409*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
410*6236dae4SAndroid Build Coastguard Worker   }
411*6236dae4SAndroid Build Coastguard Worker   logmsg("Incoming request deemed fine!");
412*6236dae4SAndroid Build Coastguard Worker 
413*6236dae4SAndroid Build Coastguard Worker   /* respond with two bytes: VERSION + METHOD */
414*6236dae4SAndroid Build Coastguard Worker   response[0] = config.responseversion;
415*6236dae4SAndroid Build Coastguard Worker   response[1] = config.responsemethod;
416*6236dae4SAndroid Build Coastguard Worker   rc = (send)(fd, (char *)response, 2, 0);
417*6236dae4SAndroid Build Coastguard Worker   if(rc != 2) {
418*6236dae4SAndroid Build Coastguard Worker     logmsg("Sending response failed!");
419*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
420*6236dae4SAndroid Build Coastguard Worker   }
421*6236dae4SAndroid Build Coastguard Worker   logmsg("Sent %zd bytes", rc);
422*6236dae4SAndroid Build Coastguard Worker   loghex(response, rc);
423*6236dae4SAndroid Build Coastguard Worker 
424*6236dae4SAndroid Build Coastguard Worker   /* expect the request or auth */
425*6236dae4SAndroid Build Coastguard Worker   rc = recv(fd, (char *)buffer, sizeof(buffer), 0);
426*6236dae4SAndroid Build Coastguard Worker   if(rc <= 0) {
427*6236dae4SAndroid Build Coastguard Worker     logmsg("SOCKS5 request or auth message missing, recv returned %zd", rc);
428*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
429*6236dae4SAndroid Build Coastguard Worker   }
430*6236dae4SAndroid Build Coastguard Worker 
431*6236dae4SAndroid Build Coastguard Worker   logmsg("READ %zd bytes", rc);
432*6236dae4SAndroid Build Coastguard Worker   loghex(buffer, rc);
433*6236dae4SAndroid Build Coastguard Worker 
434*6236dae4SAndroid Build Coastguard Worker   if(config.responsemethod == 2) {
435*6236dae4SAndroid Build Coastguard Worker     /* RFC 1929 authentication
436*6236dae4SAndroid Build Coastguard Worker        +----+------+----------+------+----------+
437*6236dae4SAndroid Build Coastguard Worker        |VER | ULEN |  UNAME   | PLEN |  PASSWD  |
438*6236dae4SAndroid Build Coastguard Worker        +----+------+----------+------+----------+
439*6236dae4SAndroid Build Coastguard Worker        | 1  |  1   | 1 to 255 |  1   | 1 to 255 |
440*6236dae4SAndroid Build Coastguard Worker        +----+------+----------+------+----------+
441*6236dae4SAndroid Build Coastguard Worker     */
442*6236dae4SAndroid Build Coastguard Worker     unsigned char ulen;
443*6236dae4SAndroid Build Coastguard Worker     unsigned char plen;
444*6236dae4SAndroid Build Coastguard Worker     bool login = TRUE;
445*6236dae4SAndroid Build Coastguard Worker     if(rc < 5) {
446*6236dae4SAndroid Build Coastguard Worker       logmsg("Too short auth input: %zd", rc);
447*6236dae4SAndroid Build Coastguard Worker       return CURL_SOCKET_BAD;
448*6236dae4SAndroid Build Coastguard Worker     }
449*6236dae4SAndroid Build Coastguard Worker     if(buffer[SOCKS5_VERSION] != 1) {
450*6236dae4SAndroid Build Coastguard Worker       logmsg("Auth VERSION byte not 1, got %d", buffer[SOCKS5_VERSION]);
451*6236dae4SAndroid Build Coastguard Worker       return CURL_SOCKET_BAD;
452*6236dae4SAndroid Build Coastguard Worker     }
453*6236dae4SAndroid Build Coastguard Worker     ulen = buffer[SOCKS5_ULEN];
454*6236dae4SAndroid Build Coastguard Worker     if(rc < 4 + ulen) {
455*6236dae4SAndroid Build Coastguard Worker       logmsg("Too short packet for username: %zd", rc);
456*6236dae4SAndroid Build Coastguard Worker       return CURL_SOCKET_BAD;
457*6236dae4SAndroid Build Coastguard Worker     }
458*6236dae4SAndroid Build Coastguard Worker     plen = buffer[SOCKS5_ULEN + ulen + 1];
459*6236dae4SAndroid Build Coastguard Worker     if(rc < 3 + ulen + plen) {
460*6236dae4SAndroid Build Coastguard Worker       logmsg("Too short packet for ulen %d plen %d: %zd", ulen, plen, rc);
461*6236dae4SAndroid Build Coastguard Worker       return CURL_SOCKET_BAD;
462*6236dae4SAndroid Build Coastguard Worker     }
463*6236dae4SAndroid Build Coastguard Worker     if((ulen != strlen(config.user)) ||
464*6236dae4SAndroid Build Coastguard Worker        (plen != strlen(config.password)) ||
465*6236dae4SAndroid Build Coastguard Worker        memcmp(&buffer[SOCKS5_UNAME], config.user, ulen) ||
466*6236dae4SAndroid Build Coastguard Worker        memcmp(&buffer[SOCKS5_UNAME + ulen + 1], config.password, plen)) {
467*6236dae4SAndroid Build Coastguard Worker       /* no match! */
468*6236dae4SAndroid Build Coastguard Worker       logmsg("mismatched credentials!");
469*6236dae4SAndroid Build Coastguard Worker       login = FALSE;
470*6236dae4SAndroid Build Coastguard Worker     }
471*6236dae4SAndroid Build Coastguard Worker     response[0] = 1;
472*6236dae4SAndroid Build Coastguard Worker     response[1] = login ? 0 : 1;
473*6236dae4SAndroid Build Coastguard Worker     rc = (send)(fd, (char *)response, 2, 0);
474*6236dae4SAndroid Build Coastguard Worker     if(rc != 2) {
475*6236dae4SAndroid Build Coastguard Worker       logmsg("Sending auth response failed!");
476*6236dae4SAndroid Build Coastguard Worker       return CURL_SOCKET_BAD;
477*6236dae4SAndroid Build Coastguard Worker     }
478*6236dae4SAndroid Build Coastguard Worker     logmsg("Sent %zd bytes", rc);
479*6236dae4SAndroid Build Coastguard Worker     loghex(response, rc);
480*6236dae4SAndroid Build Coastguard Worker     if(!login)
481*6236dae4SAndroid Build Coastguard Worker       return CURL_SOCKET_BAD;
482*6236dae4SAndroid Build Coastguard Worker 
483*6236dae4SAndroid Build Coastguard Worker     /* expect the request */
484*6236dae4SAndroid Build Coastguard Worker     rc = recv(fd, (char *)buffer, sizeof(buffer), 0);
485*6236dae4SAndroid Build Coastguard Worker     if(rc <= 0) {
486*6236dae4SAndroid Build Coastguard Worker       logmsg("SOCKS5 request message missing, recv returned %zd", rc);
487*6236dae4SAndroid Build Coastguard Worker       return CURL_SOCKET_BAD;
488*6236dae4SAndroid Build Coastguard Worker     }
489*6236dae4SAndroid Build Coastguard Worker 
490*6236dae4SAndroid Build Coastguard Worker     logmsg("READ %zd bytes", rc);
491*6236dae4SAndroid Build Coastguard Worker     loghex(buffer, rc);
492*6236dae4SAndroid Build Coastguard Worker   }
493*6236dae4SAndroid Build Coastguard Worker   if(rc < 6) {
494*6236dae4SAndroid Build Coastguard Worker     logmsg("Too short for request: %zd", rc);
495*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
496*6236dae4SAndroid Build Coastguard Worker   }
497*6236dae4SAndroid Build Coastguard Worker 
498*6236dae4SAndroid Build Coastguard Worker   if(buffer[SOCKS5_VERSION] != config.version) {
499*6236dae4SAndroid Build Coastguard Worker     logmsg("Request VERSION byte not %d", config.version);
500*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
501*6236dae4SAndroid Build Coastguard Worker   }
502*6236dae4SAndroid Build Coastguard Worker   /* 1 == CONNECT */
503*6236dae4SAndroid Build Coastguard Worker   if(buffer[SOCKS5_REQCMD] != config.reqcmd) {
504*6236dae4SAndroid Build Coastguard Worker     logmsg("Request COMMAND byte not %d", config.reqcmd);
505*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
506*6236dae4SAndroid Build Coastguard Worker   }
507*6236dae4SAndroid Build Coastguard Worker   /* reserved, should be zero */
508*6236dae4SAndroid Build Coastguard Worker   if(buffer[SOCKS5_RESERVED]) {
509*6236dae4SAndroid Build Coastguard Worker     logmsg("Request COMMAND byte not %d", config.reqcmd);
510*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
511*6236dae4SAndroid Build Coastguard Worker   }
512*6236dae4SAndroid Build Coastguard Worker   /* ATYP:
513*6236dae4SAndroid Build Coastguard Worker      o  IP V4 address: X'01'
514*6236dae4SAndroid Build Coastguard Worker      o  DOMAINNAME: X'03'
515*6236dae4SAndroid Build Coastguard Worker      o  IP V6 address: X'04'
516*6236dae4SAndroid Build Coastguard Worker   */
517*6236dae4SAndroid Build Coastguard Worker   type = buffer[SOCKS5_ATYP];
518*6236dae4SAndroid Build Coastguard Worker   address = &buffer[SOCKS5_DSTADDR];
519*6236dae4SAndroid Build Coastguard Worker   switch(type) {
520*6236dae4SAndroid Build Coastguard Worker   case 1:
521*6236dae4SAndroid Build Coastguard Worker     /* 4 bytes IPv4 address */
522*6236dae4SAndroid Build Coastguard Worker     len = 4;
523*6236dae4SAndroid Build Coastguard Worker     break;
524*6236dae4SAndroid Build Coastguard Worker   case 3:
525*6236dae4SAndroid Build Coastguard Worker     /* The first octet of the address field contains the number of octets of
526*6236dae4SAndroid Build Coastguard Worker        name that follow */
527*6236dae4SAndroid Build Coastguard Worker     len = buffer[SOCKS5_DSTADDR];
528*6236dae4SAndroid Build Coastguard Worker     len++;
529*6236dae4SAndroid Build Coastguard Worker     break;
530*6236dae4SAndroid Build Coastguard Worker   case 4:
531*6236dae4SAndroid Build Coastguard Worker     /* 16 bytes IPv6 address */
532*6236dae4SAndroid Build Coastguard Worker     len = 16;
533*6236dae4SAndroid Build Coastguard Worker     break;
534*6236dae4SAndroid Build Coastguard Worker   default:
535*6236dae4SAndroid Build Coastguard Worker     logmsg("Unknown ATYP %d", type);
536*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
537*6236dae4SAndroid Build Coastguard Worker   }
538*6236dae4SAndroid Build Coastguard Worker   if(rc < (4 + len + 2)) {
539*6236dae4SAndroid Build Coastguard Worker     logmsg("Request too short: %zd, expected %d", rc, 4 + len + 2);
540*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
541*6236dae4SAndroid Build Coastguard Worker   }
542*6236dae4SAndroid Build Coastguard Worker   logmsg("Received ATYP %d", type);
543*6236dae4SAndroid Build Coastguard Worker 
544*6236dae4SAndroid Build Coastguard Worker   {
545*6236dae4SAndroid Build Coastguard Worker     FILE *dump;
546*6236dae4SAndroid Build Coastguard Worker     dump = fopen(reqlogfile, "ab");
547*6236dae4SAndroid Build Coastguard Worker     if(dump) {
548*6236dae4SAndroid Build Coastguard Worker       int i;
549*6236dae4SAndroid Build Coastguard Worker       fprintf(dump, "atyp %u =>", type);
550*6236dae4SAndroid Build Coastguard Worker       switch(type) {
551*6236dae4SAndroid Build Coastguard Worker       case 1:
552*6236dae4SAndroid Build Coastguard Worker         /* 4 bytes IPv4 address */
553*6236dae4SAndroid Build Coastguard Worker         fprintf(dump, " %u.%u.%u.%u\n",
554*6236dae4SAndroid Build Coastguard Worker                 address[0], address[1], address[2], address[3]);
555*6236dae4SAndroid Build Coastguard Worker         break;
556*6236dae4SAndroid Build Coastguard Worker       case 3:
557*6236dae4SAndroid Build Coastguard Worker         /* The first octet of the address field contains the number of octets
558*6236dae4SAndroid Build Coastguard Worker            of name that follow */
559*6236dae4SAndroid Build Coastguard Worker         fprintf(dump, " %.*s\n", len-1, &address[1]);
560*6236dae4SAndroid Build Coastguard Worker         break;
561*6236dae4SAndroid Build Coastguard Worker       case 4:
562*6236dae4SAndroid Build Coastguard Worker         /* 16 bytes IPv6 address */
563*6236dae4SAndroid Build Coastguard Worker         for(i = 0; i < 16; i++) {
564*6236dae4SAndroid Build Coastguard Worker           fprintf(dump, " %02x", address[i]);
565*6236dae4SAndroid Build Coastguard Worker         }
566*6236dae4SAndroid Build Coastguard Worker         fprintf(dump, "\n");
567*6236dae4SAndroid Build Coastguard Worker         break;
568*6236dae4SAndroid Build Coastguard Worker       }
569*6236dae4SAndroid Build Coastguard Worker       fclose(dump);
570*6236dae4SAndroid Build Coastguard Worker     }
571*6236dae4SAndroid Build Coastguard Worker   }
572*6236dae4SAndroid Build Coastguard Worker 
573*6236dae4SAndroid Build Coastguard Worker   if(!config.port) {
574*6236dae4SAndroid Build Coastguard Worker     unsigned char *portp = &buffer[SOCKS5_DSTADDR + len];
575*6236dae4SAndroid Build Coastguard Worker     s5port = (unsigned short)((portp[0] << 8) | (portp[1]));
576*6236dae4SAndroid Build Coastguard Worker   }
577*6236dae4SAndroid Build Coastguard Worker   else
578*6236dae4SAndroid Build Coastguard Worker     s5port = config.port;
579*6236dae4SAndroid Build Coastguard Worker 
580*6236dae4SAndroid Build Coastguard Worker   if(!config.connectrep)
581*6236dae4SAndroid Build Coastguard Worker     connfd = socksconnect(s5port, config.addr);
582*6236dae4SAndroid Build Coastguard Worker 
583*6236dae4SAndroid Build Coastguard Worker   if(connfd == CURL_SOCKET_BAD) {
584*6236dae4SAndroid Build Coastguard Worker     /* failed */
585*6236dae4SAndroid Build Coastguard Worker     rep = 1;
586*6236dae4SAndroid Build Coastguard Worker   }
587*6236dae4SAndroid Build Coastguard Worker   else {
588*6236dae4SAndroid Build Coastguard Worker     rep = config.connectrep;
589*6236dae4SAndroid Build Coastguard Worker   }
590*6236dae4SAndroid Build Coastguard Worker 
591*6236dae4SAndroid Build Coastguard Worker   /* */
592*6236dae4SAndroid Build Coastguard Worker   response[SOCKS5_VERSION] = config.responseversion;
593*6236dae4SAndroid Build Coastguard Worker 
594*6236dae4SAndroid Build Coastguard Worker   /*
595*6236dae4SAndroid Build Coastguard Worker     o  REP    Reply field:
596*6236dae4SAndroid Build Coastguard Worker     o  X'00' succeeded
597*6236dae4SAndroid Build Coastguard Worker     o  X'01' general SOCKS server failure
598*6236dae4SAndroid Build Coastguard Worker     o  X'02' connection not allowed by ruleset
599*6236dae4SAndroid Build Coastguard Worker     o  X'03' Network unreachable
600*6236dae4SAndroid Build Coastguard Worker     o  X'04' Host unreachable
601*6236dae4SAndroid Build Coastguard Worker     o  X'05' Connection refused
602*6236dae4SAndroid Build Coastguard Worker     o  X'06' TTL expired
603*6236dae4SAndroid Build Coastguard Worker     o  X'07' Command not supported
604*6236dae4SAndroid Build Coastguard Worker     o  X'08' Address type not supported
605*6236dae4SAndroid Build Coastguard Worker     o  X'09' to X'FF' unassigned
606*6236dae4SAndroid Build Coastguard Worker   */
607*6236dae4SAndroid Build Coastguard Worker   response[SOCKS5_REP] = rep;
608*6236dae4SAndroid Build Coastguard Worker   response[SOCKS5_RESERVED] = 0; /* must be zero */
609*6236dae4SAndroid Build Coastguard Worker   response[SOCKS5_ATYP] = type; /* address type */
610*6236dae4SAndroid Build Coastguard Worker 
611*6236dae4SAndroid Build Coastguard Worker   /* mirror back the original addr + port */
612*6236dae4SAndroid Build Coastguard Worker 
613*6236dae4SAndroid Build Coastguard Worker   /* address or hostname */
614*6236dae4SAndroid Build Coastguard Worker   memcpy(&response[SOCKS5_BNDADDR], address, len);
615*6236dae4SAndroid Build Coastguard Worker 
616*6236dae4SAndroid Build Coastguard Worker   /* port number */
617*6236dae4SAndroid Build Coastguard Worker   memcpy(&response[SOCKS5_BNDADDR + len],
618*6236dae4SAndroid Build Coastguard Worker          &buffer[SOCKS5_DSTADDR + len], sizeof(socksport));
619*6236dae4SAndroid Build Coastguard Worker 
620*6236dae4SAndroid Build Coastguard Worker   rc = (send)(fd, (char *)response, (SEND_TYPE_ARG3)(len + 6), 0);
621*6236dae4SAndroid Build Coastguard Worker   if(rc != (len + 6)) {
622*6236dae4SAndroid Build Coastguard Worker     logmsg("Sending connect response failed!");
623*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
624*6236dae4SAndroid Build Coastguard Worker   }
625*6236dae4SAndroid Build Coastguard Worker   logmsg("Sent %zd bytes", rc);
626*6236dae4SAndroid Build Coastguard Worker   loghex(response, rc);
627*6236dae4SAndroid Build Coastguard Worker 
628*6236dae4SAndroid Build Coastguard Worker   if(!rep)
629*6236dae4SAndroid Build Coastguard Worker     return connfd;
630*6236dae4SAndroid Build Coastguard Worker 
631*6236dae4SAndroid Build Coastguard Worker   if(connfd != CURL_SOCKET_BAD)
632*6236dae4SAndroid Build Coastguard Worker     sclose(connfd);
633*6236dae4SAndroid Build Coastguard Worker 
634*6236dae4SAndroid Build Coastguard Worker   return CURL_SOCKET_BAD;
635*6236dae4SAndroid Build Coastguard Worker }
636*6236dae4SAndroid Build Coastguard Worker 
637*6236dae4SAndroid Build Coastguard Worker struct perclient {
638*6236dae4SAndroid Build Coastguard Worker   size_t fromremote;
639*6236dae4SAndroid Build Coastguard Worker   size_t fromclient;
640*6236dae4SAndroid Build Coastguard Worker   curl_socket_t remotefd;
641*6236dae4SAndroid Build Coastguard Worker   curl_socket_t clientfd;
642*6236dae4SAndroid Build Coastguard Worker   bool used;
643*6236dae4SAndroid Build Coastguard Worker };
644*6236dae4SAndroid Build Coastguard Worker 
645*6236dae4SAndroid Build Coastguard Worker /* return non-zero when transfer is done */
tunnel(struct perclient * cp,fd_set * fds)646*6236dae4SAndroid Build Coastguard Worker static int tunnel(struct perclient *cp, fd_set *fds)
647*6236dae4SAndroid Build Coastguard Worker {
648*6236dae4SAndroid Build Coastguard Worker   ssize_t nread;
649*6236dae4SAndroid Build Coastguard Worker   ssize_t nwrite;
650*6236dae4SAndroid Build Coastguard Worker   char buffer[512];
651*6236dae4SAndroid Build Coastguard Worker   if(FD_ISSET(cp->clientfd, fds)) {
652*6236dae4SAndroid Build Coastguard Worker     /* read from client, send to remote */
653*6236dae4SAndroid Build Coastguard Worker     nread = recv(cp->clientfd, buffer, sizeof(buffer), 0);
654*6236dae4SAndroid Build Coastguard Worker     if(nread > 0) {
655*6236dae4SAndroid Build Coastguard Worker       nwrite = send(cp->remotefd, (char *)buffer,
656*6236dae4SAndroid Build Coastguard Worker                     (SEND_TYPE_ARG3)nread, 0);
657*6236dae4SAndroid Build Coastguard Worker       if(nwrite != nread)
658*6236dae4SAndroid Build Coastguard Worker         return 1;
659*6236dae4SAndroid Build Coastguard Worker       cp->fromclient += nwrite;
660*6236dae4SAndroid Build Coastguard Worker     }
661*6236dae4SAndroid Build Coastguard Worker     else
662*6236dae4SAndroid Build Coastguard Worker       return 1;
663*6236dae4SAndroid Build Coastguard Worker   }
664*6236dae4SAndroid Build Coastguard Worker   if(FD_ISSET(cp->remotefd, fds)) {
665*6236dae4SAndroid Build Coastguard Worker     /* read from remote, send to client */
666*6236dae4SAndroid Build Coastguard Worker     nread = recv(cp->remotefd, buffer, sizeof(buffer), 0);
667*6236dae4SAndroid Build Coastguard Worker     if(nread > 0) {
668*6236dae4SAndroid Build Coastguard Worker       nwrite = send(cp->clientfd, (char *)buffer,
669*6236dae4SAndroid Build Coastguard Worker                     (SEND_TYPE_ARG3)nread, 0);
670*6236dae4SAndroid Build Coastguard Worker       if(nwrite != nread)
671*6236dae4SAndroid Build Coastguard Worker         return 1;
672*6236dae4SAndroid Build Coastguard Worker       cp->fromremote += nwrite;
673*6236dae4SAndroid Build Coastguard Worker     }
674*6236dae4SAndroid Build Coastguard Worker     else
675*6236dae4SAndroid Build Coastguard Worker       return 1;
676*6236dae4SAndroid Build Coastguard Worker   }
677*6236dae4SAndroid Build Coastguard Worker   return 0;
678*6236dae4SAndroid Build Coastguard Worker }
679*6236dae4SAndroid Build Coastguard Worker 
680*6236dae4SAndroid Build Coastguard Worker /*
681*6236dae4SAndroid Build Coastguard Worker   sockfdp is a pointer to an established stream or CURL_SOCKET_BAD
682*6236dae4SAndroid Build Coastguard Worker 
683*6236dae4SAndroid Build Coastguard Worker   if sockfd is CURL_SOCKET_BAD, listendfd is a listening socket we must
684*6236dae4SAndroid Build Coastguard Worker   accept()
685*6236dae4SAndroid Build Coastguard Worker */
incoming(curl_socket_t listenfd)686*6236dae4SAndroid Build Coastguard Worker static bool incoming(curl_socket_t listenfd)
687*6236dae4SAndroid Build Coastguard Worker {
688*6236dae4SAndroid Build Coastguard Worker   fd_set fds_read;
689*6236dae4SAndroid Build Coastguard Worker   fd_set fds_write;
690*6236dae4SAndroid Build Coastguard Worker   fd_set fds_err;
691*6236dae4SAndroid Build Coastguard Worker   int clients = 0; /* connected clients */
692*6236dae4SAndroid Build Coastguard Worker   struct perclient c[2];
693*6236dae4SAndroid Build Coastguard Worker 
694*6236dae4SAndroid Build Coastguard Worker   memset(c, 0, sizeof(c));
695*6236dae4SAndroid Build Coastguard Worker   if(got_exit_signal) {
696*6236dae4SAndroid Build Coastguard Worker     logmsg("signalled to die, exiting...");
697*6236dae4SAndroid Build Coastguard Worker     return FALSE;
698*6236dae4SAndroid Build Coastguard Worker   }
699*6236dae4SAndroid Build Coastguard Worker 
700*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_GETPPID
701*6236dae4SAndroid Build Coastguard Worker   /* As a last resort, quit if socks5 process becomes orphan. */
702*6236dae4SAndroid Build Coastguard Worker   if(getppid() <= 1) {
703*6236dae4SAndroid Build Coastguard Worker     logmsg("process becomes orphan, exiting");
704*6236dae4SAndroid Build Coastguard Worker     return FALSE;
705*6236dae4SAndroid Build Coastguard Worker   }
706*6236dae4SAndroid Build Coastguard Worker #endif
707*6236dae4SAndroid Build Coastguard Worker 
708*6236dae4SAndroid Build Coastguard Worker   do {
709*6236dae4SAndroid Build Coastguard Worker     int i;
710*6236dae4SAndroid Build Coastguard Worker     ssize_t rc;
711*6236dae4SAndroid Build Coastguard Worker     int error = 0;
712*6236dae4SAndroid Build Coastguard Worker     curl_socket_t sockfd = listenfd;
713*6236dae4SAndroid Build Coastguard Worker     int maxfd = (int)sockfd;
714*6236dae4SAndroid Build Coastguard Worker 
715*6236dae4SAndroid Build Coastguard Worker     FD_ZERO(&fds_read);
716*6236dae4SAndroid Build Coastguard Worker     FD_ZERO(&fds_write);
717*6236dae4SAndroid Build Coastguard Worker     FD_ZERO(&fds_err);
718*6236dae4SAndroid Build Coastguard Worker 
719*6236dae4SAndroid Build Coastguard Worker     /* there's always a socket to wait for */
720*6236dae4SAndroid Build Coastguard Worker     FD_SET(sockfd, &fds_read);
721*6236dae4SAndroid Build Coastguard Worker 
722*6236dae4SAndroid Build Coastguard Worker     for(i = 0; i < 2; i++) {
723*6236dae4SAndroid Build Coastguard Worker       if(c[i].used) {
724*6236dae4SAndroid Build Coastguard Worker         curl_socket_t fd = c[i].clientfd;
725*6236dae4SAndroid Build Coastguard Worker         FD_SET(fd, &fds_read);
726*6236dae4SAndroid Build Coastguard Worker         if((int)fd > maxfd)
727*6236dae4SAndroid Build Coastguard Worker           maxfd = (int)fd;
728*6236dae4SAndroid Build Coastguard Worker         fd = c[i].remotefd;
729*6236dae4SAndroid Build Coastguard Worker         FD_SET(fd, &fds_read);
730*6236dae4SAndroid Build Coastguard Worker         if((int)fd > maxfd)
731*6236dae4SAndroid Build Coastguard Worker           maxfd = (int)fd;
732*6236dae4SAndroid Build Coastguard Worker       }
733*6236dae4SAndroid Build Coastguard Worker     }
734*6236dae4SAndroid Build Coastguard Worker 
735*6236dae4SAndroid Build Coastguard Worker     do {
736*6236dae4SAndroid Build Coastguard Worker       /* select() blocking behavior call on blocking descriptors please */
737*6236dae4SAndroid Build Coastguard Worker       rc = select(maxfd + 1, &fds_read, &fds_write, &fds_err, NULL);
738*6236dae4SAndroid Build Coastguard Worker       if(got_exit_signal) {
739*6236dae4SAndroid Build Coastguard Worker         logmsg("signalled to die, exiting...");
740*6236dae4SAndroid Build Coastguard Worker         return FALSE;
741*6236dae4SAndroid Build Coastguard Worker       }
742*6236dae4SAndroid Build Coastguard Worker     } while((rc == -1) && ((error = errno) == EINTR));
743*6236dae4SAndroid Build Coastguard Worker 
744*6236dae4SAndroid Build Coastguard Worker     if(rc < 0) {
745*6236dae4SAndroid Build Coastguard Worker       logmsg("select() failed with error: (%d) %s",
746*6236dae4SAndroid Build Coastguard Worker              error, strerror(error));
747*6236dae4SAndroid Build Coastguard Worker       return FALSE;
748*6236dae4SAndroid Build Coastguard Worker     }
749*6236dae4SAndroid Build Coastguard Worker 
750*6236dae4SAndroid Build Coastguard Worker     if((clients < 2) && FD_ISSET(sockfd, &fds_read)) {
751*6236dae4SAndroid Build Coastguard Worker       curl_socket_t newfd = accept(sockfd, NULL, NULL);
752*6236dae4SAndroid Build Coastguard Worker       if(CURL_SOCKET_BAD == newfd) {
753*6236dae4SAndroid Build Coastguard Worker         error = SOCKERRNO;
754*6236dae4SAndroid Build Coastguard Worker         logmsg("accept(%" FMT_SOCKET_T ", NULL, NULL) "
755*6236dae4SAndroid Build Coastguard Worker                "failed with error: (%d) %s",
756*6236dae4SAndroid Build Coastguard Worker                sockfd, error, sstrerror(error));
757*6236dae4SAndroid Build Coastguard Worker       }
758*6236dae4SAndroid Build Coastguard Worker       else {
759*6236dae4SAndroid Build Coastguard Worker         curl_socket_t remotefd;
760*6236dae4SAndroid Build Coastguard Worker         logmsg("====> Client connect, fd %" FMT_SOCKET_T ". "
761*6236dae4SAndroid Build Coastguard Worker                "Read config from %s", newfd, configfile);
762*6236dae4SAndroid Build Coastguard Worker         remotefd = sockit(newfd); /* SOCKS until done */
763*6236dae4SAndroid Build Coastguard Worker         if(remotefd == CURL_SOCKET_BAD) {
764*6236dae4SAndroid Build Coastguard Worker           logmsg("====> Client disconnect");
765*6236dae4SAndroid Build Coastguard Worker           sclose(newfd);
766*6236dae4SAndroid Build Coastguard Worker         }
767*6236dae4SAndroid Build Coastguard Worker         else {
768*6236dae4SAndroid Build Coastguard Worker           struct perclient *cp = &c[0];
769*6236dae4SAndroid Build Coastguard Worker           logmsg("====> Tunnel transfer");
770*6236dae4SAndroid Build Coastguard Worker 
771*6236dae4SAndroid Build Coastguard Worker           if(c[0].used)
772*6236dae4SAndroid Build Coastguard Worker             cp = &c[1];
773*6236dae4SAndroid Build Coastguard Worker           cp->fromremote = 0;
774*6236dae4SAndroid Build Coastguard Worker           cp->fromclient = 0;
775*6236dae4SAndroid Build Coastguard Worker           cp->clientfd = newfd;
776*6236dae4SAndroid Build Coastguard Worker           cp->remotefd = remotefd;
777*6236dae4SAndroid Build Coastguard Worker           cp->used = TRUE;
778*6236dae4SAndroid Build Coastguard Worker           clients++;
779*6236dae4SAndroid Build Coastguard Worker         }
780*6236dae4SAndroid Build Coastguard Worker 
781*6236dae4SAndroid Build Coastguard Worker       }
782*6236dae4SAndroid Build Coastguard Worker     }
783*6236dae4SAndroid Build Coastguard Worker     for(i = 0; i < 2; i++) {
784*6236dae4SAndroid Build Coastguard Worker       struct perclient *cp = &c[i];
785*6236dae4SAndroid Build Coastguard Worker       if(cp->used) {
786*6236dae4SAndroid Build Coastguard Worker         if(tunnel(cp, &fds_read)) {
787*6236dae4SAndroid Build Coastguard Worker           logmsg("SOCKS transfer completed. Bytes: < %zu > %zu",
788*6236dae4SAndroid Build Coastguard Worker                  cp->fromremote, cp->fromclient);
789*6236dae4SAndroid Build Coastguard Worker           sclose(cp->clientfd);
790*6236dae4SAndroid Build Coastguard Worker           sclose(cp->remotefd);
791*6236dae4SAndroid Build Coastguard Worker           cp->used = FALSE;
792*6236dae4SAndroid Build Coastguard Worker           clients--;
793*6236dae4SAndroid Build Coastguard Worker         }
794*6236dae4SAndroid Build Coastguard Worker       }
795*6236dae4SAndroid Build Coastguard Worker     }
796*6236dae4SAndroid Build Coastguard Worker   } while(clients);
797*6236dae4SAndroid Build Coastguard Worker 
798*6236dae4SAndroid Build Coastguard Worker   return TRUE;
799*6236dae4SAndroid Build Coastguard Worker }
800*6236dae4SAndroid Build Coastguard Worker 
sockdaemon(curl_socket_t sock,unsigned short * listenport,const char * unix_socket)801*6236dae4SAndroid Build Coastguard Worker static curl_socket_t sockdaemon(curl_socket_t sock,
802*6236dae4SAndroid Build Coastguard Worker                                 unsigned short *listenport
803*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
804*6236dae4SAndroid Build Coastguard Worker         , const char *unix_socket
805*6236dae4SAndroid Build Coastguard Worker #endif
806*6236dae4SAndroid Build Coastguard Worker         )
807*6236dae4SAndroid Build Coastguard Worker {
808*6236dae4SAndroid Build Coastguard Worker   /* passive daemon style */
809*6236dae4SAndroid Build Coastguard Worker   srvr_sockaddr_union_t listener;
810*6236dae4SAndroid Build Coastguard Worker   int flag;
811*6236dae4SAndroid Build Coastguard Worker   int rc;
812*6236dae4SAndroid Build Coastguard Worker   int totdelay = 0;
813*6236dae4SAndroid Build Coastguard Worker   int maxretr = 10;
814*6236dae4SAndroid Build Coastguard Worker   int delay = 20;
815*6236dae4SAndroid Build Coastguard Worker   int attempt = 0;
816*6236dae4SAndroid Build Coastguard Worker   int error = 0;
817*6236dae4SAndroid Build Coastguard Worker 
818*6236dae4SAndroid Build Coastguard Worker   do {
819*6236dae4SAndroid Build Coastguard Worker     attempt++;
820*6236dae4SAndroid Build Coastguard Worker     flag = 1;
821*6236dae4SAndroid Build Coastguard Worker     rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
822*6236dae4SAndroid Build Coastguard Worker          (void *)&flag, sizeof(flag));
823*6236dae4SAndroid Build Coastguard Worker     if(rc) {
824*6236dae4SAndroid Build Coastguard Worker       error = SOCKERRNO;
825*6236dae4SAndroid Build Coastguard Worker       logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
826*6236dae4SAndroid Build Coastguard Worker              error, sstrerror(error));
827*6236dae4SAndroid Build Coastguard Worker       if(maxretr) {
828*6236dae4SAndroid Build Coastguard Worker         rc = wait_ms(delay);
829*6236dae4SAndroid Build Coastguard Worker         if(rc) {
830*6236dae4SAndroid Build Coastguard Worker           /* should not happen */
831*6236dae4SAndroid Build Coastguard Worker           error = errno;
832*6236dae4SAndroid Build Coastguard Worker           logmsg("wait_ms() failed with error: (%d) %s",
833*6236dae4SAndroid Build Coastguard Worker                  error, strerror(error));
834*6236dae4SAndroid Build Coastguard Worker           sclose(sock);
835*6236dae4SAndroid Build Coastguard Worker           return CURL_SOCKET_BAD;
836*6236dae4SAndroid Build Coastguard Worker         }
837*6236dae4SAndroid Build Coastguard Worker         if(got_exit_signal) {
838*6236dae4SAndroid Build Coastguard Worker           logmsg("signalled to die, exiting...");
839*6236dae4SAndroid Build Coastguard Worker           sclose(sock);
840*6236dae4SAndroid Build Coastguard Worker           return CURL_SOCKET_BAD;
841*6236dae4SAndroid Build Coastguard Worker         }
842*6236dae4SAndroid Build Coastguard Worker         totdelay += delay;
843*6236dae4SAndroid Build Coastguard Worker         delay *= 2; /* double the sleep for next attempt */
844*6236dae4SAndroid Build Coastguard Worker       }
845*6236dae4SAndroid Build Coastguard Worker     }
846*6236dae4SAndroid Build Coastguard Worker   } while(rc && maxretr--);
847*6236dae4SAndroid Build Coastguard Worker 
848*6236dae4SAndroid Build Coastguard Worker   if(rc) {
849*6236dae4SAndroid Build Coastguard Worker     logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error: (%d) %s",
850*6236dae4SAndroid Build Coastguard Worker            attempt, totdelay, error, strerror(error));
851*6236dae4SAndroid Build Coastguard Worker     logmsg("Continuing anyway...");
852*6236dae4SAndroid Build Coastguard Worker   }
853*6236dae4SAndroid Build Coastguard Worker 
854*6236dae4SAndroid Build Coastguard Worker   /* When the specified listener port is zero, it is actually a
855*6236dae4SAndroid Build Coastguard Worker      request to let the system choose a non-zero available port. */
856*6236dae4SAndroid Build Coastguard Worker 
857*6236dae4SAndroid Build Coastguard Worker   switch(socket_domain) {
858*6236dae4SAndroid Build Coastguard Worker     case AF_INET:
859*6236dae4SAndroid Build Coastguard Worker       memset(&listener.sa4, 0, sizeof(listener.sa4));
860*6236dae4SAndroid Build Coastguard Worker       listener.sa4.sin_family = AF_INET;
861*6236dae4SAndroid Build Coastguard Worker       listener.sa4.sin_addr.s_addr = INADDR_ANY;
862*6236dae4SAndroid Build Coastguard Worker       listener.sa4.sin_port = htons(*listenport);
863*6236dae4SAndroid Build Coastguard Worker       rc = bind(sock, &listener.sa, sizeof(listener.sa4));
864*6236dae4SAndroid Build Coastguard Worker       break;
865*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
866*6236dae4SAndroid Build Coastguard Worker     case AF_INET6:
867*6236dae4SAndroid Build Coastguard Worker       memset(&listener.sa6, 0, sizeof(listener.sa6));
868*6236dae4SAndroid Build Coastguard Worker       listener.sa6.sin6_family = AF_INET6;
869*6236dae4SAndroid Build Coastguard Worker       listener.sa6.sin6_addr = in6addr_any;
870*6236dae4SAndroid Build Coastguard Worker       listener.sa6.sin6_port = htons(*listenport);
871*6236dae4SAndroid Build Coastguard Worker       rc = bind(sock, &listener.sa, sizeof(listener.sa6));
872*6236dae4SAndroid Build Coastguard Worker       break;
873*6236dae4SAndroid Build Coastguard Worker #endif /* USE_IPV6 */
874*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
875*6236dae4SAndroid Build Coastguard Worker     case AF_UNIX:
876*6236dae4SAndroid Build Coastguard Worker     rc = bind_unix_socket(sock, unix_socket, &listener.sau);
877*6236dae4SAndroid Build Coastguard Worker #endif
878*6236dae4SAndroid Build Coastguard Worker   }
879*6236dae4SAndroid Build Coastguard Worker 
880*6236dae4SAndroid Build Coastguard Worker   if(rc) {
881*6236dae4SAndroid Build Coastguard Worker     error = SOCKERRNO;
882*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
883*6236dae4SAndroid Build Coastguard Worker     if(socket_domain == AF_UNIX)
884*6236dae4SAndroid Build Coastguard Worker       logmsg("Error binding socket on path %s: (%d) %s",
885*6236dae4SAndroid Build Coastguard Worker              unix_socket, error, sstrerror(error));
886*6236dae4SAndroid Build Coastguard Worker     else
887*6236dae4SAndroid Build Coastguard Worker #endif
888*6236dae4SAndroid Build Coastguard Worker       logmsg("Error binding socket on port %hu: (%d) %s",
889*6236dae4SAndroid Build Coastguard Worker              *listenport, error, sstrerror(error));
890*6236dae4SAndroid Build Coastguard Worker     sclose(sock);
891*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
892*6236dae4SAndroid Build Coastguard Worker   }
893*6236dae4SAndroid Build Coastguard Worker 
894*6236dae4SAndroid Build Coastguard Worker   if(!*listenport
895*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
896*6236dae4SAndroid Build Coastguard Worker           && !unix_socket
897*6236dae4SAndroid Build Coastguard Worker #endif
898*6236dae4SAndroid Build Coastguard Worker     ) {
899*6236dae4SAndroid Build Coastguard Worker     /* The system was supposed to choose a port number, figure out which
900*6236dae4SAndroid Build Coastguard Worker        port we actually got and update the listener port value with it. */
901*6236dae4SAndroid Build Coastguard Worker     curl_socklen_t la_size;
902*6236dae4SAndroid Build Coastguard Worker     srvr_sockaddr_union_t localaddr;
903*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
904*6236dae4SAndroid Build Coastguard Worker     if(socket_domain == AF_INET6)
905*6236dae4SAndroid Build Coastguard Worker       la_size = sizeof(localaddr.sa6);
906*6236dae4SAndroid Build Coastguard Worker     else
907*6236dae4SAndroid Build Coastguard Worker #endif
908*6236dae4SAndroid Build Coastguard Worker       la_size = sizeof(localaddr.sa4);
909*6236dae4SAndroid Build Coastguard Worker     memset(&localaddr.sa, 0, (size_t)la_size);
910*6236dae4SAndroid Build Coastguard Worker     if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
911*6236dae4SAndroid Build Coastguard Worker       error = SOCKERRNO;
912*6236dae4SAndroid Build Coastguard Worker       logmsg("getsockname() failed with error: (%d) %s",
913*6236dae4SAndroid Build Coastguard Worker              error, sstrerror(error));
914*6236dae4SAndroid Build Coastguard Worker       sclose(sock);
915*6236dae4SAndroid Build Coastguard Worker       return CURL_SOCKET_BAD;
916*6236dae4SAndroid Build Coastguard Worker     }
917*6236dae4SAndroid Build Coastguard Worker     switch(localaddr.sa.sa_family) {
918*6236dae4SAndroid Build Coastguard Worker     case AF_INET:
919*6236dae4SAndroid Build Coastguard Worker       *listenport = ntohs(localaddr.sa4.sin_port);
920*6236dae4SAndroid Build Coastguard Worker       break;
921*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
922*6236dae4SAndroid Build Coastguard Worker     case AF_INET6:
923*6236dae4SAndroid Build Coastguard Worker       *listenport = ntohs(localaddr.sa6.sin6_port);
924*6236dae4SAndroid Build Coastguard Worker       break;
925*6236dae4SAndroid Build Coastguard Worker #endif
926*6236dae4SAndroid Build Coastguard Worker     default:
927*6236dae4SAndroid Build Coastguard Worker       break;
928*6236dae4SAndroid Build Coastguard Worker     }
929*6236dae4SAndroid Build Coastguard Worker     if(!*listenport) {
930*6236dae4SAndroid Build Coastguard Worker       /* Real failure, listener port shall not be zero beyond this point. */
931*6236dae4SAndroid Build Coastguard Worker       logmsg("Apparently getsockname() succeeded, with listener port zero.");
932*6236dae4SAndroid Build Coastguard Worker       logmsg("A valid reason for this failure is a binary built without");
933*6236dae4SAndroid Build Coastguard Worker       logmsg("proper network library linkage. This might not be the only");
934*6236dae4SAndroid Build Coastguard Worker       logmsg("reason, but double check it before anything else.");
935*6236dae4SAndroid Build Coastguard Worker       sclose(sock);
936*6236dae4SAndroid Build Coastguard Worker       return CURL_SOCKET_BAD;
937*6236dae4SAndroid Build Coastguard Worker     }
938*6236dae4SAndroid Build Coastguard Worker   }
939*6236dae4SAndroid Build Coastguard Worker 
940*6236dae4SAndroid Build Coastguard Worker   /* start accepting connections */
941*6236dae4SAndroid Build Coastguard Worker   rc = listen(sock, 5);
942*6236dae4SAndroid Build Coastguard Worker   if(0 != rc) {
943*6236dae4SAndroid Build Coastguard Worker     error = SOCKERRNO;
944*6236dae4SAndroid Build Coastguard Worker     logmsg("listen(%" FMT_SOCKET_T ", 5) failed with error: (%d) %s",
945*6236dae4SAndroid Build Coastguard Worker            sock, error, sstrerror(error));
946*6236dae4SAndroid Build Coastguard Worker     sclose(sock);
947*6236dae4SAndroid Build Coastguard Worker     return CURL_SOCKET_BAD;
948*6236dae4SAndroid Build Coastguard Worker   }
949*6236dae4SAndroid Build Coastguard Worker 
950*6236dae4SAndroid Build Coastguard Worker   return sock;
951*6236dae4SAndroid Build Coastguard Worker }
952*6236dae4SAndroid Build Coastguard Worker 
953*6236dae4SAndroid Build Coastguard Worker 
main(int argc,char * argv[])954*6236dae4SAndroid Build Coastguard Worker int main(int argc, char *argv[])
955*6236dae4SAndroid Build Coastguard Worker {
956*6236dae4SAndroid Build Coastguard Worker   curl_socket_t sock = CURL_SOCKET_BAD;
957*6236dae4SAndroid Build Coastguard Worker   curl_socket_t msgsock = CURL_SOCKET_BAD;
958*6236dae4SAndroid Build Coastguard Worker   int wrotepidfile = 0;
959*6236dae4SAndroid Build Coastguard Worker   int wroteportfile = 0;
960*6236dae4SAndroid Build Coastguard Worker   const char *pidname = ".socksd.pid";
961*6236dae4SAndroid Build Coastguard Worker   const char *portname = NULL; /* none by default */
962*6236dae4SAndroid Build Coastguard Worker   bool juggle_again;
963*6236dae4SAndroid Build Coastguard Worker   int error;
964*6236dae4SAndroid Build Coastguard Worker   int arg = 1;
965*6236dae4SAndroid Build Coastguard Worker 
966*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
967*6236dae4SAndroid Build Coastguard Worker   const char *unix_socket = NULL;
968*6236dae4SAndroid Build Coastguard Worker   bool unlink_socket = false;
969*6236dae4SAndroid Build Coastguard Worker #endif
970*6236dae4SAndroid Build Coastguard Worker 
971*6236dae4SAndroid Build Coastguard Worker   while(argc > arg) {
972*6236dae4SAndroid Build Coastguard Worker     if(!strcmp("--version", argv[arg])) {
973*6236dae4SAndroid Build Coastguard Worker       printf("socksd IPv4%s\n",
974*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
975*6236dae4SAndroid Build Coastguard Worker              "/IPv6"
976*6236dae4SAndroid Build Coastguard Worker #else
977*6236dae4SAndroid Build Coastguard Worker              ""
978*6236dae4SAndroid Build Coastguard Worker #endif
979*6236dae4SAndroid Build Coastguard Worker              );
980*6236dae4SAndroid Build Coastguard Worker       return 0;
981*6236dae4SAndroid Build Coastguard Worker     }
982*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--pidfile", argv[arg])) {
983*6236dae4SAndroid Build Coastguard Worker       arg++;
984*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
985*6236dae4SAndroid Build Coastguard Worker         pidname = argv[arg++];
986*6236dae4SAndroid Build Coastguard Worker     }
987*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--portfile", argv[arg])) {
988*6236dae4SAndroid Build Coastguard Worker       arg++;
989*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
990*6236dae4SAndroid Build Coastguard Worker         portname = argv[arg++];
991*6236dae4SAndroid Build Coastguard Worker     }
992*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--config", argv[arg])) {
993*6236dae4SAndroid Build Coastguard Worker       arg++;
994*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
995*6236dae4SAndroid Build Coastguard Worker         configfile = argv[arg++];
996*6236dae4SAndroid Build Coastguard Worker     }
997*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--backend", argv[arg])) {
998*6236dae4SAndroid Build Coastguard Worker       arg++;
999*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
1000*6236dae4SAndroid Build Coastguard Worker         backendaddr = argv[arg++];
1001*6236dae4SAndroid Build Coastguard Worker     }
1002*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--backendport", argv[arg])) {
1003*6236dae4SAndroid Build Coastguard Worker       arg++;
1004*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
1005*6236dae4SAndroid Build Coastguard Worker         backendport = (unsigned short)atoi(argv[arg++]);
1006*6236dae4SAndroid Build Coastguard Worker     }
1007*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--logfile", argv[arg])) {
1008*6236dae4SAndroid Build Coastguard Worker       arg++;
1009*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
1010*6236dae4SAndroid Build Coastguard Worker         serverlogfile = argv[arg++];
1011*6236dae4SAndroid Build Coastguard Worker     }
1012*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--reqfile", argv[arg])) {
1013*6236dae4SAndroid Build Coastguard Worker       arg++;
1014*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
1015*6236dae4SAndroid Build Coastguard Worker         reqlogfile = argv[arg++];
1016*6236dae4SAndroid Build Coastguard Worker     }
1017*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--ipv6", argv[arg])) {
1018*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1019*6236dae4SAndroid Build Coastguard Worker       socket_domain = AF_INET6;
1020*6236dae4SAndroid Build Coastguard Worker       socket_type = "IPv6";
1021*6236dae4SAndroid Build Coastguard Worker #endif
1022*6236dae4SAndroid Build Coastguard Worker       arg++;
1023*6236dae4SAndroid Build Coastguard Worker     }
1024*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--ipv4", argv[arg])) {
1025*6236dae4SAndroid Build Coastguard Worker       /* for completeness, we support this option as well */
1026*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1027*6236dae4SAndroid Build Coastguard Worker       socket_type = "IPv4";
1028*6236dae4SAndroid Build Coastguard Worker #endif
1029*6236dae4SAndroid Build Coastguard Worker       arg++;
1030*6236dae4SAndroid Build Coastguard Worker     }
1031*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--unix-socket", argv[arg])) {
1032*6236dae4SAndroid Build Coastguard Worker       arg++;
1033*6236dae4SAndroid Build Coastguard Worker       if(argc > arg) {
1034*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
1035*6236dae4SAndroid Build Coastguard Worker         struct sockaddr_un sau;
1036*6236dae4SAndroid Build Coastguard Worker         unix_socket = argv[arg];
1037*6236dae4SAndroid Build Coastguard Worker         if(strlen(unix_socket) >= sizeof(sau.sun_path)) {
1038*6236dae4SAndroid Build Coastguard Worker           fprintf(stderr,
1039*6236dae4SAndroid Build Coastguard Worker                   "socksd: socket path must be shorter than %zu chars: %s\n",
1040*6236dae4SAndroid Build Coastguard Worker               sizeof(sau.sun_path), unix_socket);
1041*6236dae4SAndroid Build Coastguard Worker           return 0;
1042*6236dae4SAndroid Build Coastguard Worker         }
1043*6236dae4SAndroid Build Coastguard Worker         socket_domain = AF_UNIX;
1044*6236dae4SAndroid Build Coastguard Worker         socket_type = "unix";
1045*6236dae4SAndroid Build Coastguard Worker #endif
1046*6236dae4SAndroid Build Coastguard Worker         arg++;
1047*6236dae4SAndroid Build Coastguard Worker       }
1048*6236dae4SAndroid Build Coastguard Worker     }
1049*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--port", argv[arg])) {
1050*6236dae4SAndroid Build Coastguard Worker       arg++;
1051*6236dae4SAndroid Build Coastguard Worker       if(argc > arg) {
1052*6236dae4SAndroid Build Coastguard Worker         char *endptr;
1053*6236dae4SAndroid Build Coastguard Worker         unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
1054*6236dae4SAndroid Build Coastguard Worker         port = curlx_ultous(ulnum);
1055*6236dae4SAndroid Build Coastguard Worker         arg++;
1056*6236dae4SAndroid Build Coastguard Worker       }
1057*6236dae4SAndroid Build Coastguard Worker     }
1058*6236dae4SAndroid Build Coastguard Worker     else {
1059*6236dae4SAndroid Build Coastguard Worker       puts("Usage: socksd [option]\n"
1060*6236dae4SAndroid Build Coastguard Worker            " --backend [ipv4 addr]\n"
1061*6236dae4SAndroid Build Coastguard Worker            " --backendport [TCP port]\n"
1062*6236dae4SAndroid Build Coastguard Worker            " --config [file]\n"
1063*6236dae4SAndroid Build Coastguard Worker            " --version\n"
1064*6236dae4SAndroid Build Coastguard Worker            " --logfile [file]\n"
1065*6236dae4SAndroid Build Coastguard Worker            " --pidfile [file]\n"
1066*6236dae4SAndroid Build Coastguard Worker            " --portfile [file]\n"
1067*6236dae4SAndroid Build Coastguard Worker            " --reqfile [file]\n"
1068*6236dae4SAndroid Build Coastguard Worker            " --ipv4\n"
1069*6236dae4SAndroid Build Coastguard Worker            " --ipv6\n"
1070*6236dae4SAndroid Build Coastguard Worker            " --unix-socket [file]\n"
1071*6236dae4SAndroid Build Coastguard Worker            " --bindonly\n"
1072*6236dae4SAndroid Build Coastguard Worker            " --port [port]\n");
1073*6236dae4SAndroid Build Coastguard Worker       return 0;
1074*6236dae4SAndroid Build Coastguard Worker     }
1075*6236dae4SAndroid Build Coastguard Worker   }
1076*6236dae4SAndroid Build Coastguard Worker 
1077*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32
1078*6236dae4SAndroid Build Coastguard Worker   win32_init();
1079*6236dae4SAndroid Build Coastguard Worker   atexit(win32_cleanup);
1080*6236dae4SAndroid Build Coastguard Worker 
1081*6236dae4SAndroid Build Coastguard Worker   setmode(fileno(stdin), O_BINARY);
1082*6236dae4SAndroid Build Coastguard Worker   setmode(fileno(stdout), O_BINARY);
1083*6236dae4SAndroid Build Coastguard Worker   setmode(fileno(stderr), O_BINARY);
1084*6236dae4SAndroid Build Coastguard Worker #endif
1085*6236dae4SAndroid Build Coastguard Worker 
1086*6236dae4SAndroid Build Coastguard Worker   install_signal_handlers(false);
1087*6236dae4SAndroid Build Coastguard Worker 
1088*6236dae4SAndroid Build Coastguard Worker   sock = socket(socket_domain, SOCK_STREAM, 0);
1089*6236dae4SAndroid Build Coastguard Worker 
1090*6236dae4SAndroid Build Coastguard Worker   if(CURL_SOCKET_BAD == sock) {
1091*6236dae4SAndroid Build Coastguard Worker     error = SOCKERRNO;
1092*6236dae4SAndroid Build Coastguard Worker     logmsg("Error creating socket: (%d) %s",
1093*6236dae4SAndroid Build Coastguard Worker            error, sstrerror(error));
1094*6236dae4SAndroid Build Coastguard Worker     goto socks5_cleanup;
1095*6236dae4SAndroid Build Coastguard Worker   }
1096*6236dae4SAndroid Build Coastguard Worker 
1097*6236dae4SAndroid Build Coastguard Worker   {
1098*6236dae4SAndroid Build Coastguard Worker     /* passive daemon style */
1099*6236dae4SAndroid Build Coastguard Worker     sock = sockdaemon(sock, &port
1100*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
1101*6236dae4SAndroid Build Coastguard Worker             , unix_socket
1102*6236dae4SAndroid Build Coastguard Worker #endif
1103*6236dae4SAndroid Build Coastguard Worker             );
1104*6236dae4SAndroid Build Coastguard Worker     if(CURL_SOCKET_BAD == sock) {
1105*6236dae4SAndroid Build Coastguard Worker       goto socks5_cleanup;
1106*6236dae4SAndroid Build Coastguard Worker     }
1107*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
1108*6236dae4SAndroid Build Coastguard Worker     unlink_socket = true;
1109*6236dae4SAndroid Build Coastguard Worker #endif
1110*6236dae4SAndroid Build Coastguard Worker     msgsock = CURL_SOCKET_BAD; /* no stream socket yet */
1111*6236dae4SAndroid Build Coastguard Worker   }
1112*6236dae4SAndroid Build Coastguard Worker 
1113*6236dae4SAndroid Build Coastguard Worker   logmsg("Running %s version", socket_type);
1114*6236dae4SAndroid Build Coastguard Worker 
1115*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
1116*6236dae4SAndroid Build Coastguard Worker   if(socket_domain == AF_UNIX)
1117*6236dae4SAndroid Build Coastguard Worker     logmsg("Listening on Unix socket %s", unix_socket);
1118*6236dae4SAndroid Build Coastguard Worker   else
1119*6236dae4SAndroid Build Coastguard Worker #endif
1120*6236dae4SAndroid Build Coastguard Worker   logmsg("Listening on port %hu", port);
1121*6236dae4SAndroid Build Coastguard Worker 
1122*6236dae4SAndroid Build Coastguard Worker   wrotepidfile = write_pidfile(pidname);
1123*6236dae4SAndroid Build Coastguard Worker   if(!wrotepidfile) {
1124*6236dae4SAndroid Build Coastguard Worker     goto socks5_cleanup;
1125*6236dae4SAndroid Build Coastguard Worker   }
1126*6236dae4SAndroid Build Coastguard Worker 
1127*6236dae4SAndroid Build Coastguard Worker   if(portname) {
1128*6236dae4SAndroid Build Coastguard Worker     wroteportfile = write_portfile(portname, port);
1129*6236dae4SAndroid Build Coastguard Worker     if(!wroteportfile) {
1130*6236dae4SAndroid Build Coastguard Worker       goto socks5_cleanup;
1131*6236dae4SAndroid Build Coastguard Worker     }
1132*6236dae4SAndroid Build Coastguard Worker   }
1133*6236dae4SAndroid Build Coastguard Worker 
1134*6236dae4SAndroid Build Coastguard Worker   do {
1135*6236dae4SAndroid Build Coastguard Worker     juggle_again = incoming(sock);
1136*6236dae4SAndroid Build Coastguard Worker   } while(juggle_again);
1137*6236dae4SAndroid Build Coastguard Worker 
1138*6236dae4SAndroid Build Coastguard Worker socks5_cleanup:
1139*6236dae4SAndroid Build Coastguard Worker 
1140*6236dae4SAndroid Build Coastguard Worker   if((msgsock != sock) && (msgsock != CURL_SOCKET_BAD))
1141*6236dae4SAndroid Build Coastguard Worker     sclose(msgsock);
1142*6236dae4SAndroid Build Coastguard Worker 
1143*6236dae4SAndroid Build Coastguard Worker   if(sock != CURL_SOCKET_BAD)
1144*6236dae4SAndroid Build Coastguard Worker     sclose(sock);
1145*6236dae4SAndroid Build Coastguard Worker 
1146*6236dae4SAndroid Build Coastguard Worker #ifdef USE_UNIX_SOCKETS
1147*6236dae4SAndroid Build Coastguard Worker   if(unlink_socket && socket_domain == AF_UNIX) {
1148*6236dae4SAndroid Build Coastguard Worker     error = unlink(unix_socket);
1149*6236dae4SAndroid Build Coastguard Worker     logmsg("unlink(%s) = %d (%s)", unix_socket, error, strerror(error));
1150*6236dae4SAndroid Build Coastguard Worker   }
1151*6236dae4SAndroid Build Coastguard Worker #endif
1152*6236dae4SAndroid Build Coastguard Worker 
1153*6236dae4SAndroid Build Coastguard Worker   if(wrotepidfile)
1154*6236dae4SAndroid Build Coastguard Worker     unlink(pidname);
1155*6236dae4SAndroid Build Coastguard Worker   if(wroteportfile)
1156*6236dae4SAndroid Build Coastguard Worker     unlink(portname);
1157*6236dae4SAndroid Build Coastguard Worker 
1158*6236dae4SAndroid Build Coastguard Worker   restore_signal_handlers(false);
1159*6236dae4SAndroid Build Coastguard Worker 
1160*6236dae4SAndroid Build Coastguard Worker   if(got_exit_signal) {
1161*6236dae4SAndroid Build Coastguard Worker     logmsg("============> socksd exits with signal (%d)", exit_signal);
1162*6236dae4SAndroid Build Coastguard Worker     /*
1163*6236dae4SAndroid Build Coastguard Worker      * To properly set the return status of the process we
1164*6236dae4SAndroid Build Coastguard Worker      * must raise the same signal SIGINT or SIGTERM that we
1165*6236dae4SAndroid Build Coastguard Worker      * caught and let the old handler take care of it.
1166*6236dae4SAndroid Build Coastguard Worker      */
1167*6236dae4SAndroid Build Coastguard Worker     raise(exit_signal);
1168*6236dae4SAndroid Build Coastguard Worker   }
1169*6236dae4SAndroid Build Coastguard Worker 
1170*6236dae4SAndroid Build Coastguard Worker   logmsg("============> socksd quits");
1171*6236dae4SAndroid Build Coastguard Worker   return 0;
1172*6236dae4SAndroid Build Coastguard Worker }
1173