OpenVPN
socks.c
Go to the documentation of this file.
1 /*
2  * OpenVPN -- An application to securely tunnel IP networks
3  * over a single TCP/UDP port, with support for SSL/TLS-based
4  * session authentication and key exchange,
5  * packet encryption, packet authentication, and
6  * packet compression.
7  *
8  * Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2
12  * as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 /*
25  * 2004-01-30: Added Socks5 proxy support, see RFC 1928
26  * (Christof Meerwald, http://cmeerw.org)
27  *
28  * 2010-10-10: Added Socks5 plain text authentication support (RFC 1929)
29  * (Pierre Bourdon <delroth@gmail.com>)
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include "syshead.h"
37 
38 #include "common.h"
39 #include "misc.h"
40 #include "win32.h"
41 #include "socket.h"
42 #include "fdmisc.h"
43 #include "misc.h"
44 #include "proxy.h"
45 #include "forward.h"
46 
47 #include "memdbg.h"
48 
49 #define UP_TYPE_SOCKS "SOCKS Proxy"
50 
51 struct socks_proxy_info *
52 socks_proxy_new(const char *server,
53  const char *port,
54  const char *authfile)
55 {
56  struct socks_proxy_info *p;
57 
59 
60  ASSERT(server);
61  ASSERT(port);
62 
63  strncpynt(p->server, server, sizeof(p->server));
64  p->port = port;
65 
66  if (authfile)
67  {
68  strncpynt(p->authfile, authfile, sizeof(p->authfile));
69  }
70  else
71  {
72  p->authfile[0] = 0;
73  }
74 
75  p->defined = true;
76 
77  return p;
78 }
79 
80 void
82 {
83  free(sp);
84 }
85 
86 static bool
89  struct event_timeout *server_poll_timeout,
90  volatile int *signal_received)
91 {
92  char to_send[516];
93  char buf[2];
94  int len = 0;
95  struct user_pass creds;
96  ssize_t size;
97  bool ret = false;
98 
99  creds.defined = 0;
101  {
102  msg(M_NONFATAL, "SOCKS failed to get username/password.");
103  goto cleanup;
104  }
105 
106  if ( (strlen(creds.username) > 255) || (strlen(creds.password) > 255) )
107  {
108  msg(M_NONFATAL,
109  "SOCKS username and/or password exceeds 255 characters. "
110  "Authentication not possible.");
111  goto cleanup;
112  }
113 
114  int sret = snprintf(to_send, sizeof(to_send), "\x01%c%s%c%s",
115  (int) strlen(creds.username), creds.username,
116  (int) strlen(creds.password), creds.password);
117  ASSERT(sret <= sizeof(to_send));
118 
119  size = send(sd, to_send, strlen(to_send), MSG_NOSIGNAL);
120 
121  if (size != strlen(to_send))
122  {
123  msg(D_LINK_ERRORS | M_ERRNO, "socks_username_password_auth: TCP port write failed on send()");
124  goto cleanup;
125  }
126 
127  while (len < 2)
128  {
129  int status;
130  ssize_t size;
131  fd_set reads;
132  struct timeval tv;
133  char c;
134 
135  FD_ZERO(&reads);
136  openvpn_fd_set(sd, &reads);
137  tv.tv_sec = get_server_poll_remaining_time(server_poll_timeout);
138  tv.tv_usec = 0;
139 
140  status = select(sd + 1, &reads, NULL, NULL, &tv);
141 
142  get_signal(signal_received);
143  if (*signal_received)
144  {
145  goto cleanup;
146  }
147 
148  /* timeout? */
149  if (status == 0)
150  {
151  msg(D_LINK_ERRORS | M_ERRNO, "socks_username_password_auth: TCP port read timeout expired");
152  goto cleanup;
153  }
154 
155  /* error */
156  if (status < 0)
157  {
158  msg(D_LINK_ERRORS | M_ERRNO, "socks_username_password_auth: TCP port read failed on select()");
159  goto cleanup;
160  }
161 
162  /* read single char */
163  size = recv(sd, &c, 1, MSG_NOSIGNAL);
164 
165  /* error? */
166  if (size != 1)
167  {
168  msg(D_LINK_ERRORS | M_ERRNO, "socks_username_password_auth: TCP port read failed on recv()");
169  goto cleanup;
170  }
171 
172  /* store char in buffer */
173  buf[len++] = c;
174  }
175 
176  /* VER = 5, SUCCESS = 0 --> auth success */
177  if (buf[0] != 5 && buf[1] != 0)
178  {
179  msg(D_LINK_ERRORS, "socks_username_password_auth: server refused the authentication");
180  goto cleanup;
181  }
182 
183  ret = true;
184 cleanup:
185  secure_memzero(&creds, sizeof(creds));
186  secure_memzero(to_send, sizeof(to_send));
187  return ret;
188 }
189 
190 static bool
193  struct event_timeout *server_poll_timeout,
194  volatile int *signal_received)
195 {
196  char buf[2];
197  int len = 0;
198  ssize_t size;
199 
200  /* VER = 5, NMETHODS = 1, METHODS = [0 (no auth)] */
201  char method_sel[3] = { 0x05, 0x01, 0x00 };
202  if (p->authfile[0])
203  {
204  method_sel[2] = 0x02; /* METHODS = [2 (plain login)] */
205 
206  }
207  size = send(sd, method_sel, sizeof(method_sel), MSG_NOSIGNAL);
208  if (size != sizeof(method_sel))
209  {
210  msg(D_LINK_ERRORS | M_ERRNO, "socks_handshake: TCP port write failed on send()");
211  return false;
212  }
213 
214  while (len < 2)
215  {
216  int status;
217  ssize_t size;
218  fd_set reads;
219  struct timeval tv;
220  char c;
221 
222  FD_ZERO(&reads);
223  openvpn_fd_set(sd, &reads);
224  tv.tv_sec = get_server_poll_remaining_time(server_poll_timeout);
225  tv.tv_usec = 0;
226 
227  status = select(sd + 1, &reads, NULL, NULL, &tv);
228 
229  get_signal(signal_received);
230  if (*signal_received)
231  {
232  return false;
233  }
234 
235  /* timeout? */
236  if (status == 0)
237  {
238  msg(D_LINK_ERRORS | M_ERRNO, "socks_handshake: TCP port read timeout expired");
239  return false;
240  }
241 
242  /* error */
243  if (status < 0)
244  {
245  msg(D_LINK_ERRORS | M_ERRNO, "socks_handshake: TCP port read failed on select()");
246  return false;
247  }
248 
249  /* read single char */
250  size = recv(sd, &c, 1, MSG_NOSIGNAL);
251 
252  /* error? */
253  if (size != 1)
254  {
255  msg(D_LINK_ERRORS | M_ERRNO, "socks_handshake: TCP port read failed on recv()");
256  return false;
257  }
258 
259  /* store char in buffer */
260  buf[len++] = c;
261  }
262 
263  /* VER == 5 */
264  if (buf[0] != '\x05')
265  {
266  msg(D_LINK_ERRORS, "socks_handshake: Socks proxy returned bad status");
267  return false;
268  }
269 
270  /* validate that the auth method returned is the one sent */
271  if (buf[1] != method_sel[2])
272  {
273  msg(D_LINK_ERRORS, "socks_handshake: Socks proxy returned unexpected auth");
274  return false;
275  }
276 
277  /* select the appropriate authentication method */
278  switch (buf[1])
279  {
280  case 0: /* no authentication */
281  break;
282 
283  case 2: /* login/password */
284  if (!p->authfile[0])
285  {
286  msg(D_LINK_ERRORS, "socks_handshake: server asked for username/login auth but we were "
287  "not provided any credentials");
288  return false;
289  }
290 
291  if (!socks_username_password_auth(p, sd, server_poll_timeout, signal_received))
292  {
293  return false;
294  }
295 
296  break;
297 
298  default: /* unknown auth method */
299  msg(D_LINK_ERRORS, "socks_handshake: unknown SOCKS auth method");
300  return false;
301  }
302 
303  return true;
304 }
305 
306 static bool
308  struct openvpn_sockaddr *addr,
309  struct event_timeout *server_poll_timeout,
310  volatile int *signal_received)
311 {
312  char atyp = '\0';
313  int alen = 0;
314  int len = 0;
315  char buf[270]; /* 4 + alen(max 256) + 2 */
316 
317  if (addr != NULL)
318  {
319  addr->addr.in4.sin_family = AF_INET;
320  addr->addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
321  addr->addr.in4.sin_port = htons(0);
322  }
323 
324  while (len < 4 + alen + 2)
325  {
326  int status;
327  ssize_t size;
328  fd_set reads;
329  struct timeval tv;
330  char c;
331 
332  FD_ZERO(&reads);
333  openvpn_fd_set(sd, &reads);
334  tv.tv_sec = get_server_poll_remaining_time(server_poll_timeout);
335  tv.tv_usec = 0;
336 
337  status = select(sd + 1, &reads, NULL, NULL, &tv);
338 
339  get_signal(signal_received);
340  if (*signal_received)
341  {
342  return false;
343  }
344 
345  /* timeout? */
346  if (status == 0)
347  {
348  msg(D_LINK_ERRORS | M_ERRNO, "recv_socks_reply: TCP port read timeout expired");
349  return false;
350  }
351 
352  /* error */
353  if (status < 0)
354  {
355  msg(D_LINK_ERRORS | M_ERRNO, "recv_socks_reply: TCP port read failed on select()");
356  return false;
357  }
358 
359  /* read single char */
360  size = recv(sd, &c, 1, MSG_NOSIGNAL);
361 
362  /* error? */
363  if (size < 0)
364  {
365  msg(D_LINK_ERRORS | M_ERRNO, "recv_socks_reply: TCP port read failed on recv()");
366  return false;
367  }
368  else if (size == 0)
369  {
370  msg(D_LINK_ERRORS, "ERROR: recv_socks_reply: empty response from socks server");
371  return false;
372  }
373 
374  if (len == 3)
375  {
376  atyp = c;
377  }
378 
379  if (len == 4)
380  {
381  switch (atyp)
382  {
383  case '\x01': /* IP V4 */
384  alen = 4;
385  break;
386 
387  case '\x03': /* DOMAINNAME */
388  /* RFC 1928, section 5: 1 byte length, <n> bytes name,
389  * so the total "address length" is (length+1)
390  */
391  alen = (unsigned char) c + 1;
392  break;
393 
394  case '\x04': /* IP V6 */
395  alen = 16;
396  break;
397 
398  default:
399  msg(D_LINK_ERRORS, "recv_socks_reply: Socks proxy returned bad address type");
400  return false;
401  }
402  }
403 
404  /* store char in buffer */
405  if (len < (int)sizeof(buf))
406  {
407  buf[len] = c;
408  }
409  ++len;
410  }
411 
412  /* VER == 5 && REP == 0 (succeeded) */
413  if (buf[0] != '\x05' || buf[1] != '\x00')
414  {
415  msg(D_LINK_ERRORS, "recv_socks_reply: Socks proxy returned bad reply");
416  return false;
417  }
418 
419  /* ATYP == 1 (IP V4 address) */
420  if (atyp == '\x01' && addr != NULL)
421  {
422  memcpy(&addr->addr.in4.sin_addr, buf + 4, sizeof(addr->addr.in4.sin_addr));
423  memcpy(&addr->addr.in4.sin_port, buf + 8, sizeof(addr->addr.in4.sin_port));
424  struct gc_arena gc = gc_new();
425  msg(M_INFO, "SOCKS proxy wants us to send UDP to %s",
426  print_openvpn_sockaddr(addr, &gc));
427  gc_free(&gc);
428  }
429 
430 
431  return true;
432 }
433 
434 static int
435 port_from_servname(const char *servname)
436 {
437  int port = 0;
438  port = atoi(servname);
439  if (port >0 && port < 65536)
440  {
441  return port;
442  }
443 
444  struct servent *service;
445  service = getservbyname(servname, NULL);
446  if (service)
447  {
448  return service->s_port;
449  }
450 
451  return 0;
452 }
453 
454 void
456  socket_descriptor_t sd, /* already open to proxy */
457  const char *host, /* openvpn server remote */
458  const char *servname, /* openvpn server port */
459  struct event_timeout *server_poll_timeout,
460  struct signal_info *sig_info)
461 {
462  char buf[270];
463  size_t len;
464 
465  if (!socks_handshake(p, sd, server_poll_timeout, &sig_info->signal_received))
466  {
467  goto error;
468  }
469 
470  /* format Socks CONNECT message */
471  buf[0] = '\x05'; /* VER = 5 */
472  buf[1] = '\x01'; /* CMD = 1 (CONNECT) */
473  buf[2] = '\x00'; /* RSV */
474  buf[3] = '\x03'; /* ATYP = 3 (DOMAINNAME) */
475 
476  len = strlen(host);
477  len = (5 + len + 2 > sizeof(buf)) ? (sizeof(buf) - 5 - 2) : len;
478 
479  buf[4] = (char) len;
480  memcpy(buf + 5, host, len);
481 
482  int port = port_from_servname(servname);
483  if (port ==0)
484  {
485  msg(D_LINK_ERRORS, "establish_socks_proxy_passthrough: Cannot convert %s to port number", servname);
486  goto error;
487  }
488 
489  buf[5 + len] = (char) (port >> 8);
490  buf[5 + len + 1] = (char) (port & 0xff);
491 
492  {
493  const ssize_t size = send(sd, buf, 5 + len + 2, MSG_NOSIGNAL);
494  if ((int)size != 5 + (int)len + 2)
495  {
496  msg(D_LINK_ERRORS | M_ERRNO, "establish_socks_proxy_passthru: TCP port write failed on send()");
497  goto error;
498  }
499  }
500 
501 
502  /* receive reply from Socks proxy and discard */
503  if (!recv_socks_reply(sd, NULL, server_poll_timeout, &sig_info->signal_received))
504  {
505  goto error;
506  }
507 
508  return;
509 
510 error:
511  /* SOFT-SIGUSR1 -- socks error */
512  register_signal(sig_info, SIGUSR1, "socks-error");
513  return;
514 }
515 
516 void
518  socket_descriptor_t ctrl_sd, /* already open to proxy */
519  socket_descriptor_t udp_sd,
520  struct openvpn_sockaddr *relay_addr,
521  struct event_timeout *server_poll_timeout,
522  struct signal_info *sig_info)
523 {
524  if (!socks_handshake(p, ctrl_sd, server_poll_timeout, &sig_info->signal_received))
525  {
526  goto error;
527  }
528 
529  {
530  /* send Socks UDP ASSOCIATE message */
531  /* VER = 5, CMD = 3 (UDP ASSOCIATE), RSV = 0, ATYP = 1 (IP V4),
532  * BND.ADDR = 0, BND.PORT = 0 */
533  const ssize_t size = send(ctrl_sd,
534  "\x05\x03\x00\x01\x00\x00\x00\x00\x00\x00",
535  10, MSG_NOSIGNAL);
536  if (size != 10)
537  {
538  msg(D_LINK_ERRORS | M_ERRNO, "establish_socks_proxy_passthru: TCP port write failed on send()");
539  goto error;
540  }
541  }
542 
543  /* receive reply from Socks proxy */
544  CLEAR(*relay_addr);
545  if (!recv_socks_reply(ctrl_sd, relay_addr, server_poll_timeout, &sig_info->signal_received))
546  {
547  goto error;
548  }
549 
550  return;
551 
552 error:
553  /* SOFT-SIGUSR1 -- socks error */
554  register_signal(sig_info, SIGUSR1, "socks-error");
555  return;
556 }
557 
558 /*
559  * Remove the 10 byte socks5 header from an incoming
560  * UDP packet, setting *from to the source address.
561  *
562  * Run after UDP read.
563  */
564 void
566  struct link_socket_actual *from)
567 {
568  int atyp;
569 
570  if (BLEN(buf) < 10)
571  {
572  goto error;
573  }
574 
575  buf_read_u16(buf);
576  if (buf_read_u8(buf) != 0)
577  {
578  goto error;
579  }
580 
581  atyp = buf_read_u8(buf);
582  if (atyp != 1) /* ATYP == 1 (IP V4) */
583  {
584  goto error;
585  }
586 
587  buf_read(buf, &from->dest.addr.in4.sin_addr, sizeof(from->dest.addr.in4.sin_addr));
588  buf_read(buf, &from->dest.addr.in4.sin_port, sizeof(from->dest.addr.in4.sin_port));
589 
590  return;
591 
592 error:
593  buf->len = 0;
594 }
595 
596 /*
597  * Add a 10 byte socks header prior to UDP write.
598  * *to is the destination address.
599  *
600  * Run before UDP write.
601  * Returns the size of the header.
602  */
603 int
605  const struct link_socket_actual *to)
606 {
607  /*
608  * Get a 10 byte subset buffer prepended to buf --
609  * we expect these bytes will be here because
610  * we always allocate space for these bytes
611  */
612  struct buffer head = buf_sub(buf, 10, true);
613 
614  /* crash if not enough headroom in buf */
615  ASSERT(buf_defined(&head));
616 
617  buf_write_u16(&head, 0); /* RSV = 0 */
618  buf_write_u8(&head, 0); /* FRAG = 0 */
619  buf_write_u8(&head, '\x01'); /* ATYP = 1 (IP V4) */
620  buf_write(&head, &to->dest.addr.in4.sin_addr, sizeof(to->dest.addr.in4.sin_addr));
621  buf_write(&head, &to->dest.addr.in4.sin_port, sizeof(to->dest.addr.in4.sin_port));
622 
623  return 10;
624 }
establish_socks_proxy_udpassoc
void establish_socks_proxy_udpassoc(struct socks_proxy_info *p, socket_descriptor_t ctrl_sd, socket_descriptor_t udp_sd, struct openvpn_sockaddr *relay_addr, struct event_timeout *server_poll_timeout, struct signal_info *sig_info)
Definition: socks.c:517
signal_info::signal_received
volatile int signal_received
Definition: sig.h:43
openvpn_sockaddr::addr
union openvpn_sockaddr::@14 addr
M_INFO
#define M_INFO
Definition: errlevel.h:55
buf_read
static bool buf_read(struct buffer *src, void *dest, int size)
Definition: buffer.h:783
gc_new
static struct gc_arena gc_new(void)
Definition: buffer.h:1030
M_ERRNO
#define M_ERRNO
Definition: error.h:94
forward.h
buffer::len
int len
Length in bytes of the actual content within the allocated memory.
Definition: buffer.h:66
D_LINK_ERRORS
#define D_LINK_ERRORS
Definition: errlevel.h:57
win32.h
socks_process_outgoing_udp
int socks_process_outgoing_udp(struct buffer *buf, const struct link_socket_actual *to)
Definition: socks.c:604
M_NONFATAL
#define M_NONFATAL
Definition: error.h:90
user_pass::username
char username[USER_PASS_LEN]
Definition: misc.h:71
user_pass::defined
bool defined
Definition: misc.h:58
buf_sub
struct buffer buf_sub(struct buffer *buf, int size, bool prepend)
Definition: buffer.c:221
fdmisc.h
establish_socks_proxy_passthru
void establish_socks_proxy_passthru(struct socks_proxy_info *p, socket_descriptor_t sd, const char *host, const char *servname, struct event_timeout *server_poll_timeout, struct signal_info *sig_info)
Definition: socks.c:455
socks_proxy_info::port
const char * port
Definition: socks.h:41
openvpn_sockaddr
Definition: socket.h:65
socks_proxy_close
void socks_proxy_close(struct socks_proxy_info *sp)
Definition: socks.c:81
GET_USER_PASS_MANAGEMENT
#define GET_USER_PASS_MANAGEMENT
Definition: misc.h:107
recv_socks_reply
static bool recv_socks_reply(socket_descriptor_t sd, struct openvpn_sockaddr *addr, struct event_timeout *server_poll_timeout, volatile int *signal_received)
Definition: socks.c:307
get_server_poll_remaining_time
int get_server_poll_remaining_time(struct event_timeout *server_poll_timeout)
Definition: forward.c:531
CLEAR
#define CLEAR(x)
Definition: basic.h:33
secure_memzero
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
Definition: buffer.h:414
ASSERT
#define ASSERT(x)
Definition: error.h:195
buf_write_u16
static bool buf_write_u16(struct buffer *dest, uint16_t data)
Definition: buffer.h:703
BLEN
#define BLEN(buf)
Definition: buffer.h:127
buf_write_u8
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Definition: buffer.h:697
openvpn_sockaddr::in4
struct sockaddr_in in4
Definition: socket.h:70
socks_process_incoming_udp
void socks_process_incoming_udp(struct buffer *buf, struct link_socket_actual *from)
Definition: socks.c:565
misc.h
openvpn_fd_set
static void openvpn_fd_set(socket_descriptor_t fd, fd_set *setp)
Definition: fdmisc.h:40
UP_TYPE_SOCKS
#define UP_TYPE_SOCKS
Definition: socks.c:49
buf_read_u16
static int buf_read_u16(struct buffer *buf)
Definition: buffer.h:808
get_user_pass
static bool get_user_pass(struct user_pass *up, const char *auth_file, const char *prefix, const unsigned int flags)
Retrieves the user credentials from various sources depending on the flags.
Definition: misc.h:147
buffer
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
port_from_servname
static int port_from_servname(const char *servname)
Definition: socks.c:435
buf_write
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition: buffer.h:673
proxy.h
syshead.h
socks_proxy_info::defined
bool defined
Definition: socks.h:38
socks_proxy_info
Definition: socks.h:37
gc_arena
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
strncpynt
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition: buffer.h:361
socket_descriptor_t
SOCKET socket_descriptor_t
Definition: syshead.h:429
common.h
service
static SERVICE_STATUS_HANDLE service
Definition: interactive.c:52
signal_info
Definition: sig.h:41
status
static SERVICE_STATUS status
Definition: interactive.c:53
gc_free
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1038
socks_proxy_new
struct socks_proxy_info * socks_proxy_new(const char *server, const char *port, const char *authfile)
Definition: socks.c:52
socket.h
ALLOC_OBJ_CLEAR
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition: buffer.h:1065
config.h
event_timeout
Definition: interval.h:136
user_pass::password
char password[USER_PASS_LEN]
Definition: misc.h:72
get_signal
static void get_signal(volatile int *sig)
Copy the global signal_received (if non-zero) to the passed-in argument sig.
Definition: sig.h:110
MSG_NOSIGNAL
#define MSG_NOSIGNAL
Definition: socket.h:254
buf_read_u8
static int buf_read_u8(struct buffer *buf)
Definition: buffer.h:795
socks_proxy_info::authfile
char authfile[256]
Definition: socks.h:42
register_signal
void register_signal(struct signal_info *si, int signum, const char *signal_text)
Register a soft signal in the signal_info struct si respecting priority.
Definition: sig.c:231
print_openvpn_sockaddr
static const char * print_openvpn_sockaddr(const struct openvpn_sockaddr *addr, struct gc_arena *gc)
Definition: socket.h:363
user_pass
Definition: misc.h:56
socks_handshake
static bool socks_handshake(struct socks_proxy_info *p, socket_descriptor_t sd, struct event_timeout *server_poll_timeout, volatile int *signal_received)
Definition: socks.c:191
memdbg.h
msg
#define msg(flags,...)
Definition: error.h:144
buf_defined
static bool buf_defined(const struct buffer *buf)
Definition: buffer.h:228
socks_username_password_auth
static bool socks_username_password_auth(struct socks_proxy_info *p, socket_descriptor_t sd, struct event_timeout *server_poll_timeout, volatile int *signal_received)
Definition: socks.c:87
socks_proxy_info::server
char server[128]
Definition: socks.h:40
cleanup
static int cleanup(void **state)
Definition: test_pkcs11.c:280