Merge branch 'master' into 1.1
authorGuus Sliepen <guus@tinc-vpn.org>
Fri, 19 Nov 2010 12:22:48 +0000 (12:22 +0000)
committerGuus Sliepen <guus@tinc-vpn.org>
Fri, 19 Nov 2010 12:22:48 +0000 (12:22 +0000)
Conflicts:
src/net_packet.c
src/openssl/rsagen.h
src/protocol_auth.c
src/protocol_key.c

1  2 
src/dropin.c
src/linux/device.c
src/net.h
src/net_packet.c
src/net_setup.c
src/net_socket.c
src/node.c
src/node.h
src/process.c
src/protocol_key.c

diff --cc src/dropin.c
index 89039da34c024b6427d110cfea15ccee3c08acf9,0000000000000000000000000000000000000000..52fb5b8675bd3799eb8177e0df7222f4ecd5edbf
mode 100644,000000..100644
--- /dev/null
@@@ -1,165 -1,0 +1,172 @@@
 +/*
 +    dropin.c -- a set of drop-in replacements for libc functions
 +    Copyright (C) 2000-2005 Ivo Timmermans,
 +                  2000-2009 Guus Sliepen <guus@tinc-vpn.org>
 +
 +    This program is free software; you can redistribute it and/or modify
 +    it under the terms of the GNU General Public License as published by
 +    the Free Software Foundation; either version 2 of the License, or
 +    (at your option) any later version.
 +
 +    This program is distributed in the hope that it will be useful,
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +    GNU General Public License for more details.
 +
 +    You should have received a copy of the GNU General Public License along
 +    with this program; if not, write to the Free Software Foundation, Inc.,
 +    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 +*/
 +
 +#include "system.h"
 +
 +#include "xalloc.h"
 +
 +#ifndef HAVE_DAEMON
 +/*
 +  Replacement for the daemon() function.
 +  
 +  The daemon() function is for programs wishing to detach themselves
 +  from the controlling terminal and run in the background as system
 +  daemons.
 +
 +  Unless the argument nochdir is non-zero, daemon() changes the
 +  current working directory to the root (``/'').
 +
 +  Unless the argument noclose is non-zero, daemon() will redirect
 +  standard input, standard output and standard error to /dev/null.
 +*/
 +int daemon(int nochdir, int noclose) {
 +#ifdef HAVE_FORK
 +      pid_t pid;
 +      int fd;
 +
 +      pid = fork();
 +
 +      /* Check if forking failed */
 +      if(pid < 0) {
 +              perror("fork");
 +              exit(-1);
 +      }
 +
 +      /* If we are the parent, terminate */
 +      if(pid)
 +              exit(0);
 +
 +      /* Detach by becoming the new process group leader */
 +      if(setsid() < 0) {
 +              perror("setsid");
 +              return -1;
 +      }
 +
 +      /* Change working directory to the root (to avoid keeping mount
 +         points busy) */
 +      if(!nochdir) {
 +              chdir("/");
 +      }
 +
 +      /* Redirect stdin/out/err to /dev/null */
 +      if(!noclose) {
 +              fd = open("/dev/null", O_RDWR);
 +
 +              if(fd < 0) {
 +                      perror("opening /dev/null");
 +                      return -1;
 +              } else {
 +                      dup2(fd, 0);
 +                      dup2(fd, 1);
 +                      dup2(fd, 2);
 +              }
 +      }
 +
 +      return 0;
 +#else
 +      return -1;
 +#endif
 +}
 +#endif
 +
 +#ifndef HAVE_GET_CURRENT_DIR_NAME
 +/*
 +  Replacement for the GNU get_current_dir_name function:
 +
 +  get_current_dir_name will malloc(3) an array big enough to hold the
 +  current directory name.  If the environment variable PWD is set, and
 +  its value is correct, then that value will be returned.
 +*/
 +char *get_current_dir_name(void) {
 +      size_t size;
 +      char *buf;
 +      char *r;
 +
 +      /* Start with 100 bytes.  If this turns out to be insufficient to
 +         contain the working directory, double the size.  */
 +      size = 100;
 +      buf = xmalloc(size);
 +
 +      errno = 0;                                      /* Success */
 +      r = getcwd(buf, size);
 +
 +      /* getcwd returns NULL and sets errno to ERANGE if the bufferspace
 +         is insufficient to contain the entire working directory.  */
 +      while(r == NULL && errno == ERANGE) {
 +              free(buf);
 +              size <<= 1;                             /* double the size */
 +              buf = xmalloc(size);
 +              r = getcwd(buf, size);
 +      }
 +
 +      return buf;
 +}
 +#endif
 +
 +#ifndef HAVE_ASPRINTF
 +int asprintf(char **buf, const char *fmt, ...) {
 +      int result;
 +      va_list ap;
 +      va_start(ap, fmt);
 +      result = vasprintf(buf, fmt, ap);
 +      va_end(ap);
 +      return result;
 +}
 +
 +int vasprintf(char **buf, const char *fmt, va_list ap) {
 +      int status;
 +      va_list aq;
 +      int len;
 +
 +      len = 4096;
 +      *buf = xmalloc(len);
 +
 +      va_copy(aq, ap);
 +      status = vsnprintf(*buf, len, fmt, aq);
 +      va_end(aq);
 +
 +      if(status >= 0)
 +              *buf = xrealloc(*buf, status + 1);
 +
 +      if(status > len - 1) {
 +              len = status;
 +              va_copy(aq, ap);
 +              status = vsnprintf(*buf, len, fmt, aq);
 +              va_end(aq);
 +      }
 +
 +      return status;
 +}
 +#endif
 +
 +#ifndef HAVE_GETTIMEOFDAY
 +int gettimeofday(struct timeval *tv, void *tz) {
 +      tv->tv_sec = time(NULL);
 +      tv->tv_usec = 0;
 +      return 0;
 +}
 +#endif
