From 9da5390666ad532825d820b3554da3f39d3bc511 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 21 Mar 2002 23:11:53 +0000 Subject: [PATCH] Put a break on requests that run around in circles. --- src/protocol.c | 65 ++++++++++++++++++++++++++++++++++++++++++- src/protocol.h | 9 ++++-- src/protocol_edge.c | 22 +++++++++------ src/protocol_key.c | 22 +++++++++++---- src/protocol_subnet.c | 20 ++++++++----- 5 files changed, 114 insertions(+), 24 deletions(-) diff --git a/src/protocol.c b/src/protocol.c index 9b30a8a6..4e63728b 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -17,7 +17,7 @@ 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" @@ -32,6 +32,7 @@ #include #include +#include #include "conf.h" #include "protocol.h" @@ -40,6 +41,8 @@ #include "system.h" +avl_tree_t *past_request_tree; + int check_id(char *id) { int i; @@ -143,6 +146,66 @@ cp 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*) = { diff --git a/src/protocol.h b/src/protocol.h index c265502a..258642c1 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -17,7 +17,7 @@ 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__ @@ -31,7 +31,7 @@ incompatible version have different protocols. */ -#define PROT_CURRENT 13 +#define PROT_CURRENT 14 /* Request numbers */ @@ -48,6 +48,11 @@ enum { 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 diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 0c5ca353..4fd5354b 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -17,7 +17,7 @@ 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" @@ -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); - 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); @@ -90,7 +90,7 @@ int add_edge_h(connection_t *c) 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) @@ -113,6 +113,9 @@ cp return -1; } + if(seen_request(c->buffer)) + return 0; + /* Lookup nodes */ from = lookup_node(from_name); @@ -180,8 +183,6 @@ cp return 0; } - - 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) - send_add_edge(other, e); + send_request(other, "%s", c->buffer); } /* 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 - 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); } @@ -225,7 +226,7 @@ int del_edge_h(connection_t *c) 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); @@ -246,6 +247,9 @@ cp return -1; } + if(seen_request(c->buffer)) + return 0; + /* Lookup nodes */ from = lookup_node(from_name); @@ -291,7 +295,7 @@ cp { 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 */ diff --git a/src/protocol_key.c b/src/protocol_key.c index b85de5ed..dc44b537 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -17,7 +17,7 @@ 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" @@ -61,8 +61,8 @@ cp 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; @@ -71,15 +71,20 @@ cp int key_changed_h(connection_t *c) { char name[MAX_STRING_SIZE]; + avl_node_t *node; + connection_t *other; 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; } + if(seen_request(c->buffer)) + return 0; + n = lookup_node(name); if(!n) @@ -93,7 +98,14 @@ cp 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; } diff --git a/src/protocol_subnet.c b/src/protocol_subnet.c index fbb021d1..3cea347b 100644 --- a/src/protocol_subnet.c +++ b/src/protocol_subnet.c @@ -17,7 +17,7 @@ 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" @@ -50,7 +50,7 @@ int send_add_subnet(connection_t *c, subnet_t *subnet) 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 @@ -66,7 +66,7 @@ int add_subnet_h(connection_t *c) 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; @@ -88,6 +88,9 @@ cp 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); @@ -128,7 +131,7 @@ cp { 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; @@ -140,7 +143,7 @@ int send_del_subnet(connection_t *c, subnet_t *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; @@ -155,7 +158,7 @@ int del_subnet_h(connection_t *c) 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; @@ -187,6 +190,9 @@ cp 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; @@ -219,7 +225,7 @@ cp { 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. */