Put a break on requests that run around in circles.
authorGuus Sliepen <guus@tinc-vpn.org>
Thu, 21 Mar 2002 23:11:53 +0000 (23:11 +0000)
committerGuus Sliepen <guus@tinc-vpn.org>
Thu, 21 Mar 2002 23:11:53 +0000 (23:11 +0000)
src/protocol.c
src/protocol.h
src/protocol_edge.c
src/protocol_key.c
src/protocol_subnet.c

index 9b30a8a..4e63728 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: protocol.c,v 1.28.4.123 2002/02/27 22:37:54 guus Exp $
+    $Id: protocol.c,v 1.28.4.124 2002/03/21 23:11:53 guus Exp $
 */
 
 #include "config.h"
 */
 
 #include "config.h"
@@ -32,6 +32,7 @@
 #include <errno.h>
 
 #include <utils.h>
 #include <errno.h>
 
 #include <utils.h>
+#include <xalloc.h>
 
 #include "conf.h"
 #include "protocol.h"
 
 #include "conf.h"
 #include "protocol.h"
@@ -40,6 +41,8 @@
 
 #include "system.h"
 
 
 #include "system.h"
 
+avl_tree_t *past_request_tree;
+
 int check_id(char *id)
 {
   int i;
 int check_id(char *id)
 {
   int i;
@@ -143,6 +146,66 @@ cp
   return 0;
 }
 
   return 0;
 }
 
+int request_compare(past_request_t *a, past_request_t *b)
+{
+cp
+  return strcmp(a->request, b->request);
+}
+
+void init_requests(void)
+{
+cp
+  past_request_tree = avl_alloc_tree((avl_compare_t)request_compare, (avl_action_t)free);
+cp
+}
+
+void exit_request(void)
+{
+cp
+  avl_delete_tree(past_request_tree);
+cp
+}
+
+int seen_request(char *request)
+{
+  past_request_t p, *new;
+cp
+  p.request = request;
+
+  if(avl_search(past_request_tree, &p))
+    return 1;
+  else
+    {
+      new = (past_request_t *)xmalloc(sizeof(*new));
+      new->request = xstrdup(request);
+      new->firstseen = now;
+      avl_insert(past_request_tree, new);
+      return 0;
+    }
+cp  
+}
+
+void age_past_requests(void)
+{
+  avl_node_t *node, *next;
+  past_request_t *p;
+  int left = 0, deleted = 0;
+cp 
+  for(node = past_request_tree->head; node; node = next)
+    {
+      next = node->next;
+      p = (past_request_t *)node->data;
+      if(p->firstseen + pingtimeout < now)
+        avl_delete_node(past_request_tree, node), deleted++;
+      else
+        left++;
+    }
+
+  if(debug_lvl >= DEBUG_SCARY_THINGS && left + deleted)
+    syslog(LOG_DEBUG, _("Aging past requests: deleted %d, left %d\n"), deleted, left);
+cp
+}
+
 /* Jumptable for the request handlers */
 
 int (*request_handlers[])(connection_t*) = {
 /* Jumptable for the request handlers */
 
 int (*request_handlers[])(connection_t*) = {
index c265502..258642c 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: protocol.h,v 1.5.4.27 2002/02/26 23:26:41 guus Exp $
+    $Id: protocol.h,v 1.5.4.28 2002/03/21 23:11:53 guus Exp $
 */
 
 #ifndef __TINC_PROTOCOL_H__
 */
 
 #ifndef __TINC_PROTOCOL_H__
@@ -31,7 +31,7 @@
    incompatible version have different protocols.
  */
 
    incompatible version have different protocols.
  */
 
-#define PROT_CURRENT 13
+#define PROT_CURRENT 14
 
 /* Request numbers */
 
 
 /* Request numbers */
 
@@ -48,6 +48,11 @@ enum {
   LAST                               /* Guardian for the highest request number */
 };
 
   LAST                               /* Guardian for the highest request number */
 };
 
+typedef struct past_request_t {
+  char *request;
+  time_t firstseen;
+} past_request_t;
+
 /* Maximum size of strings in a request */
 
 #define MAX_STRING_SIZE 2048
 /* Maximum size of strings in a request */
 
 #define MAX_STRING_SIZE 2048
index 0c5ca35..4fd5354 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: protocol_edge.c,v 1.1.4.2 2002/02/18 16:25:18 guus Exp $
+    $Id: protocol_edge.c,v 1.1.4.3 2002/03/21 23:11:53 guus Exp $
 */
 
 #include "config.h"
 */
 
 #include "config.h"
@@ -55,7 +55,7 @@ cp
   sockaddr2str(&e->from.udpaddress, &from_udpaddress, &from_udpport);
   sockaddr2str(&e->to.tcpaddress, &to_tcpaddress, &to_tcpport);
   sockaddr2str(&e->to.udpaddress, &to_udpaddress, &to_udpport);
   sockaddr2str(&e->from.udpaddress, &from_udpaddress, &from_udpport);
   sockaddr2str(&e->to.tcpaddress, &to_tcpaddress, &to_tcpport);
   sockaddr2str(&e->to.udpaddress, &to_udpaddress, &to_udpport);
-  x = send_request(c, "%d %s %s %s %s %s %s %s %s %lx %d", ADD_EDGE,
+  x = send_request(c, "%d %lx %s %s %s %s %s %s %s %s %lx %d", ADD_EDGE, random(),
                       e->from.node->name, from_tcpaddress, from_tcpport, from_udpport,
                      e->to.node->name, to_tcpaddress, to_tcpport, to_udpport,
                      e->options, e->weight);
                       e->from.node->name, from_tcpaddress, from_tcpport, from_udpport,
                      e->to.node->name, to_tcpaddress, to_tcpport, to_udpport,
                      e->options, e->weight);
@@ -90,7 +90,7 @@ int add_edge_h(connection_t *c)
   int weight;
   avl_node_t *node;
 cp
   int weight;
   avl_node_t *node;
 cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d",
+  if(sscanf(c->buffer, "%*d %*lx "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d",
             from_name, from_address, from_tcpport, from_udpport,
            to_name, to_address, to_tcpport, to_udpport,
            &options, &weight) != 10)
             from_name, from_address, from_tcpport, from_udpport,
            to_name, to_address, to_tcpport, to_udpport,
            &options, &weight) != 10)
