aboutsummaryrefslogtreecommitdiff
path: root/src/topology/gnunet-daemon-topology.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-04-18 20:23:40 +0000
committerChristian Grothoff <christian@grothoff.org>2010-04-18 20:23:40 +0000
commit541caf3dec54aaee621fed935e667f9ee423ef31 (patch)
tree6f80958e68541ce071bc557bbfc168644963c473 /src/topology/gnunet-daemon-topology.c
parente8bc962b2ed43e194ba124537573da236786e82c (diff)
downloadgnunet-541caf3dec54aaee621fed935e667f9ee423ef31.tar.gz
gnunet-541caf3dec54aaee621fed935e667f9ee423ef31.zip
towards fixing blacklisting APIs and implementation
Diffstat (limited to 'src/topology/gnunet-daemon-topology.c')
-rw-r--r--src/topology/gnunet-daemon-topology.c278
1 files changed, 47 insertions, 231 deletions
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c
index b175d82ae..0aca503c1 100644
--- a/src/topology/gnunet-daemon-topology.c
+++ b/src/topology/gnunet-daemon-topology.c
@@ -106,12 +106,6 @@ struct Peer
106 struct GNUNET_CONTAINER_BloomFilter *filter; 106 struct GNUNET_CONTAINER_BloomFilter *filter;
107 107
108 /** 108 /**
109 * Our request handle for *whitelisting* this peer (NULL if
110 * no whitelisting request is pending).
111 */
112 struct GNUNET_TRANSPORT_BlacklistRequest *wh;
113
114 /**
115 * Until what time should we not try to connect again 109 * Until what time should we not try to connect again
116 * to this peer? 110 * to this peer?
117 */ 111 */
@@ -153,39 +147,6 @@ struct Peer
153 */ 147 */
154 int is_connected; 148 int is_connected;
155 149
156 /**
157 * Are we currently blocking this peer (via blacklist)?
158 */
159 int is_blocked;
160
161};
162
163
164/**
165 * Entry in linked list of active 'disconnect' requests that we have issued.
166 */
167struct DisconnectList
168{
169 /**
170 * This is a doubly-linked list.
171 */
172 struct DisconnectList *next;
173
174 /**
175 * This is a doubly-linked list.
176 */
177 struct DisconnectList *prev;
178
179 /**
180 * Our request handle.
181 */
182 struct GNUNET_TRANSPORT_BlacklistRequest *rh;
183
184 /**
185 * Peer we tried to disconnect.
186 */
187 struct GNUNET_PeerIdentity peer;
188
189}; 150};
190 151
191 152
@@ -233,6 +194,11 @@ static struct GNUNET_CONTAINER_MultiHashMap *peers;
233static struct GNUNET_STATISTICS_Handle *stats; 194static struct GNUNET_STATISTICS_Handle *stats;
234 195
235/** 196/**
197 * Blacklist (NULL if we have none).
198 */
199static struct GNUNET_TRANSPORT_Blacklist *blacklist;
200
201/**
236 * Flag to disallow non-friend connections (pure F2F mode). 202 * Flag to disallow non-friend connections (pure F2F mode).
237 */ 203 */
238static int friends_only; 204static int friends_only;
@@ -263,119 +229,31 @@ static unsigned int friend_count;
263 */ 229 */
264static int autoconnect; 230static int autoconnect;
265 231
266/**
267 * Head of doubly-linked list of active 'disconnect' requests that we have issued.
268 */
269static struct DisconnectList *disconnect_head;
270
271/**
272 * Head of doubly-linked list of active 'disconnect' requests that we have issued.
273 */
274static struct DisconnectList *disconnect_tail;
275
276 232
277/** 233/**
278 * Function called once our request to 'disconnect' a peer 234 * Function that decides if a connection is acceptable or not.
279 * has completed. 235 * If we have a blacklist, only friends are allowed, so the check
236 * is rather simple.
280 * 237 *
281 * @param cls our 'struct DisconnectList' 238 * @param cls closure
282 * @param tc unused 239 * @param pid peer to approve or disapproave
240 * @return GNUNET_OK if the connection is allowed
283 */ 241 */
284static void 242static int
285disconnect_done (void *cls, 243blacklist_check (void *cls,
286 const struct GNUNET_SCHEDULER_TaskContext *tc) 244 const struct GNUNET_PeerIdentity *pid)
287{ 245{
288 struct DisconnectList *dl = cls; 246 struct Peer *pos;
289 247
248 pos = GNUNET_CONTAINER_multihashmap_get (peers, &pid->hashPubKey);
249 if ( (pos != NULL) &&
250 (pos->is_friend == GNUNET_YES) )
251 return GNUNET_OK;
290 GNUNET_STATISTICS_update (stats, 252 GNUNET_STATISTICS_update (stats,
291 gettext_noop ("# peers blacklisted"), 253 gettext_noop ("# peers blacklisted"),
292 1, 254 1,
293 GNUNET_NO); 255 GNUNET_NO);
294 GNUNET_CONTAINER_DLL_remove (disconnect_head, 256 return GNUNET_SYSERR;
295 disconnect_tail,
296 dl);
297 GNUNET_free (dl);
298}
299
300
301/**
302 * Force a disconnect from the specified peer.
303 *
304 * @param pl peer to disconnect
305 */
306static void
307force_disconnect (struct Peer *pl)
308{
309 const struct GNUNET_PeerIdentity *peer = &pl->pid;
310 struct DisconnectList *dl;
311
312 if (NULL != pl->wh)
313 {
314 GNUNET_TRANSPORT_blacklist_cancel (pl->wh);
315 pl->wh = NULL;
316 }
317 pl->is_blocked = GNUNET_YES;
318 dl = GNUNET_malloc (sizeof (struct DisconnectList));
319 dl->peer = *peer;
320 GNUNET_CONTAINER_DLL_insert (disconnect_head,
321 disconnect_tail,
322 dl);
323 dl->rh = GNUNET_TRANSPORT_blacklist (sched, cfg,
324 peer,
325 GNUNET_TIME_UNIT_FOREVER_REL,
326 GNUNET_TIME_UNIT_FOREVER_REL,
327 &disconnect_done,
328 dl);
329}
330
331
332
333/**
334 * Function called once our request to 'whitelist' a peer
335 * has completed.
336 *
337 * @param cls our 'struct Peer'
338 * @param tc unused
339 */
340static void
341whitelist_done (void *cls,
342 const struct GNUNET_SCHEDULER_TaskContext *tc)
343{
344 struct Peer *pl = cls;
345
346 pl->wh = NULL;
347 GNUNET_STATISTICS_update (stats,
348 gettext_noop ("# peers blacklisted"),
349 -1,
350 GNUNET_NO);
351}
352
353
354/**
355 * Whitelist the given peer (if it was blacklisted before).
356 *
357 * @param cls closure (not used)
358 * @param pid identity of the peer
359 * @param value peer to free
360 * @return GNUNET_YES (always: continue to iterate)
361 */
362static int
363whitelist_peer (void *cls,
364 const GNUNET_HashCode *pid,
365 void *value)
366{
367 struct Peer *pl = value;
368
369 if (! pl->is_blocked)
370 return GNUNET_YES;
371 pl->wh = GNUNET_TRANSPORT_blacklist (sched, cfg,
372 &pl->pid,
373 GNUNET_TIME_UNIT_ZERO,
374 GNUNET_TIME_UNIT_FOREVER_REL,
375 &whitelist_done,
376 pl);
377 pl->is_blocked = GNUNET_NO;
378 return GNUNET_YES;
379} 257}
380 258
381 259
@@ -386,22 +264,11 @@ whitelist_peer (void *cls,
386static void 264static void
387whitelist_peers () 265whitelist_peers ()
388{ 266{
389 struct DisconnectList *dl; 267 if (blacklist != NULL)
390
391 /* first, cancel all blacklisting requests */
392 while (NULL != (dl = disconnect_head))
393 { 268 {
394 GNUNET_CONTAINER_DLL_remove (disconnect_head, 269 GNUNET_TRANSPORT_blacklist_cancel (blacklist);
395 disconnect_tail, 270 blacklist = NULL;
396 dl);
397 GNUNET_TRANSPORT_blacklist_cancel (dl->rh);
398 GNUNET_free (dl);
399 } 271 }
400 /* then, specifically whitelist all peers that we
401 know to have blacklisted */
402 GNUNET_CONTAINER_multihashmap_iterate (peers,
403 &whitelist_peer,
404 NULL);
405} 272}
406 273
407 274
@@ -477,8 +344,6 @@ free_peer (void *cls,
477 pos)); 344 pos));
478 if (pos->hello_req != NULL) 345 if (pos->hello_req != NULL)
479 GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req); 346 GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req);
480 if (pos->wh != NULL)
481 GNUNET_TRANSPORT_blacklist_cancel (pos->wh);
482 if (pos->connect_req != NULL) 347 if (pos->connect_req != NULL)
483 GNUNET_CORE_peer_request_connect_cancel (pos->connect_req); 348 GNUNET_CORE_peer_request_connect_cancel (pos->connect_req);
484 if (pos->hello_delay_task != GNUNET_SCHEDULER_NO_TASK) 349 if (pos->hello_delay_task != GNUNET_SCHEDULER_NO_TASK)
@@ -521,8 +386,6 @@ attempt_connect (struct Peer *pos)
521 return; 386 return;
522 if (GNUNET_OK != is_connection_allowed (pos)) 387 if (GNUNET_OK != is_connection_allowed (pos))
523 return; 388 return;
524 if (GNUNET_YES == pos->is_blocked)
525 return;
526 if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).value > 0) 389 if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).value > 0)
527 return; 390 return;
528 if (GNUNET_YES == pos->is_friend) 391 if (GNUNET_YES == pos->is_friend)
@@ -593,7 +456,6 @@ remove_from_greylist (void *cls,
593 pos); 456 pos);
594 } 457 }
595 if ( (GNUNET_NO == pos->is_friend) && 458 if ( (GNUNET_NO == pos->is_friend) &&
596 (GNUNET_NO == pos->is_blocked) &&
597 (GNUNET_NO == pos->is_connected) ) 459 (GNUNET_NO == pos->is_connected) )
598 { 460 {
599 free_peer (NULL, &pos->pid.hashPubKey, pos); 461 free_peer (NULL, &pos->pid.hashPubKey, pos);
@@ -863,18 +725,7 @@ connect_notify (void *cls,
863 if (pos == NULL) 725 if (pos == NULL)
864 { 726 {
865 pos = make_peer (peer, NULL, GNUNET_NO); 727 pos = make_peer (peer, NULL, GNUNET_NO);
866 if (GNUNET_OK != is_connection_allowed (pos)) 728 GNUNET_break (GNUNET_OK == is_connection_allowed (pos));
867 {
868 GNUNET_assert (pos->is_friend == GNUNET_NO);
869 pos->is_connected = GNUNET_YES;
870#if DEBUG_TOPOLOGY
871 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
872 "Connection to `%s' is forbidden, forcing disconnect!\n",
873 GNUNET_i2s (peer));
874#endif
875 force_disconnect (pos);
876 return;
877 }
878 } 729 }
879 else 730 else
880 { 731 {
@@ -899,35 +750,6 @@ connect_notify (void *cls,
899 750
900 751
901/** 752/**
902 * Disconnect from all non-friends (we're below quota).
903 *
904 * @param cls closure, not used
905 * @param pid identity of a peer
906 * @param value 'struct Peer*' for the peer
907 * @return GNUNET_YES (continue to iterate)
908 */
909static int
910drop_non_friends (void *cls,
911 const GNUNET_HashCode *pid,
912 void *value)
913{
914 struct Peer *pos = value;
915
916 if ( (GNUNET_NO == pos->is_friend) &&
917 (GNUNET_YES == pos->is_connected) )
918 {
919#if DEBUG_TOPOLOGY
920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
921 "Connection to `%s' is not from a friend, forcing disconnect!\n",
922 GNUNET_i2s (&pos->pid));
923#endif
924 force_disconnect (pos);
925 }
926 return GNUNET_YES;
927}
928
929
930/**
931 * Try to add more peers to our connection set. 753 * Try to add more peers to our connection set.
932 * 754 *
933 * @param cls closure, not used 755 * @param cls closure, not used
@@ -995,17 +817,10 @@ disconnect_notify (void *cls,
995 GNUNET_CONTAINER_multihashmap_iterate (peers, 817 GNUNET_CONTAINER_multihashmap_iterate (peers,
996 &try_add_peers, 818 &try_add_peers,
997 NULL); 819 NULL);
998 if (friend_count < minimum_friend_count) 820 if ( (friend_count < minimum_friend_count) &&
999 { 821 (blacklist == NULL) )
1000 /* disconnect from all non-friends */ 822 blacklist = GNUNET_TRANSPORT_blacklist (sched, cfg,
1001#if DEBUG_TOPOLOGY 823 &blacklist_check, NULL);
1002 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1003 "Not enough friendly connections, dropping all non-friend connections\n");
1004#endif
1005 GNUNET_CONTAINER_multihashmap_iterate (peers,
1006 &drop_non_friends,
1007 NULL);
1008 }
1009} 824}
1010 825
1011 826
@@ -1389,13 +1204,21 @@ handle_encrypted_hello (void *cls,
1389 GNUNET_NO); 1204 GNUNET_NO);
1390 peer = GNUNET_CONTAINER_multihashmap_get (peers, 1205 peer = GNUNET_CONTAINER_multihashmap_get (peers,
1391 &pid.hashPubKey); 1206 &pid.hashPubKey);
1392 if ( (peer != NULL) && 1207 if (peer == NULL)
1393 (peer->is_blocked) ) 1208 {
1394 return GNUNET_OK; /* ignore: currently blocked */ 1209 if ( (GNUNET_YES == friends_only) ||
1395 if ( (GNUNET_YES == friends_only) && 1210 (friend_count < minimum_friend_count) )
1396 ( (peer == NULL) || 1211 return GNUNET_OK;
1397 (GNUNET_YES != peer->is_friend) ) ) 1212 }
1398 return GNUNET_OK; /* ignore: not a friend */ 1213 else
1214 {
1215 if ( (GNUNET_YES != peer->is_friend) &&
1216 (GNUNET_YES == friends_only) )
1217 return GNUNET_OK;
1218 if ( (GNUNET_YES != peer->is_friend) &&
1219 (friend_count < minimum_friend_count) )
1220 return GNUNET_OK;
1221 }
1399 if (transport != NULL) 1222 if (transport != NULL)
1400 GNUNET_TRANSPORT_offer_hello (transport, 1223 GNUNET_TRANSPORT_offer_hello (transport,
1401 message); 1224 message);
@@ -1468,8 +1291,6 @@ static void
1468cleaning_task (void *cls, 1291cleaning_task (void *cls,
1469 const struct GNUNET_SCHEDULER_TaskContext *tc) 1292 const struct GNUNET_SCHEDULER_TaskContext *tc)
1470{ 1293{
1471 struct DisconnectList *dl;
1472
1473 if (NULL != peerinfo_notify) 1294 if (NULL != peerinfo_notify)
1474 { 1295 {
1475 GNUNET_PEERINFO_notify_cancel (peerinfo_notify); 1296 GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
@@ -1486,14 +1307,7 @@ cleaning_task (void *cls,
1486 GNUNET_CORE_disconnect (handle); 1307 GNUNET_CORE_disconnect (handle);
1487 handle = NULL; 1308 handle = NULL;
1488 } 1309 }
1489 while (NULL != (dl = disconnect_head)) 1310 whitelist_peers ();
1490 {
1491 GNUNET_CONTAINER_DLL_remove (disconnect_head,
1492 disconnect_tail,
1493 dl);
1494 GNUNET_TRANSPORT_blacklist_cancel (dl->rh);
1495 GNUNET_free (dl);
1496 }
1497 if (stats != NULL) 1311 if (stats != NULL)
1498 { 1312 {
1499 GNUNET_STATISTICS_destroy (stats, GNUNET_NO); 1313 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
@@ -1560,6 +1374,9 @@ run (void *cls,
1560 minimum_friend_count, 1374 minimum_friend_count,
1561 autoconnect ? "autoconnect enabled" : "autoconnect disabled"); 1375 autoconnect ? "autoconnect enabled" : "autoconnect disabled");
1562#endif 1376#endif
1377 if (friend_count < minimum_friend_count)
1378 blacklist = GNUNET_TRANSPORT_blacklist (sched, cfg,
1379 &blacklist_check, NULL);
1563 transport = GNUNET_TRANSPORT_connect (sched, 1380 transport = GNUNET_TRANSPORT_connect (sched,
1564 cfg, 1381 cfg,
1565 NULL, 1382 NULL,
@@ -1571,7 +1388,6 @@ run (void *cls,
1571 GNUNET_TIME_UNIT_FOREVER_REL, 1388 GNUNET_TIME_UNIT_FOREVER_REL,
1572 NULL, 1389 NULL,
1573 &core_init, 1390 &core_init,
1574 NULL,
1575 &connect_notify, 1391 &connect_notify,
1576 &disconnect_notify, 1392 &disconnect_notify,
1577 NULL, GNUNET_NO, 1393 NULL, GNUNET_NO,