2002-02-11 10:05:58 +00:00
/*
protocol_auth . c - - handle the meta - protocol , authentication
2006-04-26 13:52:58 +00:00
Copyright ( C ) 1999 - 2005 Ivo Timmermans ,
2009-03-05 13:12:36 +00:00
2000 - 2009 Guus Sliepen < guus @ tinc - vpn . org >
2002-02-11 10:05:58 +00:00
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 .
2009-09-24 22:01:00 +00:00
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 .
2002-02-11 10:05:58 +00:00
*/
2003-07-17 15:06:27 +00:00
# include "system.h"
2002-02-11 10:05:58 +00:00
2007-05-18 10:05:26 +00:00
# include "splay_tree.h"
2002-02-11 10:05:58 +00:00
# include "conf.h"
# include "connection.h"
2008-12-11 14:44:44 +00:00
# include "crypto.h"
2002-09-04 13:48:52 +00:00
# include "edge.h"
# include "graph.h"
2003-07-06 22:11:37 +00:00
# include "logger.h"
2003-07-17 15:06:27 +00:00
# include "net.h"
# include "netutl.h"
# include "node.h"
# include "protocol.h"
2008-12-11 14:44:44 +00:00
# include "rsa.h"
2003-07-17 15:06:27 +00:00
# include "utils.h"
# include "xalloc.h"
2002-02-11 10:05:58 +00:00
2007-05-18 10:00:00 +00:00
bool send_id ( connection_t * c ) {
2007-10-19 18:53:48 +00:00
gettimeofday ( & c - > start , NULL ) ;
2002-09-09 21:25:28 +00:00
return send_request ( c , " %d %s %d " , ID , myself - > connection - > name ,
myself - > connection - > protocol_version ) ;
2002-02-11 10:05:58 +00:00
}
2007-05-19 22:23:02 +00:00
bool id_h ( connection_t * c , char * request ) {
2002-09-09 21:25:28 +00:00
char name [ MAX_STRING_SIZE ] ;
2007-05-19 22:23:02 +00:00
if ( sscanf ( request , " %*d " MAX_STRING " %d " , name , & c - > protocol_version ) ! = 2 ) {
2009-09-24 22:54:07 +00:00
logger ( LOG_ERR , " Got bad %s from %s (%s) " , " ID " , c - > name ,
2002-09-09 21:25:28 +00:00
c - > hostname ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
/* Check if identity is a valid name */
2003-07-22 20:55:21 +00:00
if ( ! check_id ( name ) ) {
2009-09-24 22:54:07 +00:00
logger ( LOG_ERR , " Got bad %s from %s (%s): %s " , " ID " , c - > name ,
2002-09-09 21:25:28 +00:00
c - > hostname , " invalid name " ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
2007-05-17 19:15:48 +00:00
/* If this is an outgoing connection, make sure we are connected to the right host */
2002-09-09 21:25:28 +00:00
2007-05-17 19:15:48 +00:00
if ( c - > outgoing ) {
2002-09-09 21:25:28 +00:00
if ( strcmp ( c - > name , name ) ) {
2009-09-24 22:54:07 +00:00
logger ( LOG_ERR , " Peer %s is %s instead of %s " , c - > hostname , name ,
2002-09-09 21:25:28 +00:00
c - > name ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
2005-05-04 15:51:45 +00:00
} else {
if ( c - > name )
free ( c - > name ) ;
2002-09-09 21:25:28 +00:00
c - > name = xstrdup ( name ) ;
2005-05-04 15:51:45 +00:00
}
2002-09-09 21:25:28 +00:00
/* Check if version matches */
if ( c - > protocol_version ! = myself - > connection - > protocol_version ) {
2009-09-24 22:54:07 +00:00
logger ( LOG_ERR , " Peer %s (%s) uses incompatible version %d " ,
2002-09-09 21:25:28 +00:00
c - > name , c - > hostname , c - > protocol_version ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
if ( bypass_security ) {
if ( ! c - > config_tree )
init_configuration ( & c - > config_tree ) ;
c - > allow_request = ACK ;
return send_ack ( c ) ;
}
if ( ! c - > config_tree ) {
init_configuration ( & c - > config_tree ) ;
2003-07-22 20:55:21 +00:00
if ( ! read_connection_config ( c ) ) {
2009-09-24 22:54:07 +00:00
logger ( LOG_ERR , " Peer %s had unknown identity (%s) " , c - > hostname ,
2002-09-09 21:25:28 +00:00
c - > name ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
}
2003-07-22 20:55:21 +00:00
if ( ! read_rsa_public_key ( c ) ) {
return false ;
2002-09-09 21:25:28 +00:00
}
c - > allow_request = METAKEY ;
return send_metakey ( c ) ;
2002-02-11 10:05:58 +00:00
}
2007-05-18 10:00:00 +00:00
bool send_metakey ( connection_t * c ) {
2008-12-11 14:44:44 +00:00
size_t len = rsa_size ( & c - > rsa ) ;
char key [ len ] ;
char enckey [ len ] ;
char hexkey [ 2 * len + 1 ] ;
2002-09-09 21:25:28 +00:00
2008-12-11 14:44:44 +00:00
if ( ! cipher_open_blowfish_ofb ( & c - > outcipher ) )
return false ;
2005-06-03 10:16:03 +00:00
2009-06-06 17:04:04 +00:00
if ( ! digest_open_sha1 ( & c - > outdigest , - 1 ) )
2008-12-11 14:44:44 +00:00
return false ;
2002-09-09 21:25:28 +00:00
2008-12-11 14:44:44 +00:00
/* Create a random key */
2002-09-09 21:25:28 +00:00
2008-12-11 14:44:44 +00:00
randomize ( key , len ) ;
2002-09-09 21:25:28 +00:00
/* The message we send must be smaller than the modulus of the RSA key.
By definition , for a key of k bits , the following formula holds :
2 ^ ( k - 1 ) < = modulus < 2 ^ ( k )
Where ^ means " to the power of " , not " xor " .
This means that to be sure , we must choose our message < 2 ^ ( k - 1 ) .
This can be done by setting the most significant bit to zero .
*/
2008-12-11 14:44:44 +00:00
key [ 0 ] & = 0x7F ;
cipher_set_key_from_rsa ( & c - > outcipher , key , len , true ) ;
2002-09-09 21:25:28 +00:00
2003-07-12 17:41:48 +00:00
ifdebug ( SCARY_THINGS ) {
2008-12-11 14:44:44 +00:00
bin2hex ( key , hexkey , len ) ;
hexkey [ len * 2 ] = ' \0 ' ;
2009-09-29 12:55:29 +00:00
logger ( LOG_DEBUG , " Generated random meta key (unencrypted): %s " , hexkey ) ;
2002-09-09 21:25:28 +00:00
}
/* Encrypt the random data
We do not use one of the PKCS padding schemes here .
This is allowed , because we encrypt a totally random string
with a length equal to that of the modulus of the RSA key .
*/
2008-12-11 14:44:44 +00:00
if ( ! rsa_public_encrypt ( & c - > rsa , key , len , enckey ) ) {
2009-09-29 12:55:29 +00:00
logger ( LOG_ERR , " Error during encryption of meta key for %s (%s) " , c - > name , c - > hostname ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
/* Convert the encrypted random data to a hexadecimal formatted string */
2008-12-11 14:44:44 +00:00
bin2hex ( enckey , hexkey , len ) ;
hexkey [ len * 2 ] = ' \0 ' ;
2002-09-09 21:25:28 +00:00
/* Send the meta key */
2008-12-11 14:44:44 +00:00
bool result = send_request ( c , " %d %d %d %d %d %s " , METAKEY ,
cipher_get_nid ( & c - > outcipher ) ,
digest_get_nid ( & c - > outdigest ) , c - > outmaclength ,
c - > outcompression , hexkey ) ;
c - > status . encryptout = true ;
return result ;
2002-02-11 10:05:58 +00:00
}
2007-05-19 22:23:02 +00:00
bool metakey_h ( connection_t * c , char * request ) {
2008-12-11 14:44:44 +00:00
char hexkey [ MAX_STRING_SIZE ] ;
2002-09-09 21:25:28 +00:00
int cipher , digest , maclength , compression ;
2008-12-11 14:44:44 +00:00
size_t len = rsa_size ( & myself - > connection - > rsa ) ;
char enckey [ len ] ;
char key [ len ] ;
2002-09-09 21:25:28 +00:00
2008-12-11 14:44:44 +00:00
if ( sscanf ( request , " %*d %d %d %d %d " MAX_STRING , & cipher , & digest , & maclength , & compression , hexkey ) ! = 5 ) {
2009-09-29 12:55:29 +00:00
logger ( LOG_ERR , " Got bad %s from %s (%s) " , " METAKEY " , c - > name , c - > hostname ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
/* Check if the length of the meta key is all right */
2008-12-11 14:44:44 +00:00
if ( strlen ( hexkey ) ! = len * 2 ) {
2009-09-24 22:54:07 +00:00
logger ( LOG_ERR , " Possible intruder %s (%s): %s " , c - > name , c - > hostname , " wrong keylength " ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
/* Convert the challenge from hexadecimal back to binary */
2008-12-11 14:44:44 +00:00
hex2bin ( hexkey , enckey , len ) ;
2002-09-09 21:25:28 +00:00
/* Decrypt the meta key */
2008-12-11 14:44:44 +00:00
if ( ! rsa_private_decrypt ( & myself - > connection - > rsa , enckey , len , key ) ) {
2009-09-29 12:55:29 +00:00
logger ( LOG_ERR , " Error during decryption of meta key for %s (%s) " , c - > name , c - > hostname ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
2003-07-12 17:41:48 +00:00
ifdebug ( SCARY_THINGS ) {
2008-12-11 14:44:44 +00:00
bin2hex ( key , hexkey , len ) ;
hexkey [ len * 2 ] = ' \0 ' ;
2009-09-29 12:55:29 +00:00
logger ( LOG_DEBUG , " Received random meta key (unencrypted): %s " , hexkey ) ;
2002-02-20 19:25:09 +00:00
}
2002-09-09 21:25:28 +00:00
/* Check and lookup cipher and digest algorithms */
2008-12-11 14:44:44 +00:00
if ( ! cipher_open_by_nid ( & c - > incipher , cipher ) | | ! cipher_set_key_from_rsa ( & c - > incipher , key , len , false ) ) {
2009-09-29 12:55:29 +00:00
logger ( LOG_ERR , " Error during initialisation of cipher from %s (%s) " , c - > name , c - > hostname ) ;
2008-12-11 14:44:44 +00:00
return false ;
2002-02-20 19:25:09 +00:00
}
2002-09-09 21:25:28 +00:00
2009-06-06 17:04:04 +00:00
if ( ! digest_open_by_nid ( & c - > indigest , digest , - 1 ) ) {
2009-09-29 12:55:29 +00:00
logger ( LOG_ERR , " Error during initialisation of digest from %s (%s) " , c - > name , c - > hostname ) ;
2008-12-11 14:44:44 +00:00
return false ;
2002-02-20 19:25:09 +00:00
}
2008-12-11 14:44:44 +00:00
c - > status . decryptin = true ;
2002-09-09 21:25:28 +00:00
c - > allow_request = CHALLENGE ;
2002-02-11 10:05:58 +00:00
2002-09-09 21:25:28 +00:00
return send_challenge ( c ) ;
2002-02-11 10:05:58 +00:00
}
2007-05-18 10:00:00 +00:00
bool send_challenge ( connection_t * c ) {
2008-12-11 14:44:44 +00:00
size_t len = rsa_size ( & c - > rsa ) ;
char buffer [ len * 2 + 1 ] ;
2002-02-11 10:05:58 +00:00
2002-09-09 21:25:28 +00:00
if ( ! c - > hischallenge )
2009-06-05 21:03:28 +00:00
c - > hischallenge = xrealloc ( c - > hischallenge , len ) ;
2002-02-11 10:05:58 +00:00
2002-09-09 21:25:28 +00:00
/* Copy random data to the buffer */
2002-02-11 10:05:58 +00:00
2008-12-11 14:44:44 +00:00
randomize ( c - > hischallenge , len ) ;
2002-02-11 10:05:58 +00:00
2002-09-09 21:25:28 +00:00
/* Convert to hex */
bin2hex ( c - > hischallenge , buffer , len ) ;
buffer [ len * 2 ] = ' \0 ' ;
/* Send the challenge */
2003-07-22 20:55:21 +00:00
return send_request ( c , " %d %s " , CHALLENGE , buffer ) ;
2002-02-11 10:05:58 +00:00
}
2007-05-19 22:23:02 +00:00
bool challenge_h ( connection_t * c , char * request ) {
2002-09-09 21:25:28 +00:00
char buffer [ MAX_STRING_SIZE ] ;
2008-12-11 14:44:44 +00:00
size_t len = rsa_size ( & myself - > connection - > rsa ) ;
size_t digestlen = digest_length ( & c - > outdigest ) ;
char digest [ digestlen ] ;
2002-02-11 10:05:58 +00:00
2007-05-19 22:23:02 +00:00
if ( sscanf ( request , " %*d " MAX_STRING , buffer ) ! = 1 ) {
2009-09-29 12:55:29 +00:00
logger ( LOG_ERR , " Got bad %s from %s (%s) " , " CHALLENGE " , c - > name , c - > hostname ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
/* Check if the length of the challenge is all right */
if ( strlen ( buffer ) ! = len * 2 ) {
2009-09-29 12:55:29 +00:00
logger ( LOG_ERR , " Possible intruder %s (%s): %s " , c - > name , c - > hostname , " wrong challenge length " ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
2002-02-11 10:05:58 +00:00
2002-09-09 21:25:28 +00:00
/* Convert the challenge from hexadecimal back to binary */
2002-02-11 10:05:58 +00:00
2008-12-11 14:44:44 +00:00
hex2bin ( buffer , buffer , len ) ;
2002-02-11 10:05:58 +00:00
2002-09-09 21:25:28 +00:00
c - > allow_request = CHAL_REPLY ;
2002-02-11 10:05:58 +00:00
2002-09-09 21:25:28 +00:00
/* Calculate the hash from the challenge we received */
2002-02-11 10:05:58 +00:00
2008-12-11 14:44:44 +00:00
digest_create ( & c - > indigest , buffer , len , digest ) ;
2002-02-11 10:05:58 +00:00
2002-09-09 21:25:28 +00:00
/* Convert the hash to a hexadecimal formatted string */
2002-02-11 10:05:58 +00:00
2008-12-11 14:44:44 +00:00
bin2hex ( digest , buffer , digestlen ) ;
buffer [ digestlen * 2 ] = ' \0 ' ;
2002-02-11 10:05:58 +00:00
2002-09-09 21:25:28 +00:00
/* Send the reply */
2008-12-11 14:44:44 +00:00
return send_request ( c , " %d %s " , CHAL_REPLY , buffer ) ;
2002-02-11 10:05:58 +00:00
}
2007-05-19 22:23:02 +00:00
bool chal_reply_h ( connection_t * c , char * request ) {
2002-09-09 21:25:28 +00:00
char hishash [ MAX_STRING_SIZE ] ;
2007-05-19 22:23:02 +00:00
if ( sscanf ( request , " %*d " MAX_STRING , hishash ) ! = 1 ) {
2009-09-24 22:54:07 +00:00
logger ( LOG_ERR , " Got bad %s from %s (%s) " , " CHAL_REPLY " , c - > name ,
2002-09-09 21:25:28 +00:00
c - > hostname ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
/* Check if the length of the hash is all right */
2008-12-11 14:44:44 +00:00
if ( strlen ( hishash ) ! = digest_length ( & c - > outdigest ) * 2 ) {
2009-09-29 13:19:55 +00:00
logger ( LOG_ERR , " Possible intruder %s (%s): %s " , c - > name , c - > hostname , " wrong challenge reply length " ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
/* Convert the hash to binary format */
2008-12-11 14:44:44 +00:00
hex2bin ( hishash , hishash , digest_length ( & c - > outdigest ) ) ;
2002-09-09 21:25:28 +00:00
2008-12-11 14:44:44 +00:00
/* Verify the hash */
2002-09-09 21:25:28 +00:00
2008-12-11 14:44:44 +00:00
if ( ! digest_verify ( & c - > outdigest , c - > hischallenge , rsa_size ( & c - > rsa ) , hishash ) ) {
2009-09-29 13:19:55 +00:00
logger ( LOG_ERR , " Possible intruder %s (%s): %s " , c - > name , c - > hostname , " wrong challenge reply " ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
/* Identity has now been positively verified.
Send an acknowledgement with the rest of the information needed .
*/
2008-12-11 14:44:44 +00:00
free ( c - > hischallenge ) ;
c - > hischallenge = NULL ;
2002-09-09 21:25:28 +00:00
c - > allow_request = ACK ;
return send_ack ( c ) ;
2002-02-11 10:05:58 +00:00
}
2007-05-18 10:00:00 +00:00
bool send_ack ( connection_t * c ) {
2002-09-09 21:25:28 +00:00
/* ACK message contains rest of the information the other end needs
to create node_t and edge_t structures . */
struct timeval now ;
2003-11-10 22:31:53 +00:00
bool choice ;
2002-09-09 21:25:28 +00:00
/* Estimate weight */
gettimeofday ( & now , NULL ) ;
2003-07-22 20:55:21 +00:00
c - > estimated_weight = ( now . tv_sec - c - > start . tv_sec ) * 1000 + ( now . tv_usec - c - > start . tv_usec ) / 1000 ;
2002-09-09 21:25:28 +00:00
2003-11-10 22:31:53 +00:00
/* Check some options */
if ( ( get_config_bool ( lookup_config ( c - > config_tree , " IndirectData " ) , & choice ) & & choice ) | | myself - > options & OPTION_INDIRECT )
c - > options | = OPTION_INDIRECT ;
if ( ( get_config_bool ( lookup_config ( c - > config_tree , " TCPOnly " ) , & choice ) & & choice ) | | myself - > options & OPTION_TCPONLY )
c - > options | = OPTION_TCPONLY | OPTION_INDIRECT ;
2009-03-09 12:48:54 +00:00
if ( myself - > options & OPTION_PMTU_DISCOVERY )
2003-12-20 21:25:17 +00:00
c - > options | = OPTION_PMTU_DISCOVERY ;
2003-12-20 19:47:53 +00:00
2003-12-22 11:04:17 +00:00
get_config_int ( lookup_config ( c - > config_tree , " Weight " ) , & c - > estimated_weight ) ;
2009-10-24 14:15:24 +00:00
return send_request ( c , " %d %s %d %x " , ACK , myport , c - > estimated_weight , c - > options ) ;
2002-02-11 10:05:58 +00:00
}
2007-05-18 10:00:00 +00:00
static void send_everything ( connection_t * c ) {
2007-05-18 10:05:26 +00:00
splay_node_t * node , * node2 ;
2002-09-09 21:25:28 +00:00
node_t * n ;
subnet_t * s ;
edge_t * e ;
/* Send all known subnets and edges */
2003-11-17 15:30:18 +00:00
if ( tunnelserver ) {
for ( node = myself - > subnet_tree - > head ; node ; node = node - > next ) {
s = node - > data ;
send_add_subnet ( c , s ) ;
}
return ;
}
2002-09-09 21:25:28 +00:00
for ( node = node_tree - > head ; node ; node = node - > next ) {
2003-08-28 21:05:11 +00:00
n = node - > data ;
2002-09-09 21:25:28 +00:00
for ( node2 = n - > subnet_tree - > head ; node2 ; node2 = node2 - > next ) {
2003-08-28 21:05:11 +00:00
s = node2 - > data ;
2002-09-09 21:25:28 +00:00
send_add_subnet ( c , s ) ;
}
for ( node2 = n - > edge_tree - > head ; node2 ; node2 = node2 - > next ) {
2003-08-28 21:05:11 +00:00
e = node2 - > data ;
2002-09-09 21:25:28 +00:00
send_add_edge ( c , e ) ;
}
}
2002-02-11 10:05:58 +00:00
}
2007-05-19 22:23:02 +00:00
bool ack_h ( connection_t * c , char * request ) {
2002-09-09 21:25:28 +00:00
char hisport [ MAX_STRING_SIZE ] ;
char * hisaddress , * dummy ;
2003-12-22 11:04:17 +00:00
int weight , mtu ;
2009-10-24 14:15:24 +00:00
uint32_t options ;
2002-09-09 21:25:28 +00:00
node_t * n ;
2009-11-02 13:24:27 +00:00
if ( sscanf ( request , " %*d " MAX_STRING " %d %x " , hisport , & weight , & options ) ! = 3 ) {
2009-09-24 22:54:07 +00:00
logger ( LOG_ERR , " Got bad %s from %s (%s) " , " ACK " , c - > name ,
2002-09-09 21:25:28 +00:00
c - > hostname ) ;
2003-07-22 20:55:21 +00:00
return false ;
2002-09-09 21:25:28 +00:00
}
/* Check if we already have a node_t for him */
n = lookup_node ( c - > name ) ;
if ( ! n ) {
n = new_node ( ) ;
n - > name = xstrdup ( c - > name ) ;
node_add ( n ) ;
} else {
if ( n - > connection ) {
/* Oh dear, we already have a connection to this node. */
2009-09-29 12:55:29 +00:00
ifdebug ( CONNECTIONS ) logger ( LOG_DEBUG , " Established a second connection with %s (%s), closing old connection " , n - > connection - > name , n - > connection - > hostname ) ;
2007-05-18 10:29:10 +00:00
if ( n - > connection - > outgoing ) {
if ( c - > outgoing )
2009-09-29 12:55:29 +00:00
logger ( LOG_WARNING , " Two outgoing connections to the same node! " ) ;
2007-05-18 10:29:10 +00:00
else
c - > outgoing = n - > connection - > outgoing ;
n - > connection - > outgoing = NULL ;
}
2003-07-22 20:55:21 +00:00
terminate_connection ( n - > connection , false ) ;
2003-01-12 17:02:23 +00:00
/* Run graph algorithm to purge key and make sure up/down scripts are rerun with new IP addresses and stuff */
graph ( ) ;
2002-09-09 21:25:28 +00:00
}
}
n - > connection = c ;
c - > node = n ;
2009-03-09 12:48:54 +00:00
if ( ! ( c - > options & options & OPTION_PMTU_DISCOVERY ) ) {
c - > options & = ~ OPTION_PMTU_DISCOVERY ;
options & = ~ OPTION_PMTU_DISCOVERY ;
}
2002-09-09 21:25:28 +00:00
c - > options | = options ;
2003-12-22 11:04:17 +00:00
if ( get_config_int ( lookup_config ( c - > config_tree , " PMTU " ) , & mtu ) & & mtu < n - > mtu )
n - > mtu = mtu ;
if ( get_config_int ( lookup_config ( myself - > connection - > config_tree , " PMTU " ) , & mtu ) & & mtu < n - > mtu )
n - > mtu = mtu ;
2002-09-09 21:25:28 +00:00
/* Activate this connection */
c - > allow_request = ALL ;
2003-07-22 20:55:21 +00:00
c - > status . active = true ;
2002-09-09 21:25:28 +00:00
2009-09-24 22:54:07 +00:00
ifdebug ( CONNECTIONS ) logger ( LOG_NOTICE , " Connection with %s (%s) activated " , c - > name ,
2002-09-09 21:25:28 +00:00
c - > hostname ) ;
/* Send him everything we know */
2003-11-17 15:30:18 +00:00
send_everything ( c ) ;
2002-09-09 21:25:28 +00:00
/* Create an edge_t for this connection */
c - > edge = new_edge ( ) ;
c - > edge - > from = myself ;
c - > edge - > to = n ;
sockaddr2str ( & c - > address , & hisaddress , & dummy ) ;
c - > edge - > address = str2sockaddr ( hisaddress , hisport ) ;
free ( hisaddress ) ;
free ( dummy ) ;
c - > edge - > weight = ( weight + c - > estimated_weight ) / 2 ;
c - > edge - > connection = c ;
c - > edge - > options = c - > options ;
edge_add ( c - > edge ) ;
/* Notify everyone of the new edge */
2003-11-17 15:30:18 +00:00
if ( tunnelserver )
2003-11-10 22:31:53 +00:00
send_add_edge ( c , c - > edge ) ;
2003-11-17 15:30:18 +00:00
else
send_add_edge ( broadcast , c - > edge ) ;
2002-09-09 21:25:28 +00:00
/* Run MST and SSSP algorithms */
graph ( ) ;
2003-07-22 20:55:21 +00:00
return true ;
2002-02-11 10:05:58 +00:00
}