++
++#ifdef HAVE_MINGW
++int usleep(long usec) {
++      Sleep(usec / 1000);
++      return 0;
++}
++#endif
Simple merge
diff --cc src/net.h
index f53c27a411896d5cc58ffcb30fc76bf72a350af5,55856e2b57c84618325dc7064cdd16f2dc697a26..9b625a0d9873c7a32723e55210559157c9df8ffc
+++ b/src/net.h
@@@ -111,9 -110,14 +112,11 @@@ extern unsigned replaywin
  
  extern listen_socket_t listen_socket[MAXSOCKETS];
  extern int listen_sockets;
 -extern int keyexpires;
  extern int keylifetime;
+ extern int udp_rcvbuf;
+ extern int udp_sndbuf;
  extern bool do_prune;
 -extern bool do_purge;
  extern char *myport;
 -extern time_t now;
  extern int contradicting_add_edge;
  extern int contradicting_del_edge;
  
index b444bc9310277605e4bec46108f25bd578eeba0f,9e5ef4654b3cc0ce007374cefe36724d67159986..7be466201eae816acca0d52ab3fd6ddcff545f92
@@@ -281,28 -293,35 +284,35 @@@ static void receive_udppacket(node_t *n
  
        /* Check the sequence number */
  
 -      inpkt->len -= sizeof(inpkt->seqno);
 +      inpkt->len -= sizeof inpkt->seqno;
        inpkt->seqno = ntohl(inpkt->seqno);
  
-       if(inpkt->seqno != n->received_seqno + 1) {
-               if(inpkt->seqno >= n->received_seqno + sizeof n->late * 8) {
-                       logger(LOG_WARNING, "Lost %d packets from %s (%s)",
-                                          inpkt->seqno - n->received_seqno - 1, n->name, n->hostname);
-                       
-                       memset(n->late, 0, sizeof n->late);
-               } else if (inpkt->seqno <= n->received_seqno) {
-                       if((n->received_seqno >= sizeof n->late * 8 && inpkt->seqno <= n->received_seqno - sizeof n->late * 8) || !(n->late[(inpkt->seqno / 8) % sizeof n->late] & (1 << inpkt->seqno % 8))) {
-                               logger(LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d",
-                                          n->name, n->hostname, inpkt->seqno, n->received_seqno);
-                               return;
+       if(replaywin) {
+               if(inpkt->seqno != n->received_seqno + 1) {
+                       if(inpkt->seqno >= n->received_seqno + replaywin * 8) {
+                               if(n->farfuture++ < replaywin >> 2) {
+                                       logger(LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)",
+                                               n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture);
+                                       return;
+                               }
+                               logger(LOG_WARNING, "Lost %d packets from %s (%s)",
+                                               inpkt->seqno - n->received_seqno - 1, n->name, n->hostname);
+                               memset(n->late, 0, replaywin);
+                       } else if (inpkt->seqno <= n->received_seqno) {
+                               if((n->received_seqno >= replaywin * 8 && inpkt->seqno <= n->received_seqno - replaywin * 8) || !(n->late[(inpkt->seqno / 8) % replaywin] & (1 << inpkt->seqno % 8))) {
+                                       logger(LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d",
+                                               n->name, n->hostname, inpkt->seqno, n->received_seqno);
+                                       return;
+                               }
+                       } else {
+                               for(i = n->received_seqno + 1; i < inpkt->seqno; i++)
+                                       n->late[(i / 8) % replaywin] |= 1 << i % 8;
                        }
-               } else {
-                       for(i = n->received_seqno + 1; i < inpkt->seqno; i++)
-                               n->late[(i / 8) % sizeof n->late] |= 1 << i % 8;
                }
+               n->farfuture = 0;
+               n->late[(inpkt->seqno / 8) % replaywin] &= ~(1 << inpkt->seqno % 8);
        }
-       
-       n->late[(inpkt->seqno / 8) % sizeof n->late] &= ~(1 << inpkt->seqno % 8);
  
        if(inpkt->seqno > n->received_seqno)
                n->received_seqno = inpkt->seqno;
diff --cc src/net_setup.c
Simple merge
index 44d7f77159c5d586ceb8fdb62438e5f6c5593538,2e6b068552d3838cbeb175c32f97637cf7d83fcc..e20076fbe00d9f97e71406f3c95c8193fddfa8c8
@@@ -258,8 -261,14 +260,14 @@@ int setup_vpn_in_socket(const sockaddr_
  #endif
  
        option = 1;
 -      setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
 +      setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
  
+       if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf)))
+               logger(LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, strerror(errno));
+       if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf)))
+               logger(LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, strerror(errno));
  #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
        if(sa->sa.sa_family == AF_INET6)
                setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