@@ -113,6 +113,9 @@ cp
       return -1;
     }
 
       return -1;
     }
 
+  if(seen_request(c->buffer))
+    return 0;
+
   /* Lookup nodes */
 
   from = lookup_node(from_name);
   /* Lookup nodes */
 
   from = lookup_node(from_name);
@@ -180,8 +183,6 @@ cp
     return 0;
   }
 
     return 0;
   }
 
-
-
   e = new_edge();
   e->from.node = from;
   e->from.tcpaddress = from_tcpaddress;
   e = new_edge();
   e->from.node = from;
   e->from.tcpaddress = from_tcpaddress;
@@ -199,7 +200,7 @@ cp
     {
       other = (connection_t *)node->data;
       if(other->status.active && other != c)
     {
       other = (connection_t *)node->data;
       if(other->status.active && other != c)
-        send_add_edge(other, e);
+        send_request(other, "%s", c->buffer);
     }
 
   /* Run MST before or after we tell the rest? */
     }
 
   /* Run MST before or after we tell the rest? */
@@ -212,7 +213,7 @@ cp
 int send_del_edge(connection_t *c, edge_t *e)
 {
 cp
 int send_del_edge(connection_t *c, edge_t *e)
 {
 cp
-  return send_request(c, "%d %s %s", DEL_EDGE,
+  return send_request(c, "%d %lx %s %s", DEL_EDGE, random(),
                       e->from.node->name, e->to.node->name);
 }
 
                       e->from.node->name, e->to.node->name);
 }
 
@@ -225,7 +226,7 @@ int del_edge_h(connection_t *c)
   connection_t *other;
   avl_node_t *node;
 cp
   connection_t *other;
   avl_node_t *node;
 cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING"", from_name, to_name) != 2)
+  if(sscanf(c->buffer, "%*d %*lx "MAX_STRING" "MAX_STRING"", from_name, to_name) != 2)
     {
       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_EDGE",
              c->name, c->hostname);
     {
       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_EDGE",
              c->name, c->hostname);
@@ -246,6 +247,9 @@ cp
       return -1;
     }
 
       return -1;
     }
 
+  if(seen_request(c->buffer))
+    return 0;
+
   /* Lookup nodes */
 
   from = lookup_node(from_name);
   /* Lookup nodes */
 
   from = lookup_node(from_name);
@@ -291,7 +295,7 @@ cp
     {
       other = (connection_t *)node->data;
       if(other->status.active && other != c)
     {
       other = (connection_t *)node->data;
       if(other->status.active && other != c)
-        send_del_edge(other, e);
+        send_request(other, "%s", c->buffer);
     }
 
   /* Delete the edge */
     }
 
   /* Delete the edge */
index b85de5e..dc44b53 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: protocol_key.c,v 1.1.4.4 2002/02/27 22:37:55 guus Exp $
+    $Id: protocol_key.c,v 1.1.4.5 2002/03/21 23:11:53 guus Exp $
 */
 
 #include "config.h"
 */
 
 #include "config.h"
@@ -61,8 +61,8 @@ cp
   for(node = connection_tree->head; node; node = node->next)
     {
       other = (connection_t *)node->data;
   for(node = connection_tree->head; node; node = node->next)
     {
       other = (connection_t *)node->data;
-      if(other->status.active && other->status.mst && other != c)
-        send_request(other, "%d %s", KEY_CHANGED, n->name);
+      if(other->status.active && other != c)
+        send_request(other, "%d %lx %s", KEY_CHANGED, random(), n->name);
     }
 cp
   return 0;
     }
 cp
   return 0;
