X-Git-Url: https://tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fnet.c;h=9daf8c81c0012758c189abeff688e53fb8319821;hp=7b9133e0c02d005761300fa24a4bcf03fa8ae1b6;hb=61e71ab74ad9b5edb044b84ccf1111a33eb468cb;hpb=a083b1cf305f3d241f2f4b36968a5b1ed9117612 diff --git a/src/net.c b/src/net.c index 7b9133e0..9daf8c81 100644 --- a/src/net.c +++ b/src/net.c @@ -1,6 +1,6 @@ /* net.c -- most of the network code - Copyright (C) 1998,99 Ivo Timmermans + Copyright (C) 1998,1999,2000 Ivo Timmermans 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 @@ -51,7 +51,7 @@ int total_tap_out = 0; int total_socket_in = 0; int total_socket_out = 0; -time_t last_ping_time = 0; +static int seconds_till_retry; /* The global list of existing connections */ conn_list_t *conn_list = NULL; @@ -107,6 +107,8 @@ cp } total_socket_out += r; + + cl->want_ping = 1; cp return 0; } @@ -123,6 +125,9 @@ cp syslog(LOG_ERR, "Can't write to tap device: %m"); else total_tap_out += lenin; + + cl->want_ping = 0; + cl->last_ping_time = time(NULL); cp return 0; } @@ -304,21 +309,6 @@ cp return xsend(cl, packet); } -int send_broadcast(conn_list_t *cl, vpn_packet_t *packet) -{ - conn_list_t *p; -cp - for(p = cl; p != NULL; p = p->next) - if(send_packet(p->real_ip, packet) < 0) - { - syslog(LOG_ERR, "Could not send a broadcast packet to %08lx (%08lx): %m", - p->vpn_ip, p->real_ip); - break; /* FIXME: should retry later, and send a ping over the metaconnection. */ - } -cp - return 0; -} - /* open the local ethertap device */ @@ -553,6 +543,30 @@ cp return 0; } +RETSIGTYPE +sigalrm_handler(int a) +{ + config_t const *cfg; +cp + cfg = get_config_val(upstreamip); + + if(!setup_outgoing_connection(cfg->data.ip->ip)) + { + signal(SIGALRM, SIG_IGN); + } + else + { + signal(SIGALRM, sigalrm_handler); + seconds_till_retry += 5; + if(seconds_till_retry>300) /* Don't wait more than 5 minutes. */ + seconds_till_retry = 300; + alarm(seconds_till_retry); + syslog(LOG_ERR, "Still failed to connect to other. Will retry in %d seconds.", + seconds_till_retry); + } +cp +} + /* setup all initial network connections */ @@ -561,7 +575,7 @@ int setup_network_connections(void) config_t const *cfg; cp if((cfg = get_config_val(pingtimeout)) == NULL) - timeout = 10; + timeout = 5; else timeout = cfg->data.val; @@ -576,33 +590,14 @@ cp return 0; if(setup_outgoing_connection(cfg->data.ip->ip)) - return -1; -cp - return 0; -} - -RETSIGTYPE -sigalrm_handler(int a) -{ - config_t const *cfg; - static int seconds_till_retry; -cp - cfg = get_config_val(upstreamip); - - if(!setup_outgoing_connection(cfg->data.ip->ip)) - { - signal(SIGALRM, SIG_IGN); - seconds_till_retry = 5; - } - else { signal(SIGALRM, sigalrm_handler); - seconds_till_retry += 5; + seconds_till_retry = 300; alarm(seconds_till_retry); - syslog(LOG_ERR, "Still failed to connect to other. Will retry in %d seconds.", - seconds_till_retry); + syslog(LOG_NOTICE, "Try to re-establish outgoing connection in 5 minutes."); } cp + return 0; } /* @@ -666,8 +661,8 @@ cp if(connect(nfd, (struct sockaddr *)&a, sizeof(a)) == -1) { - syslog(LOG_ERR, "Create connection to %08lx:%d failed: %m", ntohs(cl->real_ip), - cl->port); + syslog(LOG_ERR, "Connecting to " IP_ADDR_S ":%d failed: %m", + IP_ADDR_V(cl->real_ip), cl->port); return -1; } @@ -707,6 +702,8 @@ cp p->meta_socket = sfd; p->status.meta = 1; p->buflen = 0; + p->last_ping_time = time(NULL); + p->want_ping = 0; syslog(LOG_NOTICE, "Connection from %s:%d", p->hostname, htons(ci.sin_port)); @@ -831,62 +828,54 @@ cp if(cl->status.outgoing) { - alarm(5); signal(SIGALRM, sigalrm_handler); + seconds_till_retry = 5; + alarm(seconds_till_retry); syslog(LOG_NOTICE, "Try to re-establish outgoing connection in 5 seconds."); } + cl->status.active = 0; cl->status.remove = 1; cp } /* - send out a ping request to all active - connections -*/ -int send_broadcast_ping(void) -{ - conn_list_t *p; -cp - for(p = conn_list; p != NULL; p = p->next) - { - if(p->status.remove) - continue; - if(p->status.active && p->status.meta) - { - if(send_ping(p)) - terminate_connection(p); - else - { - p->status.pinged = 1; - p->status.got_pong = 0; - } - } - } - - last_ping_time = time(NULL); -cp - return 0; -} - -/* - end all connections that did not respond - to the ping probe in time + Check if the other end is active. + If we have sent packets, but didn't receive any, + then possibly the other end is dead. We send a + PING request over the meta connection. If the other + end does not reply in time, we consider them dead + and close the connection. */ int check_dead_connections(void) { conn_list_t *p; + time_t now; cp + now = time(NULL); for(p = conn_list; p != NULL; p = p->next) { if(p->status.remove) continue; - if(p->status.active && p->status.meta && p->status.pinged && !p->status.got_pong) + if(p->status.active && p->status.meta) { - syslog(LOG_INFO, "%s (" IP_ADDR_S ") didn't respond to ping", - p->hostname, IP_ADDR_V(p->vpn_ip)); - p->status.timeout = 1; - terminate_connection(p); + if(p->last_ping_time + timeout < now) + { + if(p->status.pinged && !p->status.got_pong) + { + syslog(LOG_INFO, "%s (" IP_ADDR_S ") didn't respond to ping", + p->hostname, IP_ADDR_V(p->vpn_ip)); + p->status.timeout = 1; + terminate_connection(p); + } + else if(p->want_ping) + { + send_ping(p); + p->last_ping_time = now; + p->status.pinged = 1; + p->status.got_pong = 0; + } + } } } cp @@ -946,8 +935,8 @@ cp if(cl->buflen >= MAXBUFSIZE) { - syslog(LOG_ERR, "Metadata read buffer full! Discarding contents."); - cl->buflen = 0; + syslog(LOG_ERR, "Metadata read buffer overflow."); + return -1; } lenin = read(cl->meta_socket, cl->buffer, MAXBUFSIZE-cl->buflen); @@ -982,17 +971,22 @@ cp if(request_handlers[request] == NULL) { syslog(LOG_ERR, "Unknown request: %s", cl->buffer); - return 0; + return -1; } if(debug_lvl > 3) syslog(LOG_DEBUG, "Got request: %s", cl->buffer); - request_handlers[request](cl); + if(request_handlers[request](cl)) /* Something went wrong. Probably scriptkiddies. Terminate. */ + { + syslog(LOG_ERR, "Error while processing request from IP_ADDR_S", IP_ADDR_V(cl->real_ip)); + return -1; + } } else { - syslog(LOG_ERR, "Bogus data received: %s", cl->buffer); + syslog(LOG_ERR, "Bogus data received."); + return -1; } cl->buflen -= cl->reqlen; @@ -1004,6 +998,9 @@ cp break; } } + + cl->last_ping_time = time(NULL); + cl->want_ping = 0; cp return 0; } @@ -1115,8 +1112,9 @@ void main_loop(void) fd_set fset; struct timeval tv; int r; + time_t last_ping_check; cp - last_ping_time = time(NULL); + last_ping_check = time(NULL); for(;;) { @@ -1134,11 +1132,11 @@ cp return; } - if(r == 0 || last_ping_time + timeout < time(NULL)) - /* Timeout... hm... something might be wrong. */ + if(last_ping_check + timeout < time(NULL)) + /* Let's check if everybody is still alive */ { check_dead_connections(); - send_broadcast_ping(); + last_ping_check = time(NULL); continue; }