diff --cc src/node.c
index 0159f9dd965bc57c219805dac01868c5a614ee2a,7bcad892753ddaec91beca2793fdff48780dcc31..862bd69693ca9707e2ebd01076806e0e1bec43cf
@@@ -60,10 -52,13 +60,11 @@@ void exit_nodes(void) 
  }
  
  node_t *new_node(void) {
 -      node_t *n = xmalloc_and_zero(sizeof(*n));
 +      node_t *n = xmalloc_and_zero(sizeof *n);
  
+       if(replaywin) n->late = xmalloc_and_zero(replaywin);
        n->subnet_tree = new_subnet_tree();
        n->edge_tree = new_edge_tree();
 -      EVP_CIPHER_CTX_init(&n->inctx);
 -      EVP_CIPHER_CTX_init(&n->outctx);
        n->mtu = MTU;
        n->maxmtu = MTU;
  
diff --cc src/node.h
Simple merge
diff --cc src/process.c
Simple merge
index f57dc2ea059ff07d01d104c8e3df46b48c60287a,fbd7cabb8babafdd89fd09ac16a4fa46254bc8f8..ec5a690f600810044dc81bf7afc90a2c7c44a311
@@@ -156,17 -163,21 +156,17 @@@ bool send_ans_key(node_t *to) 
        // Reset sequence number and late packet window
        mykeyused = true;
        to->received_seqno = 0;
-       memset(to->late, 0, sizeof(to->late));
+       if(replaywin) memset(to->late, 0, replaywin);
  
 -      // Convert to hexadecimal and send
 -      char key[2 * to->inkeylength + 1];
 -      bin2hex(to->inkey, key, to->inkeylength);
 -      key[to->inkeylength * 2] = '\0';
 -
 -      return send_request(to->nexthop->connection, "%d %s %s %s %d %d %d %d", ANS_KEY,
 -                      myself->name, to->name, key,
 -                      to->incipher ? to->incipher->nid : 0,
 -                      to->indigest ? to->indigest->type : 0, to->inmaclength,
 -                      to->incompression);
 +      return send_request(to->nexthop->connection, "%d %s %s %s %d %d %zu %d", ANS_KEY,
 +                                              myself->name, to->name, key,
 +                                              cipher_get_nid(&to->incipher),
 +                                              digest_get_nid(&to->indigest),
 +                                              digest_length(&to->indigest),
 +                                              to->incompression);
  }
  
 -bool ans_key_h(connection_t *c) {
 +bool ans_key_h(connection_t *c, char *request) {
        char from_name[MAX_STRING_SIZE];
        char to_name[MAX_STRING_SIZE];
        char key[MAX_STRING_SIZE];