cfengine  3.15.4
About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version.
  Fossies Dox: cfengine-3.15.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

net.c
Go to the documentation of this file.
1 /*
2  Copyright 2019 Northern.tech AS
3 
4  This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the
8  Free Software Foundation; version 3.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 
19  To the extent this program is licensed as part of the Enterprise
20  versions of CFEngine, the applicable Commercial Open Source License
21  (COSL) may apply to this file if you as a licensee so wish it. See
22  included file COSL.txt.
23 */
24 
25 #include <platform.h>
26 #include <cfnet.h> /* CF_BUFSIZE */
27 #include <net.h>
28 #include <classic.h>
29 #include <tls_generic.h>
30 #include <connection_info.h>
31 #include <logging.h>
32 #include <misc_lib.h>
33 #include <cf3.defs.h>
34 #include <protocol.h>
35 
36 
37 /* TODO remove libpromises dependency. */
38 extern char BINDINTERFACE[CF_MAXVARSIZE]; /* cf3globals.c, cf3.extern.h */
39 
40 void SetBindInterface(const char *ip)
41 {
42  strlcpy(BINDINTERFACE, ip, sizeof(BINDINTERFACE));
43  Log(LOG_LEVEL_VERBOSE, "Setting bindtointerface to '%s'", BINDINTERFACE);
44 }
45 
46 
47 /**
48  * @param len is the number of bytes to send, or 0 if buffer is a
49  * '\0'-terminated string so strlen(buffer) can be used.
50  * @return -1 in case of error or connection closed
51  * (also currently returns 0 for success but don't count on it)
52  * @NOTE #buffer can't be of zero length, our protocol
53  * does not allow empty transactions!
54  * @NOTE (len <= CF_BUFSIZE - CF_INBAND_OFFSET)
55  *
56  * @TODO Currently only transactions up to CF_BUFSIZE-CF_INBAND_OFFSET are
57  * allowed to be sent. This function should be changed to allow up to
58  * CF_BUFSIZE-1 (since '\0' is not sent, but the receiver needs space to
59  * append it). So transaction length will be at most 4095!
60  */
62  const char *buffer, int len, char status)
63 {
64  assert(status == CF_MORE || status == CF_DONE);
65 
66  char work[CF_BUFSIZE] = { 0 };
67  int ret;
68 
69  if (len == 0)
70  {
71  len = strlen(buffer);
72  }
73 
74  /* Not allowed to send zero-payload packets */
75  assert(len > 0);
76 
77  if (len > CF_BUFSIZE - CF_INBAND_OFFSET)
78  {
79  Log(LOG_LEVEL_ERR, "SendTransaction: len (%d) > %d - %d",
81  return -1;
82  }
83 
84  snprintf(work, CF_INBAND_OFFSET, "%c %d", status, len);
85 
86  memcpy(work + CF_INBAND_OFFSET, buffer, len);
87 
88  Log(LOG_LEVEL_DEBUG, "SendTransaction header: %s", work);
89  LogRaw(LOG_LEVEL_DEBUG, "SendTransaction data: ",
90  work + CF_INBAND_OFFSET, len);
91 
92  switch (ProtocolClassicOrTLS(conn_info->protocol))
93  {
94 
96  ret = SendSocketStream(conn_info->sd, work,
97  len + CF_INBAND_OFFSET);
98  break;
99 
100  case CF_PROTOCOL_TLS:
101  ret = TLSSend(conn_info->ssl, work, len + CF_INBAND_OFFSET);
102  if (ret <= 0)
103  {
104  ret = -1;
105  }
106  break;
107 
108  default:
109  UnexpectedError("SendTransaction: ProtocolVersion %d!",
110  conn_info->protocol);
111  ret = -1;
112  }
113 
114  if (ret == -1)
115  {
116  /* We are experiencing problems with sending data to server.
117  * This might lead to packages being not delivered in correct
118  * order and unexpected issues like directories being replaced
119  * with files.
120  * In order to make sure that file transfer is reliable we have to
121  * close connection to avoid broken packages being received. */
123  return -1;
124  }
125  else
126  {
127  /* SSL_MODE_AUTO_RETRY guarantees no partial writes. */
128  assert(ret == len + CF_INBAND_OFFSET);
129 
130  return 0;
131  }
132 }
133 
134 /*************************************************************************/
135 
136 /**
137  * Receive a transaction packet of at most CF_BUFSIZE-1 bytes, and
138  * NULL-terminate it.
139  *
140  * @param #buffer must be of size at least CF_BUFSIZE.
141  *
142  * @return -1 in case of closed socket, other error or timeout.
143  * The connection MAY NOT BE FINALISED!
144  * >0 the number of bytes read, transaction was successfully received.
145  *
146  * @TODO shutdown() the connection in all cases were this function returns -1,
147  * in order to protect against future garbage reads.
148  */
149 int ReceiveTransaction(ConnectionInfo *conn_info, char *buffer, int *more)
150 {
151  char proto[CF_INBAND_OFFSET + 1] = { 0 };
152  int ret;
153 
154  /* Get control channel. */
155  switch (ProtocolClassicOrTLS(conn_info->protocol))
156  {
157  case CF_PROTOCOL_CLASSIC:
158  ret = RecvSocketStream(conn_info->sd, proto, CF_INBAND_OFFSET);
159  break;
160  case CF_PROTOCOL_TLS:
161  ret = TLSRecv(conn_info->ssl, proto, CF_INBAND_OFFSET);
162  break;
163  default:
164  UnexpectedError("ReceiveTransaction: ProtocolVersion %d!",
165  conn_info->protocol);
166  ret = -1;
167  }
168 
169  /* If error occurred or recv() timeout or if connection was gracefully
170  * closed. Connection has been finalised. */
171  if (ret <= 0)
172  {
173  /* We are experiencing problems with receiving data from server.
174  * This might lead to packages being not delivered in correct
175  * order and unexpected issues like directories being replaced
176  * with files.
177  * In order to make sure that file transfer is reliable we have to
178  * close connection to avoid broken packages being received. */
180  return -1;
181  }
182  else if (ret != CF_INBAND_OFFSET)
183  {
184  /* If we received less bytes than expected. Might happen
185  * with TLSRecv(). */
187  "ReceiveTransaction: bogus short header (%d bytes: '%s')",
188  ret, proto);
190  return -1;
191  }
192 
193  LogRaw(LOG_LEVEL_DEBUG, "ReceiveTransaction header: ", proto, ret);
194 
195  char status = 'x';
196  int len = 0;
197 
198  ret = sscanf(proto, "%c %d", &status, &len);
199  if (ret != 2)
200  {
202  "ReceiveTransaction: bogus header: %s", proto);
204  return -1;
205  }
206 
207  if (status != CF_MORE && status != CF_DONE)
208  {
210  "ReceiveTransaction: bogus header (more='%c')", status);
212  return -1;
213  }
214  if (len > CF_BUFSIZE - CF_INBAND_OFFSET)
215  {
217  "ReceiveTransaction: packet too long (len=%d)", len);
219  return -1;
220  }
221  else if (len <= 0)
222  {
223  /* Zero-length packets are disallowed, because
224  * ReceiveTransaction() == 0 currently means connection closed. */
226  "ReceiveTransaction: packet too short (len=%d)", len);
228  return -1;
229  }
230 
231  if (more != NULL)
232  {
233  switch (status)
234  {
235  case CF_MORE:
236  *more = true;
237  break;
238  case CF_DONE:
239  *more = false;
240  break;
241  default:
242  ProgrammingError("Unreachable, "
243  "bogus headers have already been checked!");
244  }
245  }
246 
247  /* Get data. */
248  switch (ProtocolClassicOrTLS(conn_info->protocol))
249  {
250  case CF_PROTOCOL_CLASSIC:
251  ret = RecvSocketStream(conn_info->sd, buffer, len);
252  break;
253  case CF_PROTOCOL_TLS:
254  ret = TLSRecv(conn_info->ssl, buffer, len);
255  break;
256  default:
257  UnexpectedError("ReceiveTransaction: ProtocolVersion %d!",
258  conn_info->protocol);
259  ret = -1;
260  }
261 
262  /* Connection gracefully closed (ret==0) or connection error (ret==-1) or
263  * just partial receive of bytestream.*/
264  if (ret != len)
265  {
266  /*
267  * Should never happen except with TLS, given that we are using
268  * SSL_MODE_AUTO_RETRY and that transaction payload < CF_BUFSIZE < TLS
269  * record size, it can currently only happen if the other side does
270  * TLSSend(wrong_number) for the transaction.
271  *
272  * TODO IMPORTANT terminate TLS session in that case.
273  */
275  "Partial transaction read %d != %d bytes!",
276  ret, len);
278  return -1;
279  }
280 
281  LogRaw(LOG_LEVEL_DEBUG, "ReceiveTransaction data: ", buffer, ret);
282 
283  return ret;
284 }
285 
286 /* BWlimit global variables
287 
288  Throttling happens for all network interfaces, all traffic being sent for
289  any connection of this process (cf-agent or cf-serverd).
290  We need a lock, to avoid concurrent writes to "bwlimit_next".
291  Then, "bwlimit_next" is the absolute time (as of clock_gettime() ) that we
292  are clear to send, after. It is incremented with the delay for every packet
293  scheduled for sending. Thus, integer arithmetic will make sure we wait for
294  the correct amount of time, in total.
295  */
296 
297 #ifndef _WIN32
298 static pthread_mutex_t bwlimit_lock = PTHREAD_MUTEX_INITIALIZER;
299 static struct timespec bwlimit_next = {0, 0L};
300 #endif
301 
302 uint32_t bwlimit_kbytes = 0; /* desired limit, in kB/s */
303 
304 
305 /** Throttle traffic, if next packet happens too soon after the previous one
306  *
307  * This function is global, across all network operations (and interfaces, perhaps)
308  * @param tosend Length of current packet being sent out (in bytes)
309  */
310 
311 #ifdef CLOCK_MONOTONIC
312 # define PREFERRED_CLOCK CLOCK_MONOTONIC
313 #else
314 /* Some OS-es don't have monotonic clock, but we can still use the
315  * next available one */
316 # define PREFERRED_CLOCK CLOCK_REALTIME
317 #endif
318 
319 void EnforceBwLimit(int tosend)
320 {
321  if (!bwlimit_kbytes)
322  {
323  /* early return, before any expensive syscalls */
324  return;
325  }
326 
327 #ifdef _WIN32
328  Log(LOG_LEVEL_WARNING, "Bandwidth limiting with \"bwlimit\" is not supported on Windows.");
329  (void)tosend; // Avoid "unused" warning.
330  return;
331 #else
332 
333  const uint32_t u_10e6 = 1000000L;
334  const uint32_t u_10e9 = 1000000000L;
335  struct timespec clock_now = {0, 0L};
336 
337  if (pthread_mutex_lock(&bwlimit_lock) == 0)
338  {
339  clock_gettime(PREFERRED_CLOCK, &clock_now);
340 
341  if ((bwlimit_next.tv_sec < clock_now.tv_sec) ||
342  ( (bwlimit_next.tv_sec == clock_now.tv_sec) &&
343  (bwlimit_next.tv_nsec < clock_now.tv_nsec) ) )
344  {
345  /* penalty has expired, we can immediately send data. But reset the timestamp */
346  bwlimit_next = clock_now;
347  clock_now.tv_sec = 0;
348  clock_now.tv_nsec = 0L;
349  }
350  else
351  {
352  clock_now.tv_sec = bwlimit_next.tv_sec - clock_now.tv_sec;
353  clock_now.tv_nsec = bwlimit_next.tv_nsec - clock_now.tv_nsec;
354  if (clock_now.tv_nsec < 0L)
355  {
356  clock_now.tv_sec --;
357  clock_now.tv_nsec += u_10e9;
358  }
359  }
360 
361  uint64_t delay = ((uint64_t) tosend * u_10e6) / bwlimit_kbytes; /* in ns */
362 
363  bwlimit_next.tv_sec += (delay / u_10e9);
364  bwlimit_next.tv_nsec += (long) (delay % u_10e9);
365  if (bwlimit_next.tv_nsec >= u_10e9)
366  {
367  bwlimit_next.tv_sec++;
368  bwlimit_next.tv_nsec -= u_10e9;
369  }
370 
371  if (bwlimit_next.tv_sec > 20)
372  {
373  /* Upper limit of 20sec for penalty. This will avoid huge wait if
374  * our clock has jumped >minutes back in time. Still, assuming that
375  * most of our packets are <= 2048 bytes, the lower bwlimit is bound
376  * to 102.4 Bytes/sec. With 65k packets (rare) is 3.7kBytes/sec in
377  * that extreme case.
378  * With more clients hitting a single server, this lower bound is
379  * multiplied by num of clients, eg. 102.4kBytes/sec for 1000 reqs.
380  * simultaneously.
381  */
382  bwlimit_next.tv_sec = 20;
383  }
384  pthread_mutex_unlock(&bwlimit_lock);
385  }
386 
387  /* Even if we push our data every few bytes to the network interface,
388  the software+hardware buffers will queue it and send it in bursts,
389  anyway. It is more likely that we will waste CPU sys-time calling
390  nanosleep() for such short delays.
391  So, sleep only if we have >1ms penalty
392  */
393  if (clock_now.tv_sec > 0 || ( (clock_now.tv_sec == 0) && (clock_now.tv_nsec >= u_10e6)) )
394  {
395  nanosleep(&clock_now, NULL);
396  }
397 #endif // !_WIN32
398 }
399 
400 
401 /*************************************************************************/
402 
403 
404 /**
405  Tries to connect() to server #host, returns the socket descriptor and the
406  IP address that succeeded in #txtaddr.
407 
408  @param #connect_timeout how long to wait for connect(), zero blocks forever
409  @param #txtaddr If connected successfully return the IP connected in
410  textual representation
411  @return Connected socket descriptor or -1 in case of failure.
412 */
413 int SocketConnect(const char *host, const char *port,
414  unsigned int connect_timeout, bool force_ipv4,
415  char *txtaddr, size_t txtaddr_size)
416 {
417  struct addrinfo *response = NULL, *ap;
418  bool connected = false;
419  int sd = -1;
420 
421  struct addrinfo query = {
422  .ai_family = force_ipv4 ? AF_INET : AF_UNSPEC,
423  .ai_socktype = SOCK_STREAM
424  };
425 
426  int ret = getaddrinfo(host, port, &query, &response);
427  if (ret != 0)
428  {
430  "Unable to find host '%s' service '%s' (%s)",
431  host, port, gai_strerror(ret));
432  if (response != NULL)
433  {
434  freeaddrinfo(response);
435  }
436  return -1;
437  }
438 
439  for (ap = response; !connected && ap != NULL; ap = ap->ai_next)
440  {
441  /* Convert address to string. */
442  getnameinfo(ap->ai_addr, ap->ai_addrlen,
443  txtaddr, txtaddr_size,
444  NULL, 0, NI_NUMERICHOST);
446  "Connecting to host %s, port %s as address %s",
447  host, port, txtaddr);
448 
449  sd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
450  if (sd == -1)
451  {
452  Log(LOG_LEVEL_ERR, "Couldn't open a socket to '%s' (socket: %s)",
453  txtaddr, GetErrorStr());
454  }
455  else
456  {
457  /* Bind socket to specific interface, if requested. */
458  if (BINDINTERFACE[0] != '\0')
459  {
460  struct addrinfo query2 = {
461  .ai_family = force_ipv4 ? AF_INET : AF_UNSPEC,
462  .ai_socktype = SOCK_STREAM,
463  /* returned address is for bind() */
464  .ai_flags = AI_PASSIVE
465  };
466 
467  struct addrinfo *response2 = NULL, *ap2;
468  int ret2 = getaddrinfo(BINDINTERFACE, NULL, &query2, &response2);
469  if (ret2 != 0)
470  {
472  "Unable to lookup interface '%s' to bind. (getaddrinfo: %s)",
473  BINDINTERFACE, gai_strerror(ret2));
474 
475  if (response2 != NULL)
476  {
477  freeaddrinfo(response2);
478  }
479  assert(response); /* first getaddrinfo was successful */
480  freeaddrinfo(response);
481  cf_closesocket(sd);
482  return -1;
483  }
484 
485  for (ap2 = response2; ap2 != NULL; ap2 = ap2->ai_next)
486  {
487  if (bind(sd, ap2->ai_addr, ap2->ai_addrlen) == 0)
488  {
489  break;
490  }
491  }
492  if (ap2 == NULL)
493  {
495  "Unable to bind to interface '%s'. (bind: %s)",
497  }
498  assert(response2); /* second getaddrinfo was successful */
499  freeaddrinfo(response2);
500  }
501 
502  connected = TryConnect(sd, connect_timeout * 1000,
503  ap->ai_addr, ap->ai_addrlen);
504  if (!connected)
505  {
506  Log(LOG_LEVEL_VERBOSE, "Unable to connect to address %s (%s)",
507  txtaddr, GetErrorStr());
508  cf_closesocket(sd);
509  sd = -1;
510  }
511  }
512  }
513 
514  assert(response != NULL); /* first getaddrinfo was successful */
515  freeaddrinfo(response);
516 
517  if (connected)
518  {
520  "Connected to host %s address %s port %s (socket descriptor %d)",
521  host, txtaddr, port, sd);
522  }
523  else
524  {
526  "Unable to connect to host %s port %s (socket descriptor %d)",
527  host, port, sd);
528  }
529 
530  return sd;
531 }
532 
533 
534 #if !defined(__MINGW32__)
535 
536 #if defined(__hpux) && defined(__GNUC__)
537 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
538 // HP-UX GCC type-pun warning on FD_SET() macro:
539 // While the "fd_set" type is defined in /usr/include/sys/_fd_macros.h as a
540 // struct of an array of "long" values in accordance with the XPG4 standard's
541 // requirements, the macros for the FD operations "pretend it is an array of
542 // int32_t's so the binary layout is the same for both Narrow and Wide
543 // processes," as described in _fd_macros.h. In the FD_SET, FD_CLR, and
544 // FD_ISSET macros at line 101, the result is cast to an "__fd_mask *" type,
545 // which is defined as int32_t at _fd_macros.h:82.
546 //
547 // This conflict between the "long fds_bits[]" array in the XPG4-compliant
548 // fd_set structure, and the cast to an int32_t - not long - pointer in the
549 // macros, causes a type-pun warning if -Wstrict-aliasing is enabled.
550 // The warning is merely a side effect of HP-UX working as designed,
551 // so it can be ignored.
552 #endif
553 
554 /**
555  * Tries to connect for #timeout_ms milliseconds. On success sets the recv()
556  * timeout to #timeout_ms as well.
557  *
558  * @param #timeout_ms How long to wait for connect(), if zero wait forever.
559  * @return true on success, false otherwise.
560  **/
561 bool TryConnect(int sd, unsigned long timeout_ms,
562  const struct sockaddr *sa, socklen_t sa_len)
563 {
564  assert(sd != -1);
565  assert(sa != NULL);
566 
567  if (sd >= FD_SETSIZE)
568  {
570  "Open connections exceed FD_SETSIZE limit (%d >= %d)",
571  sd, FD_SETSIZE);
572  return false;
573  }
574 
575  /* set non-blocking socket */
576  int arg = fcntl(sd, F_GETFL, NULL);
577  int ret = fcntl(sd, F_SETFL, arg | O_NONBLOCK);
578  if (ret == -1)
579  {
581  "Failed to set socket to non-blocking mode (fcntl: %s)",
582  GetErrorStr());
583  }
584 
585  ret = connect(sd, sa, sa_len);
586  if (ret == -1)
587  {
588  if (errno != EINPROGRESS)
589  {
590  Log(LOG_LEVEL_INFO, "Failed to connect to server (connect: %s)",
591  GetErrorStr());
592  return false;
593  }
594 
595  int errcode;
596  socklen_t opt_len = sizeof(errcode);
597  fd_set myset;
598  FD_ZERO(&myset);
599  FD_SET(sd, &myset);
600 
601  Log(LOG_LEVEL_VERBOSE, "Waiting to connect...");
602 
603  struct timeval tv, *tvp;
604  if (timeout_ms > 0)
605  {
606  tv.tv_sec = timeout_ms / 1000;
607  tv.tv_usec = (timeout_ms % 1000) * 1000;
608  tvp = &tv;
609  }
610  else
611  {
612  tvp = NULL; /* wait indefinitely */
613  }
614 
615  ret = select(sd + 1, NULL, &myset, NULL, tvp);
616  if (ret == 0)
617  {
618  Log(LOG_LEVEL_INFO, "Timeout connecting to server");
619  return false;
620  }
621  if (ret == -1)
622  {
623  if (errno == EINTR)
624  {
626  "Socket connect was interrupted by signal");
627  }
628  else
629  {
631  "Failure while connecting (select: %s)",
632  GetErrorStr());
633  }
634  return false;
635  }
636 
637  ret = getsockopt(sd, SOL_SOCKET, SO_ERROR,
638  (void *) &errcode, &opt_len);
639  if (ret == -1)
640  {
642  "Could not check connection status (getsockopt: %s)",
643  GetErrorStr());
644  return false;
645  }
646 
647  if (errcode != 0)
648  {
649  Log(LOG_LEVEL_INFO, "Failed to connect to server: %s",
650  GetErrorStrFromCode(errcode));
651  return false;
652  }
653  }
654 
655  /* Connection succeeded, return to blocking mode. */
656  ret = fcntl(sd, F_SETFL, arg);
657  if (ret == -1)
658  {
660  "Failed to set socket back to blocking mode (fcntl: %s)",
661  GetErrorStr());
662  }
663 
664  if (timeout_ms > 0)
665  {
666  SetReceiveTimeout(sd, timeout_ms);
667  }
668 
669  return true;
670 }
671 
672 #if defined(__hpux) && defined(__GNUC__)
673 #pragma GCC diagnostic warning "-Wstrict-aliasing"
674 #endif
675 
676 #endif /* !defined(__MINGW32__) */
677 
678 
679 
680 /**
681  * Set timeout for recv(), in milliseconds.
682  * @param ms must be > 0.
683  */
684 int SetReceiveTimeout(int fd, unsigned long ms)
685 {
686  assert(ms > 0);
687 
688  Log(LOG_LEVEL_VERBOSE, "Setting socket timeout to %lu seconds.", ms/1000);
689 
690 /* On windows SO_RCVTIMEO is set by a DWORD indicating the timeout in
691  * milliseconds, on UNIX it's a struct timeval. */
692 
693 #if !defined(__MINGW32__)
694  struct timeval tv = {
695  .tv_sec = ms / 1000,
696  .tv_usec = (ms % 1000) * 1000
697  };
698  int ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
699 #else
700  int ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &ms, sizeof(ms));
701 #endif
702 
703  if (ret != 0)
704  {
706  "Failed to set socket timeout to %lu milliseconds.", ms);
707  return -1;
708  }
709 
710  return 0;
711 }
#define CF_DONE
Definition: cfnet.h:45
#define CF_MORE
Definition: cfnet.h:46
#define CF_INBAND_OFFSET
Definition: cfnet.h:51
int cf_closesocket(int sd)
Definition: misc.c:31
int RecvSocketStream(int sd, char *buffer, int toget)
Receive up to #toget bytes, plus a '\0', into buffer from sd.
Definition: classic.c:64
int SendSocketStream(int sd, const char buffer[4096], int tosend)
Send #tosend bytes from buffer to sd.
Definition: classic.c:135
int clock_gettime(clockid_t clock_id, struct timespec *tp)
Definition: clock_gettime.c:30
@ CONNECTIONINFO_STATUS_BROKEN
#define CF_BUFSIZE
Definition: definitions.h:50
#define CF_MAXVARSIZE
Definition: definitions.h:36
void freeaddrinfo(struct addrinfo *res)
Definition: getaddrinfo.c:323
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hintp, struct addrinfo **res)
Definition: getaddrinfo.c:262
const char * gai_strerror(int errcode)
Definition: getaddrinfo.c:340
int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags)
Definition: getaddrinfo.c:476
int errno
#define NULL
Definition: getopt1.c:56
void LogRaw(LogLevel level, const char *prefix, const void *buf, size_t buflen)
Logs binary data in #buf, with unprintable bytes translated to '.'. Message is prefixed with #prefix.
Definition: logging.c:382
const char * GetErrorStrFromCode(int error_code)
Definition: logging.c:270
const char * GetErrorStr(void)
Definition: logging.c:275
void Log(LogLevel level, const char *fmt,...)
Definition: logging.c:409
@ LOG_LEVEL_ERR
Definition: logging.h:42
@ LOG_LEVEL_DEBUG
Definition: logging.h:47
@ LOG_LEVEL_WARNING
Definition: logging.h:43
@ LOG_LEVEL_VERBOSE
Definition: logging.h:46
@ LOG_LEVEL_INFO
Definition: logging.h:45
#define ProgrammingError(...)
Definition: misc_lib.h:33
#define UnexpectedError(...)
Definition: misc_lib.h:38
static struct timespec bwlimit_next
Definition: net.c:299
static pthread_mutex_t bwlimit_lock
Definition: net.c:298
char BINDINTERFACE[1024]
Definition: cf3globals.c:140
int SocketConnect(const char *host, const char *port, unsigned int connect_timeout, bool force_ipv4, char *txtaddr, size_t txtaddr_size)
Definition: net.c:413
uint32_t bwlimit_kbytes
Definition: net.c:302
void SetBindInterface(const char *ip)
Definition: net.c:40
int ReceiveTransaction(ConnectionInfo *conn_info, char *buffer, int *more)
Definition: net.c:149
#define PREFERRED_CLOCK
Definition: net.c:316
void EnforceBwLimit(int tosend)
Definition: net.c:319
int SetReceiveTimeout(int fd, unsigned long ms)
Definition: net.c:684
int SendTransaction(ConnectionInfo *conn_info, const char *buffer, int len, char status)
Definition: net.c:61
bool TryConnect(int sd, unsigned long timeout_ms, const struct sockaddr *sa, socklen_t sa_len)
Definition: net.c:561
int nanosleep(const struct timespec *req, struct timespec *rem)
int socklen_t
Definition: platform.h:419
static ProtocolVersion ProtocolClassicOrTLS(const ProtocolVersion p)
@ CF_PROTOCOL_CLASSIC
@ CF_PROTOCOL_TLS
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:34
ProtocolVersion protocol
ConnectionStatus status
int TLSRecv(SSL *ssl, char *buffer, int toget)
Receives at most #length bytes of data from the SSL session and stores it in the buffer.
Definition: tls_generic.c:737
int TLSSend(SSL *ssl, const char *buffer, int length)
Sends the data stored on the buffer using a TLS session.
Definition: tls_generic.c:669