@@ -71,15 +71,20 @@ cp
 int key_changed_h(connection_t *c)
 {
   char name[MAX_STRING_SIZE];
 int key_changed_h(connection_t *c)
 {
   char name[MAX_STRING_SIZE];
+  avl_node_t *node;
+  connection_t *other;
   node_t *n;
 cp
   node_t *n;
 cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING, name) != 1)
+  if(sscanf(c->buffer, "%*d %*lx "MAX_STRING, name) != 1)
     {
       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "KEY_CHANGED",
              c->name, c->hostname);
       return -1;
     }
 
     {
       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "KEY_CHANGED",
              c->name, c->hostname);
       return -1;
     }
 
+  if(seen_request(c->buffer))
+    return 0;
+
   n = lookup_node(name);
 
   if(!n)
   n = lookup_node(name);
 
   if(!n)
@@ -93,7 +98,14 @@ cp
   n->status.waitingforkey = 0;
   n->sent_seqno = 0;
 
   n->status.waitingforkey = 0;
   n->sent_seqno = 0;
 
-  send_key_changed(c, n);
+  /* Tell the others */
+
+  for(node = connection_tree->head; node; node = node->next)
+    {
+      other = (connection_t *)node->data;
+      if(other->status.active && other != c)
+        send_request(other, "%s", c->buffer);
+    }
 cp
   return 0;
 }
 cp
   return 0;
 }
index fbb021d..3cea347 100644 (file)
@@ -17,7 +17,7 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: protocol_subnet.c,v 1.1.4.1 2002/02/11 10:05:58 guus Exp $
+    $Id: protocol_subnet.c,v 1.1.4.2 2002/03/21 23:11:53 guus Exp $
 */
 
 #include "config.h"
 */
 
 #include "config.h"
@@ -50,7 +50,7 @@ int send_add_subnet(connection_t *c, subnet_t *subnet)
   int x;
   char *netstr;
 cp
   int x;
   char *netstr;
 cp
-  x = send_request(c, "%d %s %s", ADD_SUBNET,
+  x = send_request(c, "%d %lx %s %s", ADD_SUBNET, random(),
                       subnet->owner->name, netstr = net2str(subnet));
   free(netstr);
 cp
                       subnet->owner->name, netstr = net2str(subnet));
   free(netstr);
 cp
@@ -66,7 +66,7 @@ int add_subnet_h(connection_t *c)
   subnet_t *s;
   avl_node_t *node;
 cp
   subnet_t *s;
   avl_node_t *node;
 cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
+  if(sscanf(c->buffer, "%*d %*lx "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
     {
       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_SUBNET", c->name, c->hostname);
       return -1;
     {
       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_SUBNET", c->name, c->hostname);
       return -1;
@@ -88,6 +88,9 @@ cp
       return -1;
     }
 
       return -1;
     }
 
+  if(seen_request(c->buffer))
+    return 0;
   /* Check if the owner of the new subnet is in the connection list */
 
   owner = lookup_node(name);
   /* Check if the owner of the new subnet is in the connection list */
 
   owner = lookup_node(name);
@@ -128,7 +131,7 @@ cp
     {
       other = (connection_t *)node->data;
       if(other->status.active && other != c)
     {
       other = (connection_t *)node->data;
       if(other->status.active && other != c)
-        send_add_subnet(other, s);
+        send_request(other, "%s", c->buffer);
     }
 cp
   return 0;
     }
 cp
   return 0;
@@ -140,7 +143,7 @@ int send_del_subnet(connection_t *c, subnet_t *s)
   char *netstr;
 cp
   netstr = net2str(s);
   char *netstr;
 cp
   netstr = net2str(s);
-  x = send_request(c, "%d %s %s", DEL_SUBNET, s->owner->name, netstr);
+  x = send_request(c, "%d %lx %s %s", DEL_SUBNET, random(), s->owner->name, netstr);
   free(netstr);
 cp
   return x;
   free(netstr);
 cp
   return x;
@@ -155,7 +158,7 @@ int del_subnet_h(connection_t *c)
   subnet_t *s, *find;
   avl_node_t *node;
 cp
   subnet_t *s, *find;
   avl_node_t *node;
 cp
-  if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
+  if(sscanf(c->buffer, "%*d %*lx "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
     {
       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_SUBNET", c->name, c->hostname);
       return -1;
     {
       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_SUBNET", c->name, c->hostname);
       return -1;
@@ -187,6 +190,9 @@ cp
       return -1;
     }
 
       return -1;
     }
 
+  if(seen_request(c->buffer))
+    return 0;
+
   /* If everything is correct, delete the subnet from the list of the owner */
 
   s->owner = owner;
   /* If everything is correct, delete the subnet from the list of the owner */
 
   s->owner = owner;
@@ -219,7 +225,7 @@ cp
     {
       other = (connection_t *)node->data;
       if(other->status.active && other != c)
     {
       other = (connection_t *)node->data;
       if(other->status.active && other != c)
-        send_del_subnet(other, find);
+        send_request(other, "%s", c->buffer);
     }
 
   /* Finally, delete it. */
     }
 
   /* Finally, delete it. */