6565/* Number of get node requests to send to quickly find close nodes. */
6666#define MAX_BOOTSTRAP_TIMES 5
6767
68+ static uint8_t calc_dist (uint8_t a , uint8_t b )
69+ {
70+ return a ^ b ;
71+ }
72+
6873/* Compares pk1 and pk2 with pk.
6974 *
7075 * return 0 if both are same distance.
@@ -79,43 +84,38 @@ int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2)
7984
8085 for (i = 0 ; i < crypto_box_PUBLICKEYBYTES ; ++ i ) {
8186
82- distance1 = pk [i ] ^ pk1 [i ];
83- distance2 = pk [i ] ^ pk2 [i ];
87+ distance1 = calc_dist ( pk [i ], pk1 [i ]) ;
88+ distance2 = calc_dist ( pk [i ], pk2 [i ]) ;
8489
85- if (!i ) {
86- if (distance1 & (1 << 7 )) {
87- d1_abs = 1 ;
88- }
90+ if (distance1 < distance2 )
91+ return 1 ;
8992
90- if (distance2 & (1 << 7 )) {
91- d2_abs = 1 ;
92- }
93- }
93+ if (distance1 > distance2 )
94+ return 2 ;
95+ }
9496
95- if ( d1_abs )
96- distance1 = ~ distance1 ;
97+ return 0 ;
98+ }
9799
98- if (d2_abs )
99- distance2 = ~distance2 ;
100+ /* Return index of first unequal bit number.
101+ */
102+ static unsigned int bit_by_bit_cmp (const uint8_t * pk1 , const uint8_t * pk2 )
103+ {
104+ unsigned int i , j = 0 ;
100105
101- if (i == (crypto_box_PUBLICKEYBYTES - 1 )) {
102- if (d1_abs )
103- if (distance1 != UINT8_MAX )
104- ++ distance1 ;
106+ for (i = 0 ; i < crypto_box_PUBLICKEYBYTES ; ++ i ) {
107+ if (pk1 [i ] == pk2 [i ])
108+ continue ;
105109
106- if ( d2_abs )
107- if ( distance2 != UINT8_MAX )
108- ++ distance2 ;
110+ for ( j = 0 ; j < 8 ; ++ j ) {
111+ if (( pk1 [ i ] & ( 1 << ( 7 - j ))) != ( pk2 [ i ] & ( 1 << ( 7 - j ))) )
112+ break ;
109113 }
110114
111- if (distance1 < distance2 )
112- return 1 ;
113-
114- if (distance1 > distance2 )
115- return 2 ;
115+ break ;
116116 }
117117
118- return 0 ;
118+ return i * 8 + j ;
119119}
120120
121121/* Shared key generations are costly, it is therefor smart to store commonly used
@@ -586,7 +586,7 @@ static int get_somewhat_close_nodes(const DHT *dht, const uint8_t *public_key, N
586586{
587587 uint32_t num_nodes = 0 , i ;
588588 get_close_nodes_inner (public_key , nodes_list , sa_family ,
589- dht -> close_clientlist , LCLIENT_LIST , & num_nodes , is_LAN , want_good );
589+ dht -> close_clientlist , LCLIENT_LIST , & num_nodes , is_LAN , 0 );
590590
591591 /*TODO uncomment this when hardening is added to close friend clients
592592 for (i = 0; i < dht->num_friends; ++i)
@@ -780,6 +780,68 @@ static int replace_all( Client_data *list,
780780 return 0 ;
781781}
782782
783+ /* Add node to close list.
784+ *
785+ * simulate is set to 1 if we want to check if a node can be added to the list without adding it.
786+ *
787+ * return -1 on failure.
788+ * return 0 on success.
789+ */
790+ static int add_to_close (DHT * dht , const uint8_t * public_key , IP_Port ip_port , _Bool simulate )
791+ {
792+ unsigned int i ;
793+
794+ unsigned int index = bit_by_bit_cmp (public_key , dht -> self_public_key );
795+
796+ if (index > LCLIENT_LENGTH )
797+ index = LCLIENT_LENGTH - 1 ;
798+
799+ for (i = 0 ; i < LCLIENT_NODES ; ++ i ) {
800+ Client_data * client = & dht -> close_clientlist [(index * LCLIENT_NODES ) + i ];
801+
802+ if (is_timeout (client -> assoc4 .timestamp , BAD_NODE_TIMEOUT ) && is_timeout (client -> assoc6 .timestamp , BAD_NODE_TIMEOUT )) {
803+ if (!simulate ) {
804+ IPPTsPng * ipptp_write = NULL ;
805+ IPPTsPng * ipptp_clear = NULL ;
806+
807+ if (ip_port .ip .family == AF_INET ) {
808+ ipptp_write = & client -> assoc4 ;
809+ ipptp_clear = & client -> assoc6 ;
810+ } else {
811+ ipptp_write = & client -> assoc6 ;
812+ ipptp_clear = & client -> assoc4 ;
813+ }
814+
815+ id_copy (client -> public_key , public_key );
816+ ipptp_write -> ip_port = ip_port ;
817+ ipptp_write -> timestamp = unix_time ();
818+
819+ ip_reset (& ipptp_write -> ret_ip_port .ip );
820+ ipptp_write -> ret_ip_port .port = 0 ;
821+ ipptp_write -> ret_timestamp = 0 ;
822+
823+ /* zero out other address */
824+ memset (ipptp_clear , 0 , sizeof (* ipptp_clear ));
825+ }
826+
827+ return 0 ;
828+ }
829+ }
830+
831+ return -1 ;
832+ }
833+
834+ /* Return 1 if node can be added to close list, 0 if it can't.
835+ */
836+ _Bool node_addable_to_close_list (DHT * dht , const uint8_t * public_key , IP_Port ip_port )
837+ {
838+ if (add_to_close (dht , public_key , ip_port , 1 ) == 0 ) {
839+ return 1 ;
840+ }
841+
842+ return 0 ;
843+ }
844+
783845static _Bool is_pk_in_client_list (Client_data * list , unsigned int client_list_length , const uint8_t * public_key ,
784846 IP_Port ip_port )
785847{
@@ -807,23 +869,18 @@ static unsigned int ping_node_from_getnodes_ok(DHT *dht, const uint8_t *public_k
807869{
808870 _Bool ret = 0 ;
809871
810- if (store_node_ok (& dht -> close_clientlist [1 ], public_key , dht -> self_public_key )) {
811- ret = 1 ;
812- }
813-
814- if (store_node_ok (& dht -> close_clientlist [0 ], public_key , dht -> self_public_key )) {
872+ if (add_to_close (dht , public_key , ip_port , 1 ) == 0 ) {
815873 ret = 1 ;
816874 }
817875
818- if (ret && !client_in_nodelist (dht -> to_bootstrap , dht -> num_to_bootstrap , public_key )
819- && !is_pk_in_client_list (dht -> close_clientlist , LCLIENT_LIST , public_key , ip_port )) {
820- if (dht -> num_to_bootstrap < MAX_SENT_NODES ) {
876+ if (ret && !client_in_nodelist (dht -> to_bootstrap , dht -> num_to_bootstrap , public_key )) {
877+ if (dht -> num_to_bootstrap < MAX_CLOSE_TO_BOOTSTRAP_NODES ) {
821878 memcpy (dht -> to_bootstrap [dht -> num_to_bootstrap ].public_key , public_key , crypto_box_PUBLICKEYBYTES );
822879 dht -> to_bootstrap [dht -> num_to_bootstrap ].ip_port = ip_port ;
823880 ++ dht -> num_to_bootstrap ;
824881 } else {
825882 //TODO: ipv6 vs v4
826- add_to_list (dht -> to_bootstrap , MAX_SENT_NODES , public_key , ip_port , dht -> self_public_key );
883+ add_to_list (dht -> to_bootstrap , MAX_CLOSE_TO_BOOTSTRAP_NODES , public_key , ip_port , dht -> self_public_key );
827884 }
828885 }
829886
@@ -878,7 +935,7 @@ int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *public_key)
878935 * to replace the first ip by the second.
879936 */
880937 if (!client_or_ip_port_in_list (dht -> close_clientlist , LCLIENT_LIST , public_key , ip_port )) {
881- if (replace_all (dht -> close_clientlist , LCLIENT_LIST , public_key , ip_port , dht -> self_public_key ))
938+ if (add_to_close (dht , public_key , ip_port , 0 ))
882939 used ++ ;
883940 } else
884941 used ++ ;
@@ -1391,54 +1448,9 @@ int DHT_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
13911448 return -1 ;
13921449}
13931450
1394- static void abs_divide_by_2 (uint8_t * public_key_dist )
1395- {
1396- unsigned int i ;
1397- _Bool one = 0 , abs = 0 ;
1398-
1399- if (public_key_dist [0 ] & (1 << 7 )) {
1400- for (i = 0 ; i < crypto_box_PUBLICKEYBYTES ; ++ i ) {
1401- public_key_dist [i ] = ~public_key_dist [i ];
1402- }
1403-
1404- if (public_key_dist [crypto_box_PUBLICKEYBYTES - 1 ] != UINT8_MAX )
1405- ++ public_key_dist [crypto_box_PUBLICKEYBYTES - 1 ];
1406- }
1407-
1408- for (i = 0 ; i < crypto_box_PUBLICKEYBYTES ; ++ i ) {
1409- _Bool temp = 0 ;
1410-
1411- if (public_key_dist [i ] & (1 )) {
1412- temp = 1 ;
1413- }
1414-
1415- public_key_dist [i ] >>= 1 ;
1416-
1417- if (one )
1418- public_key_dist [i ] += (1 << 7 );
1419-
1420- one = temp ;
1421- }
1422- }
1423-
1424- static void find_midpoint (uint8_t * out , const uint8_t * top , const uint8_t * bot )
1425- {
1426- unsigned int i ;
1427-
1428- for (i = 0 ; i < crypto_box_PUBLICKEYBYTES ; ++ i ) {
1429- out [i ] = top [i ] ^ bot [i ];
1430- }
1431-
1432- abs_divide_by_2 (out );
1433-
1434- for (i = 0 ; i < crypto_box_PUBLICKEYBYTES ; ++ i ) {
1435- out [i ] ^= bot [i ];
1436- }
1437- }
1438-
14391451/* returns number of nodes not in kill-timeout */
14401452static uint8_t do_ping_and_sendnode_requests (DHT * dht , uint64_t * lastgetnode , const uint8_t * public_key ,
1441- Client_data * list , uint32_t list_count , uint32_t * bootstrap_times )
1453+ Client_data * list , uint32_t list_count , uint32_t * bootstrap_times , _Bool sortable )
14421454{
14431455 uint32_t i ;
14441456 uint8_t not_kill = 0 ;
@@ -1482,33 +1494,19 @@ static uint8_t do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, co
14821494 }
14831495 }
14841496
1485- if (sort_ok ) {
1497+ if (sortable && sort_ok ) {
14861498 sort_client_list (list , list_count , public_key );
14871499 }
14881500
14891501 if ((num_nodes != 0 ) && (is_timeout (* lastgetnode , GET_NODE_INTERVAL ) || * bootstrap_times < MAX_BOOTSTRAP_TIMES )) {
1490- uint32_t rand_node = rand () % (num_nodes * 2 );
1491-
1492- if (rand_node >= num_nodes ) {
1493- rand_node = rand_node % num_nodes ;
1494-
1495- if ((num_nodes - 1 ) != rand_node ) {
1496- rand_node += rand () % (num_nodes - (rand_node + 1 ));
1497- }
1498-
1499- if (memcmp (client_list [rand_node ]-> public_key , public_key , crypto_box_PUBLICKEYBYTES ) != 0 ) {
1500- uint8_t get_pk [crypto_box_PUBLICKEYBYTES ];
1501- find_midpoint (get_pk , client_list [rand_node ]-> public_key , public_key );
1502- getnodes (dht , assoc_list [rand_node ]-> ip_port , client_list [rand_node ]-> public_key , get_pk , NULL );
1503- }
1504- } else {
1505- if ((num_nodes - 1 ) != rand_node ) {
1506- rand_node += rand () % (num_nodes - (rand_node + 1 ));
1507- }
1502+ uint32_t rand_node = rand () % (num_nodes );
15081503
1509- getnodes (dht , assoc_list [rand_node ]-> ip_port , client_list [rand_node ]-> public_key , public_key , NULL );
1504+ if ((num_nodes - 1 ) != rand_node ) {
1505+ rand_node += rand () % (num_nodes - (rand_node + 1 ));
15101506 }
15111507
1508+ getnodes (dht , assoc_list [rand_node ]-> ip_port , client_list [rand_node ]-> public_key , public_key , NULL );
1509+
15121510 * lastgetnode = temp_time ;
15131511 ++ * bootstrap_times ;
15141512 }
@@ -1533,7 +1531,7 @@ static void do_DHT_friends(DHT *dht)
15331531 friend -> num_to_bootstrap = 0 ;
15341532
15351533 do_ping_and_sendnode_requests (dht , & friend -> lastgetnode , friend -> public_key , friend -> client_list , MAX_FRIEND_CLIENTS ,
1536- & friend -> bootstrap_times );
1534+ & friend -> bootstrap_times , 1 );
15371535 }
15381536}
15391537
@@ -1551,7 +1549,7 @@ static void do_Close(DHT *dht)
15511549 dht -> num_to_bootstrap = 0 ;
15521550
15531551 uint8_t not_killed = do_ping_and_sendnode_requests (dht , & dht -> close_lastgetnodes , dht -> self_public_key ,
1554- dht -> close_clientlist , LCLIENT_LIST , & dht -> close_bootstrap_times );
1552+ dht -> close_clientlist , LCLIENT_LIST , & dht -> close_bootstrap_times , 0 );
15551553
15561554 if (!not_killed ) {
15571555 /* all existing nodes are at least KILL_NODE_TIMEOUT,
@@ -2453,7 +2451,7 @@ void do_DHT(DHT *dht)
24532451 do_DHT_friends (dht );
24542452 do_NAT (dht );
24552453 do_to_ping (dht -> ping );
2456- do_hardening (dht );
2454+ // do_hardening(dht);
24572455#ifdef ENABLE_ASSOC_DHT
24582456
24592457 if (dht -> assoc )
0 commit comments