diff options
author | t3sserakt <t3ss@posteo.de> | 2020-06-12 12:51:46 +0200 |
---|---|---|
committer | t3sserakt <t3ss@posteo.de> | 2020-06-12 12:51:46 +0200 |
commit | 726ac3ef2819e41aa5f045d76d9966b078934e32 (patch) | |
tree | bb94685c92fd06acfd1e9e2866b2afdffe1ec477 /src/transport/gnunet-communicator-tcp.c | |
parent | 11dbdc79aeb05e82913ac70cf2ac8d4f45b02c28 (diff) | |
download | gnunet-726ac3ef2819e41aa5f045d76d9966b078934e32.tar.gz gnunet-726ac3ef2819e41aa5f045d76d9966b078934e32.zip |
Fixed 5528: TCP *communicator* bindto option should support DNS names, and 6013: TCP communicator should bind to IPv6 and IPv4 if only port given
Diffstat (limited to 'src/transport/gnunet-communicator-tcp.c')
-rw-r--r-- | src/transport/gnunet-communicator-tcp.c | 898 |
1 files changed, 684 insertions, 214 deletions
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c index 7f70c55df..e25cdf139 100644 --- a/src/transport/gnunet-communicator-tcp.c +++ b/src/transport/gnunet-communicator-tcp.c | |||
@@ -40,8 +40,10 @@ | |||
40 | #include "gnunet_nt_lib.h" | 40 | #include "gnunet_nt_lib.h" |
41 | #include "gnunet_nat_service.h" | 41 | #include "gnunet_nat_service.h" |
42 | #include "gnunet_statistics_service.h" | 42 | #include "gnunet_statistics_service.h" |
43 | #include "gnunet_ats_transport_service.h" | ||
44 | #include "transport.h" | ||
43 | #include "gnunet_transport_communication_service.h" | 45 | #include "gnunet_transport_communication_service.h" |
44 | 46 | #include "gnunet_resolver_service.h" | |
45 | /** | 47 | /** |
46 | * How long do we believe our addresses to remain up (before | 48 | * How long do we believe our addresses to remain up (before |
47 | * the other peer should revalidate). | 49 | * the other peer should revalidate). |
@@ -253,6 +255,21 @@ struct TCPFinish | |||
253 | 255 | ||
254 | GNUNET_NETWORK_STRUCT_END | 256 | GNUNET_NETWORK_STRUCT_END |
255 | 257 | ||
258 | /** | ||
259 | * Struct to use as closure. | ||
260 | */ | ||
261 | struct ListenTask | ||
262 | { | ||
263 | /** | ||
264 | * ID of listen task | ||
265 | */ | ||
266 | struct GNUNET_SCHEDULER_Task *listen_task; | ||
267 | |||
268 | /** | ||
269 | * Listen socket. | ||
270 | */ | ||
271 | struct GNUNET_NETWORK_Handle *listen_sock; | ||
272 | }; | ||
256 | 273 | ||
257 | /** | 274 | /** |
258 | * Handle for a queue. | 275 | * Handle for a queue. |
@@ -265,6 +282,16 @@ struct Queue | |||
265 | struct GNUNET_PeerIdentity target; | 282 | struct GNUNET_PeerIdentity target; |
266 | 283 | ||
267 | /** | 284 | /** |
285 | * ID of listen task | ||
286 | */ | ||
287 | struct GNUNET_SCHEDULER_Task *listen_task; | ||
288 | |||
289 | /** | ||
290 | * Listen socket. | ||
291 | */ | ||
292 | struct GNUNET_NETWORK_Handle *listen_sock; | ||
293 | |||
294 | /** | ||
268 | * socket that we transmit all data with on this queue | 295 | * socket that we transmit all data with on this queue |
269 | */ | 296 | */ |
270 | struct GNUNET_NETWORK_Handle *sock; | 297 | struct GNUNET_NETWORK_Handle *sock; |
@@ -449,6 +476,16 @@ struct ProtoQueue | |||
449 | struct ProtoQueue *prev; | 476 | struct ProtoQueue *prev; |
450 | 477 | ||
451 | /** | 478 | /** |
479 | * ID of listen task | ||
480 | */ | ||
481 | struct GNUNET_SCHEDULER_Task *listen_task; | ||
482 | |||
483 | /** | ||
484 | * Listen socket. | ||
485 | */ | ||
486 | struct GNUNET_NETWORK_Handle *listen_sock; | ||
487 | |||
488 | /** | ||
452 | * socket that we transmit all data with on this queue | 489 | * socket that we transmit all data with on this queue |
453 | */ | 490 | */ |
454 | struct GNUNET_NETWORK_Handle *sock; | 491 | struct GNUNET_NETWORK_Handle *sock; |
@@ -485,11 +522,61 @@ struct ProtoQueue | |||
485 | size_t ibuf_off; | 522 | size_t ibuf_off; |
486 | }; | 523 | }; |
487 | 524 | ||
525 | /** | ||
526 | * In case of port only configuration we like to bind to ipv4 and ipv6 addresses. | ||
527 | */ | ||
528 | struct PortOnlyIpv4Ipv6 | ||
529 | { | ||
530 | /** | ||
531 | * Ipv4 address we like to bind to. | ||
532 | */ | ||
533 | struct sockaddr *addr_ipv4; | ||
534 | |||
535 | /** | ||
536 | * Length of ipv4 address. | ||
537 | */ | ||
538 | socklen_t *addr_len_ipv4; | ||
539 | |||
540 | /** | ||
541 | * Ipv6 address we like to bind to. | ||
542 | */ | ||
543 | struct sockaddr *addr_ipv6; | ||
544 | |||
545 | /** | ||
546 | * Length of ipv6 address. | ||
547 | */ | ||
548 | socklen_t *addr_len_ipv6; | ||
549 | |||
550 | }; | ||
488 | 551 | ||
489 | /** | 552 | /** |
490 | * ID of listen task | 553 | * DLL to store the addresses we like to register at NAT service. |
491 | */ | 554 | */ |
492 | static struct GNUNET_SCHEDULER_Task *listen_task; | 555 | struct Addresses |
556 | { | ||
557 | /** | ||
558 | * Kept in a DLL. | ||
559 | */ | ||
560 | struct Addresses *next; | ||
561 | |||
562 | /** | ||
563 | * Kept in a DLL. | ||
564 | */ | ||
565 | struct Addresses *prev; | ||
566 | |||
567 | /** | ||
568 | * Address we like to register at NAT service. | ||
569 | */ | ||
570 | struct sockaddr *addr; | ||
571 | |||
572 | /** | ||
573 | * Length of address we like to register at NAT service. | ||
574 | */ | ||
575 | socklen_t addr_len; | ||
576 | |||
577 | }; | ||
578 | |||
579 | |||
493 | 580 | ||
494 | /** | 581 | /** |
495 | * Maximum queue length before we stop reading towards the transport service. | 582 | * Maximum queue length before we stop reading towards the transport service. |
@@ -512,11 +599,6 @@ static struct GNUNET_TRANSPORT_CommunicatorHandle *ch; | |||
512 | static struct GNUNET_CONTAINER_MultiPeerMap *queue_map; | 599 | static struct GNUNET_CONTAINER_MultiPeerMap *queue_map; |
513 | 600 | ||
514 | /** | 601 | /** |
515 | * Listen socket. | ||
516 | */ | ||
517 | static struct GNUNET_NETWORK_Handle *listen_sock; | ||
518 | |||
519 | /** | ||
520 | * Our public key. | 602 | * Our public key. |
521 | */ | 603 | */ |
522 | static struct GNUNET_PeerIdentity my_identity; | 604 | static struct GNUNET_PeerIdentity my_identity; |
@@ -556,6 +638,25 @@ static struct ProtoQueue *proto_head; | |||
556 | */ | 638 | */ |
557 | static struct ProtoQueue *proto_tail; | 639 | static struct ProtoQueue *proto_tail; |
558 | 640 | ||
641 | /** | ||
642 | * Handle for DNS lookup of bindto address | ||
643 | */ | ||
644 | struct GNUNET_RESOLVER_RequestHandle *resolve_request_handle; | ||
645 | |||
646 | /** | ||
647 | * Head of DLL with addresses we like to register at NAT servcie. | ||
648 | */ | ||
649 | struct Addresses *addrs_head; | ||
650 | |||
651 | /** | ||
652 | * Head of DLL with addresses we like to register at NAT servcie. | ||
653 | */ | ||
654 | struct Addresses *addrs_tail; | ||
655 | |||
656 | /** | ||
657 | * Number of addresses in the DLL for register at NAT service. | ||
658 | */ | ||
659 | int addrs_lens; | ||
559 | 660 | ||
560 | /** | 661 | /** |
561 | * We have been notified that our listen socket has something to | 662 | * We have been notified that our listen socket has something to |
@@ -579,6 +680,10 @@ static void | |||
579 | queue_destroy (struct Queue *queue) | 680 | queue_destroy (struct Queue *queue) |
580 | { | 681 | { |
581 | struct GNUNET_MQ_Handle *mq; | 682 | struct GNUNET_MQ_Handle *mq; |
683 | struct ListenTask *lt; | ||
684 | lt = GNUNET_new (struct ListenTask); | ||
685 | lt->listen_sock = queue->listen_sock; | ||
686 | lt->listen_task = queue->listen_task; | ||
582 | 687 | ||
583 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 688 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
584 | "Disconnecting queue for peer `%s'\n", | 689 | "Disconnecting queue for peer `%s'\n", |
@@ -618,11 +723,13 @@ queue_destroy (struct Queue *queue) | |||
618 | queue->destroyed = GNUNET_YES; | 723 | queue->destroyed = GNUNET_YES; |
619 | else | 724 | else |
620 | GNUNET_free (queue); | 725 | GNUNET_free (queue); |
621 | if (NULL == listen_task) | 726 | |
622 | listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | 727 | if (NULL == lt->listen_task) |
623 | listen_sock, | 728 | lt->listen_task = GNUNET_SCHEDULER_add_read_net ( |
624 | &listen_cb, | 729 | GNUNET_TIME_UNIT_FOREVER_REL, |
625 | NULL); | 730 | lt->listen_sock, |
731 | &listen_cb, | ||
732 | lt); | ||
626 | } | 733 | } |
627 | 734 | ||
628 | 735 | ||
@@ -1063,7 +1170,8 @@ queue_read (void *cls) | |||
1063 | However, we have to take into account that the plaintext buffer may have | 1170 | However, we have to take into account that the plaintext buffer may have |
1064 | already contained data and not jumpt too far ahead in the ciphertext. | 1171 | already contained data and not jumpt too far ahead in the ciphertext. |
1065 | If there is no rekey and the last message is incomplete (max > total), | 1172 | If there is no rekey and the last message is incomplete (max > total), |
1066 | it is safe to keep the decryption so we shift by 'max' */if (GNUNET_YES == queue->rekeyed) | 1173 | it is safe to keep the decryption so we shift by 'max' */ |
1174 | if (GNUNET_YES == queue->rekeyed) | ||
1067 | { | 1175 | { |
1068 | max = total - old_pread_off; | 1176 | max = total - old_pread_off; |
1069 | queue->rekeyed = GNUNET_NO; | 1177 | queue->rekeyed = GNUNET_NO; |
@@ -1095,143 +1203,276 @@ queue_read (void *cls) | |||
1095 | queue_finish (queue); | 1203 | queue_finish (queue); |
1096 | } | 1204 | } |
1097 | 1205 | ||
1206 | /** | ||
1207 | * Convert a `struct sockaddr_in6 to a `struct sockaddr *` | ||
1208 | * | ||
1209 | * @param[out] sock_len set to the length of the address. | ||
1210 | * @param v6 The sockaddr_in6 to be converted. | ||
1211 | * @return The struct sockaddr *. | ||
1212 | */ | ||
1213 | static struct sockaddr * | ||
1214 | tcp_address_to_sockaddr_numeric_v6 (socklen_t *sock_len, struct sockaddr_in6 v6, | ||
1215 | unsigned int port) | ||
1216 | { | ||
1217 | struct sockaddr *in; | ||
1218 | |||
1219 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1220 | "1 address %s\n", | ||
1221 | GNUNET_a2s (in, *sock_len)); | ||
1222 | |||
1223 | v6.sin6_family = AF_INET6; | ||
1224 | v6.sin6_port = htons ((uint16_t) port); | ||
1225 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
1226 | v6.sin6_len = sizeof(sizeof(struct sockaddr_in6)); | ||
1227 | #endif | ||
1228 | in = GNUNET_memdup (&v6, sizeof(v6)); | ||
1229 | *sock_len = sizeof(struct sockaddr_in6); | ||
1230 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1231 | "address %s\n", | ||
1232 | GNUNET_a2s (in, *sock_len)); | ||
1233 | |||
1234 | return in; | ||
1235 | } | ||
1098 | 1236 | ||
1099 | /** | 1237 | /** |
1100 | * Convert TCP bind specification to a `struct sockaddr *` | 1238 | * Convert a `struct sockaddr_in4 to a `struct sockaddr *` |
1101 | * | 1239 | * |
1102 | * @param bindto bind specification to convert | 1240 | * @param[out] sock_len set to the length of the address. |
1103 | * @param[out] sock_len set to the length of the address | 1241 | * @param v4 The sockaddr_in4 to be converted. |
1104 | * @return converted bindto specification | 1242 | * @return The struct sockaddr *. |
1105 | */ | 1243 | */ |
1106 | static struct sockaddr * | 1244 | static struct sockaddr * |
1107 | tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len) | 1245 | tcp_address_to_sockaddr_numeric_v4 (socklen_t *sock_len, struct sockaddr_in v4, |
1246 | unsigned int port) | ||
1108 | { | 1247 | { |
1109 | struct sockaddr *in; | 1248 | struct sockaddr *in; |
1110 | unsigned int port; | 1249 | |
1111 | char dummy[2]; | 1250 | v4.sin_family = AF_INET; |
1112 | char *colon; | 1251 | v4.sin_port = htons ((uint16_t) port); |
1252 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
1253 | v4.sin_len = sizeof(struct sockaddr_in); | ||
1254 | #endif | ||
1255 | in = GNUNET_memdup (&v4, sizeof(v4)); | ||
1256 | *sock_len = sizeof(struct sockaddr_in); | ||
1257 | return in; | ||
1258 | } | ||
1259 | |||
1260 | /** | ||
1261 | * Convert TCP bind specification to a `struct PortOnlyIpv4Ipv6 *` | ||
1262 | * | ||
1263 | * @param bindto bind specification to convert. | ||
1264 | * @return The converted bindto specification. | ||
1265 | */ | ||
1266 | static struct PortOnlyIpv4Ipv6 * | ||
1267 | tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int *port) | ||
1268 | { | ||
1269 | struct PortOnlyIpv4Ipv6 *po; | ||
1270 | struct sockaddr_in *i4; | ||
1271 | struct sockaddr_in6 *i6; | ||
1272 | socklen_t sock_len_ipv4; | ||
1273 | socklen_t sock_len_ipv6; | ||
1274 | |||
1275 | /* interpreting value as just a PORT number */ | ||
1276 | if (*port > UINT16_MAX) | ||
1277 | { | ||
1278 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1279 | "BINDTO specification `%s' invalid: value too large for port\n", | ||
1280 | bindto); | ||
1281 | return NULL; | ||
1282 | } | ||
1283 | |||
1284 | po = GNUNET_new (struct PortOnlyIpv4Ipv6); | ||
1285 | |||
1286 | if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) || | ||
1287 | (GNUNET_YES == | ||
1288 | GNUNET_CONFIGURATION_get_value_yesno (cfg, | ||
1289 | COMMUNICATOR_CONFIG_SECTION, | ||
1290 | "DISABLE_V6"))) | ||
1291 | { | ||
1292 | i4 = GNUNET_malloc (sizeof(struct sockaddr_in)); | ||
1293 | po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4, | ||
1294 | *port); | ||
1295 | po->addr_len_ipv4 = &sock_len_ipv4; | ||
1296 | } | ||
1297 | else | ||
1298 | { | ||
1299 | |||
1300 | i4 = GNUNET_malloc (sizeof(struct sockaddr_in)); | ||
1301 | po->addr_ipv4 = tcp_address_to_sockaddr_numeric_v4 (&sock_len_ipv4, *i4, | ||
1302 | *port); | ||
1303 | po->addr_len_ipv4 = &sock_len_ipv4; | ||
1304 | |||
1305 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1306 | "3.5 address %s\n", | ||
1307 | GNUNET_a2s (po->addr_ipv4, sock_len_ipv4)); | ||
1308 | |||
1309 | i6 = GNUNET_malloc (sizeof(struct sockaddr_in6)); | ||
1310 | po->addr_ipv6 = tcp_address_to_sockaddr_numeric_v6 (&sock_len_ipv6, *i6, | ||
1311 | *port); | ||
1312 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1313 | "3 address %s\n", | ||
1314 | GNUNET_a2s (po->addr_ipv6, sock_len_ipv6)); | ||
1315 | |||
1316 | po->addr_len_ipv6 = &sock_len_ipv6; | ||
1317 | } | ||
1318 | return po; | ||
1319 | } | ||
1320 | |||
1321 | /** | ||
1322 | * This Method extracts the address part of the BINDTO string. | ||
1323 | * | ||
1324 | * @param bindto String we extract the address part from. | ||
1325 | * @return The extracted address string. | ||
1326 | */ | ||
1327 | static char * | ||
1328 | extract_address (const char *bindto) | ||
1329 | { | ||
1330 | |||
1331 | char *start; | ||
1332 | char *token; | ||
1113 | char *cp; | 1333 | char *cp; |
1334 | char *rest = NULL; | ||
1114 | 1335 | ||
1115 | if (1 == sscanf (bindto, "%u%1s", &port, dummy)) | 1336 | if (NULL == bindto) |
1337 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1338 | "bindto is NULL\n"); | ||
1339 | |||
1340 | cp = GNUNET_strdup (bindto); | ||
1341 | start = cp; | ||
1342 | if (('[' == *cp) && (']' == cp[strlen (cp) - 1])) | ||
1116 | { | 1343 | { |
1117 | /* interpreting value as just a PORT number */ | 1344 | start++; /* skip over '['*/ |
1118 | if (port > UINT16_MAX) | 1345 | cp[strlen (cp) - 1] = '\0'; /* eat ']'*/ |
1346 | } | ||
1347 | else { | ||
1348 | token = strtok_r (cp, "]", &rest); | ||
1349 | if (strlen (bindto) == strlen (token)) | ||
1119 | { | 1350 | { |
1120 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1351 | token = strtok_r (cp, ":", &rest); |
1121 | "BINDTO specification `%s' invalid: value too large for port\n", | ||
1122 | bindto); | ||
1123 | return NULL; | ||
1124 | } | 1352 | } |
1125 | if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) || | 1353 | else |
1126 | (GNUNET_YES == | ||
1127 | GNUNET_CONFIGURATION_get_value_yesno (cfg, | ||
1128 | COMMUNICATOR_CONFIG_SECTION, | ||
1129 | "DISABLE_V6"))) | ||
1130 | { | 1354 | { |
1131 | struct sockaddr_in *i4; | 1355 | token++; |
1356 | return token; | ||
1357 | } | ||
1358 | } | ||
1132 | 1359 | ||
1133 | i4 = GNUNET_malloc (sizeof(struct sockaddr_in)); | 1360 | // GNUNET_free(cp); |
1134 | i4->sin_family = AF_INET; | 1361 | |
1135 | i4->sin_port = htons ((uint16_t) port); | 1362 | return start; |
1136 | #if HAVE_SOCKADDR_IN_SIN_LEN | 1363 | } |
1137 | i4->sin_len = sizeof(sizeof(struct sockaddr_in)); | 1364 | |
1138 | #endif | 1365 | /** |
1139 | *sock_len = sizeof(struct sockaddr_in); | 1366 | * This Method extracts the port part of the BINDTO string. |
1140 | in = (struct sockaddr *) i4; | 1367 | * |
1368 | * @param addr_and_port String we extract the port from. | ||
1369 | * @return The extracted port as unsigned int. | ||
1370 | */ | ||
1371 | static unsigned int | ||
1372 | extract_port (const char *addr_and_port) | ||
1373 | { | ||
1374 | unsigned int port; | ||
1375 | char dummy[2]; | ||
1376 | char *token; | ||
1377 | char *addr; | ||
1378 | char *colon; | ||
1379 | char *cp; | ||
1380 | char *rest = NULL; | ||
1381 | |||
1382 | if (NULL != addr_and_port) | ||
1383 | { | ||
1384 | cp = GNUNET_strdup (addr_and_port); | ||
1385 | token = strtok_r (cp, "]", &rest); | ||
1386 | if (strlen (addr_and_port) == strlen (token)) | ||
1387 | { | ||
1388 | colon = strrchr (cp, ':'); | ||
1389 | if (NULL == colon) | ||
1390 | { | ||
1391 | return 0; | ||
1392 | } | ||
1393 | addr = colon; | ||
1394 | addr++; | ||
1141 | } | 1395 | } |
1142 | else | 1396 | else |
1143 | { | 1397 | { |
1144 | struct sockaddr_in6 *i6; | 1398 | token = strtok_r (NULL, "]", &rest); |
1145 | 1399 | if (NULL == token) | |
1146 | i6 = GNUNET_malloc (sizeof(struct sockaddr_in6)); | 1400 | { |
1147 | i6->sin6_family = AF_INET6; | 1401 | return 0; |
1148 | i6->sin6_port = htons ((uint16_t) port); | 1402 | } |
1149 | #if HAVE_SOCKADDR_IN_SIN_LEN | 1403 | else |
1150 | i6->sin6_len = sizeof(sizeof(struct sockaddr_in6)); | 1404 | { |
1151 | #endif | 1405 | addr = token; |
1152 | *sock_len = sizeof(struct sockaddr_in6); | 1406 | addr++; |
1153 | in = (struct sockaddr *) i6; | 1407 | } |
1154 | } | 1408 | } |
1155 | return in; | 1409 | |
1156 | } | 1410 | |
1157 | cp = GNUNET_strdup (bindto); | 1411 | if (1 == sscanf (addr, "%u%1s", &port, dummy)) |
1158 | colon = strrchr (cp, ':'); | ||
1159 | if (NULL != colon) | ||
1160 | { | ||
1161 | /* interpet value after colon as port */ | ||
1162 | *colon = '\0'; | ||
1163 | colon++; | ||
1164 | if (1 == sscanf (colon, "%u%1s", &port, dummy)) | ||
1165 | { | 1412 | { |
1166 | /* interpreting value as just a PORT number */ | 1413 | /* interpreting value as just a PORT number */ |
1167 | if (port > UINT16_MAX) | 1414 | if (port > UINT16_MAX) |
1168 | { | 1415 | { |
1169 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1416 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1170 | "BINDTO specification `%s' invalid: value too large for port\n", | 1417 | "Port `%u' invalid: value too large for port\n", |
1171 | bindto); | 1418 | port); |
1172 | GNUNET_free (cp); | 1419 | // GNUNET_free (cp); |
1173 | return NULL; | 1420 | return 0; |
1174 | } | 1421 | } |
1175 | } | 1422 | } |
1176 | else | 1423 | else |
1177 | { | 1424 | { |
1178 | GNUNET_log ( | 1425 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1179 | GNUNET_ERROR_TYPE_ERROR, | 1426 | "BINDTO specification invalid: last ':' not followed by number\n"); |
1180 | "BINDTO specification `%s' invalid: last ':' not followed by number\n", | 1427 | // GNUNET_free (cp); |
1181 | bindto); | 1428 | return 0; |
1182 | GNUNET_free (cp); | ||
1183 | return NULL; | ||
1184 | } | 1429 | } |
1185 | } | 1430 | } |
1186 | else | 1431 | else |
1187 | { | 1432 | { |
1433 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1434 | "return 0\n"); | ||
1188 | /* interpret missing port as 0, aka pick any free one */ | 1435 | /* interpret missing port as 0, aka pick any free one */ |
1189 | port = 0; | 1436 | port = 0; |
1190 | } | 1437 | } |
1191 | { | ||
1192 | /* try IPv4 */ | ||
1193 | struct sockaddr_in v4; | ||
1194 | 1438 | ||
1195 | if (1 == inet_pton (AF_INET, cp, &v4.sin_addr)) | 1439 | |
1196 | { | 1440 | return port; |
1197 | v4.sin_family = AF_INET; | 1441 | } |
1198 | v4.sin_port = htons ((uint16_t) port); | 1442 | |
1199 | #if HAVE_SOCKADDR_IN_SIN_LEN | 1443 | /** |
1200 | v4.sin_len = sizeof(struct sockaddr_in); | 1444 | * Convert TCP bind specification to a `struct sockaddr *` |
1201 | #endif | 1445 | * |
1202 | in = GNUNET_memdup (&v4, sizeof(v4)); | 1446 | * @param bindto bind specification to convert |
1203 | *sock_len = sizeof(v4); | 1447 | * @param[out] sock_len set to the length of the address |
1204 | GNUNET_free (cp); | 1448 | * @return converted bindto specification |
1205 | return in; | 1449 | */ |
1206 | } | 1450 | static struct sockaddr * |
1451 | tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len) | ||
1452 | { | ||
1453 | struct sockaddr *in; | ||
1454 | unsigned int port; | ||
1455 | struct sockaddr_in v4; | ||
1456 | struct sockaddr_in6 v6; | ||
1457 | const char *start; | ||
1458 | |||
1459 | // cp = GNUNET_strdup (bindto); | ||
1460 | start = extract_address (bindto); | ||
1461 | |||
1462 | if (1 == inet_pton (AF_INET, start, &v4.sin_addr)) | ||
1463 | { | ||
1464 | // colon = strrchr (cp, ':'); | ||
1465 | port = extract_port (bindto); | ||
1466 | in = tcp_address_to_sockaddr_numeric_v4 (sock_len, v4, port); | ||
1207 | } | 1467 | } |
1468 | else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr)) | ||
1208 | { | 1469 | { |
1209 | /* try IPv6 */ | 1470 | // colon = strrchr (cp, ':'); |
1210 | struct sockaddr_in6 v6; | 1471 | port = extract_port (bindto); |
1211 | const char *start; | 1472 | in = tcp_address_to_sockaddr_numeric_v6 (sock_len, v6, port); |
1212 | |||
1213 | start = cp; | ||
1214 | if (('[' == *cp) && (']' == cp[strlen (cp) - 1])) | ||
1215 | { | ||
1216 | start++; /* skip over '[' */ | ||
1217 | cp[strlen (cp) - 1] = '\0'; /* eat ']' */ | ||
1218 | } | ||
1219 | if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr)) | ||
1220 | { | ||
1221 | v6.sin6_family = AF_INET6; | ||
1222 | v6.sin6_port = htons ((uint16_t) port); | ||
1223 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
1224 | v6.sin6_len = sizeof(sizeof(struct sockaddr_in6)); | ||
1225 | #endif | ||
1226 | in = GNUNET_memdup (&v6, sizeof(v6)); | ||
1227 | *sock_len = sizeof(v6); | ||
1228 | GNUNET_free (cp); | ||
1229 | return in; | ||
1230 | } | ||
1231 | } | 1473 | } |
1232 | /* #5528 FIXME (feature!): maybe also try getnameinfo()? */ | 1474 | |
1233 | GNUNET_free (cp); | 1475 | return in; |
1234 | return NULL; | ||
1235 | } | 1476 | } |
1236 | 1477 | ||
1237 | 1478 | ||
@@ -1667,6 +1908,16 @@ decrypt_and_check_tc (struct Queue *queue, | |||
1667 | static void | 1908 | static void |
1668 | free_proto_queue (struct ProtoQueue *pq) | 1909 | free_proto_queue (struct ProtoQueue *pq) |
1669 | { | 1910 | { |
1911 | if (NULL != pq->listen_task) | ||
1912 | { | ||
1913 | GNUNET_SCHEDULER_cancel (pq->listen_task); | ||
1914 | pq->listen_task = NULL; | ||
1915 | } | ||
1916 | if (NULL != pq->listen_sock) | ||
1917 | { | ||
1918 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pq->listen_sock)); | ||
1919 | pq->listen_sock = NULL; | ||
1920 | } | ||
1670 | GNUNET_NETWORK_socket_close (pq->sock); | 1921 | GNUNET_NETWORK_socket_close (pq->sock); |
1671 | GNUNET_free (pq->address); | 1922 | GNUNET_free (pq->address); |
1672 | GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq); | 1923 | GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq); |
@@ -1739,6 +1990,8 @@ proto_read_kx (void *cls) | |||
1739 | queue->address = pq->address; /* steals reference */ | 1990 | queue->address = pq->address; /* steals reference */ |
1740 | queue->address_len = pq->address_len; | 1991 | queue->address_len = pq->address_len; |
1741 | queue->target = tc.sender; | 1992 | queue->target = tc.sender; |
1993 | queue->listen_task = pq->listen_task; | ||
1994 | queue->listen_sock = pq->listen_sock; | ||
1742 | queue->sock = pq->sock; | 1995 | queue->sock = pq->sock; |
1743 | start_initial_kx_out (queue); | 1996 | start_initial_kx_out (queue); |
1744 | boot_queue (queue, GNUNET_TRANSPORT_CS_INBOUND); | 1997 | boot_queue (queue, GNUNET_TRANSPORT_CS_INBOUND); |
@@ -1762,7 +2015,7 @@ proto_read_kx (void *cls) | |||
1762 | * read. Do the read and reschedule this function to be called again | 2015 | * read. Do the read and reschedule this function to be called again |
1763 | * once more is available. | 2016 | * once more is available. |
1764 | * | 2017 | * |
1765 | * @param cls NULL | 2018 | * @param cls ListenTask with listening socket and task |
1766 | */ | 2019 | */ |
1767 | static void | 2020 | static void |
1768 | listen_cb (void *cls) | 2021 | listen_cb (void *cls) |
@@ -1771,20 +2024,23 @@ listen_cb (void *cls) | |||
1771 | socklen_t addrlen; | 2024 | socklen_t addrlen; |
1772 | struct GNUNET_NETWORK_Handle *sock; | 2025 | struct GNUNET_NETWORK_Handle *sock; |
1773 | struct ProtoQueue *pq; | 2026 | struct ProtoQueue *pq; |
2027 | struct ListenTask *lt; | ||
1774 | 2028 | ||
1775 | listen_task = NULL; | 2029 | lt = cls; |
1776 | GNUNET_assert (NULL != listen_sock); | 2030 | |
2031 | lt->listen_task = NULL; | ||
2032 | GNUNET_assert (NULL != lt->listen_sock); | ||
1777 | addrlen = sizeof(in); | 2033 | addrlen = sizeof(in); |
1778 | memset (&in, 0, sizeof(in)); | 2034 | memset (&in, 0, sizeof(in)); |
1779 | sock = GNUNET_NETWORK_socket_accept (listen_sock, | 2035 | sock = GNUNET_NETWORK_socket_accept (lt->listen_sock, |
1780 | (struct sockaddr*) &in, | 2036 | (struct sockaddr*) &in, |
1781 | &addrlen); | 2037 | &addrlen); |
1782 | if ((NULL == sock) && ((EMFILE == errno) || (ENFILE == errno))) | 2038 | if ((NULL == sock) && ((EMFILE == errno) || (ENFILE == errno))) |
1783 | return; /* system limit reached, wait until connection goes down */ | 2039 | return; /* system limit reached, wait until connection goes down */ |
1784 | listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | 2040 | lt->listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, |
1785 | listen_sock, | 2041 | lt->listen_sock, |
1786 | &listen_cb, | 2042 | &listen_cb, |
1787 | NULL); | 2043 | lt); |
1788 | if ((NULL == sock) && ((EAGAIN == errno) || (ENOBUFS == errno))) | 2044 | if ((NULL == sock) && ((EAGAIN == errno) || (ENOBUFS == errno))) |
1789 | return; | 2045 | return; |
1790 | if (NULL == sock) | 2046 | if (NULL == sock) |
@@ -1884,7 +2140,6 @@ queue_read_kx (void *cls) | |||
1884 | queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue); | 2140 | queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue); |
1885 | } | 2141 | } |
1886 | 2142 | ||
1887 | |||
1888 | /** | 2143 | /** |
1889 | * Function called by the transport service to initialize a | 2144 | * Function called by the transport service to initialize a |
1890 | * message queue given address information about another peer. | 2145 | * message queue given address information about another peer. |
@@ -1924,6 +2179,13 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address) | |||
1924 | path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")]; | 2179 | path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")]; |
1925 | in = tcp_address_to_sockaddr (path, &in_len); | 2180 | in = tcp_address_to_sockaddr (path, &in_len); |
1926 | 2181 | ||
2182 | if (NULL == in) | ||
2183 | { | ||
2184 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2185 | "Failed to setup TCP socket address\n"); | ||
2186 | return GNUNET_SYSERR; | ||
2187 | } | ||
2188 | |||
1927 | sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP); | 2189 | sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP); |
1928 | if (NULL == sock) | 2190 | if (NULL == sock) |
1929 | { | 2191 | { |
@@ -1967,7 +2229,6 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address) | |||
1967 | return GNUNET_OK; | 2229 | return GNUNET_OK; |
1968 | } | 2230 | } |
1969 | 2231 | ||
1970 | |||
1971 | /** | 2232 | /** |
1972 | * Iterator over all message queues to clean up. | 2233 | * Iterator over all message queues to clean up. |
1973 | * | 2234 | * |
@@ -2005,16 +2266,6 @@ do_shutdown (void *cls) | |||
2005 | GNUNET_NAT_unregister (nat); | 2266 | GNUNET_NAT_unregister (nat); |
2006 | nat = NULL; | 2267 | nat = NULL; |
2007 | } | 2268 | } |
2008 | if (NULL != listen_task) | ||
2009 | { | ||
2010 | GNUNET_SCHEDULER_cancel (listen_task); | ||
2011 | listen_task = NULL; | ||
2012 | } | ||
2013 | if (NULL != listen_sock) | ||
2014 | { | ||
2015 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (listen_sock)); | ||
2016 | listen_sock = NULL; | ||
2017 | } | ||
2018 | GNUNET_CONTAINER_multipeermap_iterate (queue_map, &get_queue_delete_it, NULL); | 2269 | GNUNET_CONTAINER_multipeermap_iterate (queue_map, &get_queue_delete_it, NULL); |
2019 | GNUNET_CONTAINER_multipeermap_destroy (queue_map); | 2270 | GNUNET_CONTAINER_multipeermap_destroy (queue_map); |
2020 | if (NULL != ch) | 2271 | if (NULL != ch) |
@@ -2087,6 +2338,10 @@ nat_address_cb (void *cls, | |||
2087 | char *my_addr; | 2338 | char *my_addr; |
2088 | struct GNUNET_TRANSPORT_AddressIdentifier *ai; | 2339 | struct GNUNET_TRANSPORT_AddressIdentifier *ai; |
2089 | 2340 | ||
2341 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2342 | "1 nat_address %s\n", | ||
2343 | GNUNET_a2s (addr, addrlen)); | ||
2344 | |||
2090 | if (GNUNET_YES == add_remove) | 2345 | if (GNUNET_YES == add_remove) |
2091 | { | 2346 | { |
2092 | enum GNUNET_NetworkType nt; | 2347 | enum GNUNET_NetworkType nt; |
@@ -2112,80 +2367,53 @@ nat_address_cb (void *cls, | |||
2112 | } | 2367 | } |
2113 | } | 2368 | } |
2114 | 2369 | ||
2115 | |||
2116 | /** | 2370 | /** |
2117 | * Setup communicator and launch network interactions. | 2371 | * This method launch network interactions for each address we like to bind to. |
2118 | * | 2372 | * |
2119 | * @param cls NULL (always) | 2373 | * @param addr The address we will listen to. |
2120 | * @param args remaining command-line arguments | 2374 | * @param in_len The length of the address we will listen to. |
2121 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | 2375 | * @return GNUNET_SYSERR in case of error. GNUNET_OK in case we are successfully listen to the address. |
2122 | * @param c configuration | ||
2123 | */ | 2376 | */ |
2124 | static void | 2377 | static int |
2125 | run (void *cls, | 2378 | init_socket (const struct sockaddr *addr, |
2126 | char *const *args, | 2379 | socklen_t in_len) |
2127 | const char *cfgfile, | ||
2128 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
2129 | { | 2380 | { |
2130 | char *bindto; | ||
2131 | struct sockaddr *in; | ||
2132 | socklen_t in_len; | ||
2133 | struct sockaddr_storage in_sto; | 2381 | struct sockaddr_storage in_sto; |
2134 | socklen_t sto_len; | 2382 | socklen_t sto_len; |
2383 | struct GNUNET_NETWORK_Handle *listen_sock; | ||
2384 | struct ListenTask *lt; | ||
2135 | 2385 | ||
2136 | (void) cls; | 2386 | if (NULL == addr) |
2137 | cfg = c; | ||
2138 | if (GNUNET_OK != | ||
2139 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
2140 | COMMUNICATOR_CONFIG_SECTION, | ||
2141 | "BINDTO", | ||
2142 | &bindto)) | ||
2143 | { | ||
2144 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
2145 | COMMUNICATOR_CONFIG_SECTION, | ||
2146 | "BINDTO"); | ||
2147 | return; | ||
2148 | } | ||
2149 | if (GNUNET_OK != | ||
2150 | GNUNET_CONFIGURATION_get_value_number (cfg, | ||
2151 | COMMUNICATOR_CONFIG_SECTION, | ||
2152 | "MAX_QUEUE_LENGTH", | ||
2153 | &max_queue_length)) | ||
2154 | max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; | ||
2155 | if (GNUNET_OK != | ||
2156 | GNUNET_CONFIGURATION_get_value_time (cfg, | ||
2157 | COMMUNICATOR_CONFIG_SECTION, | ||
2158 | "REKEY_INTERVAL", | ||
2159 | &rekey_interval)) | ||
2160 | rekey_interval = DEFAULT_REKEY_INTERVAL; | ||
2161 | |||
2162 | in = tcp_address_to_sockaddr (bindto, &in_len); | ||
2163 | if (NULL == in) | ||
2164 | { | 2387 | { |
2165 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2388 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
2166 | "Failed to setup TCP socket address with path `%s'\n", | 2389 | "Address is NULL.\n"); |
2167 | bindto); | 2390 | return GNUNET_SYSERR; |
2168 | GNUNET_free (bindto); | ||
2169 | return; | ||
2170 | } | 2391 | } |
2392 | |||
2393 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2394 | "4 address %s\n", | ||
2395 | GNUNET_a2s (addr, in_len)); | ||
2396 | |||
2397 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2398 | "address %s\n", | ||
2399 | GNUNET_a2s (addr, in_len)); | ||
2400 | |||
2171 | listen_sock = | 2401 | listen_sock = |
2172 | GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP); | 2402 | GNUNET_NETWORK_socket_create (addr->sa_family, SOCK_STREAM, IPPROTO_TCP); |
2173 | if (NULL == listen_sock) | 2403 | if (NULL == listen_sock) |
2174 | { | 2404 | { |
2175 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); | 2405 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); |
2176 | GNUNET_free (in); | 2406 | return GNUNET_SYSERR; |
2177 | GNUNET_free (bindto); | ||
2178 | return; | ||
2179 | } | 2407 | } |
2180 | if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, in, in_len)) | 2408 | |
2409 | if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, addr, in_len)) | ||
2181 | { | 2410 | { |
2182 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "bind", bindto); | 2411 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); |
2183 | GNUNET_NETWORK_socket_close (listen_sock); | 2412 | GNUNET_NETWORK_socket_close (listen_sock); |
2184 | listen_sock = NULL; | 2413 | listen_sock = NULL; |
2185 | GNUNET_free (in); | 2414 | return GNUNET_SYSERR; |
2186 | GNUNET_free (bindto); | ||
2187 | return; | ||
2188 | } | 2415 | } |
2416 | |||
2189 | if (GNUNET_OK != | 2417 | if (GNUNET_OK != |
2190 | GNUNET_NETWORK_socket_listen (listen_sock, | 2418 | GNUNET_NETWORK_socket_listen (listen_sock, |
2191 | 5)) | 2419 | 5)) |
@@ -2194,69 +2422,311 @@ run (void *cls, | |||
2194 | "listen"); | 2422 | "listen"); |
2195 | GNUNET_NETWORK_socket_close (listen_sock); | 2423 | GNUNET_NETWORK_socket_close (listen_sock); |
2196 | listen_sock = NULL; | 2424 | listen_sock = NULL; |
2197 | GNUNET_free (in); | 2425 | return GNUNET_SYSERR; |
2198 | GNUNET_free (bindto); | ||
2199 | } | 2426 | } |
2427 | |||
2200 | /* We might have bound to port 0, allowing the OS to figure it out; | 2428 | /* We might have bound to port 0, allowing the OS to figure it out; |
2201 | thus, get the real IN-address from the socket */ | 2429 | thus, get the real IN-address from the socket */ |
2202 | sto_len = sizeof(in_sto); | 2430 | sto_len = sizeof(in_sto); |
2431 | |||
2203 | if (0 != getsockname (GNUNET_NETWORK_get_fd (listen_sock), | 2432 | if (0 != getsockname (GNUNET_NETWORK_get_fd (listen_sock), |
2204 | (struct sockaddr *) &in_sto, | 2433 | (struct sockaddr *) &in_sto, |
2205 | &sto_len)) | 2434 | &sto_len)) |
2206 | { | 2435 | { |
2207 | memcpy (&in_sto, in, in_len); | 2436 | memcpy (&in_sto, addr, in_len); |
2208 | sto_len = in_len; | 2437 | sto_len = in_len; |
2209 | } | 2438 | } |
2210 | GNUNET_free (in); | 2439 | |
2211 | GNUNET_free (bindto); | 2440 | addr = (struct sockaddr *) &in_sto; |
2212 | in = (struct sockaddr *) &in_sto; | ||
2213 | in_len = sto_len; | 2441 | in_len = sto_len; |
2214 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2442 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2215 | "Bound to `%s'\n", | 2443 | "Bound to `%s'\n", |
2216 | GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len)); | 2444 | GNUNET_a2s ((const struct sockaddr *) &in_sto, sto_len)); |
2217 | stats = GNUNET_STATISTICS_create ("C-TCP", cfg); | 2445 | stats = GNUNET_STATISTICS_create ("C-TCP", cfg); |
2218 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | 2446 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); |
2219 | is = GNUNET_NT_scanner_init (); | 2447 | |
2220 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); | 2448 | if (NULL == is) |
2449 | is = GNUNET_NT_scanner_init (); | ||
2450 | |||
2451 | if (NULL == my_private_key) | ||
2452 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); | ||
2221 | if (NULL == my_private_key) | 2453 | if (NULL == my_private_key) |
2222 | { | 2454 | { |
2223 | GNUNET_log ( | 2455 | GNUNET_log ( |
2224 | GNUNET_ERROR_TYPE_ERROR, | 2456 | GNUNET_ERROR_TYPE_ERROR, |
2225 | _ ( | 2457 | _ ( |
2226 | "Transport service is lacking key configuration settings. Exiting.\n")); | 2458 | "Transport service is lacking key configuration settings. Exiting.\n")); |
2459 | GNUNET_RESOLVER_request_cancel (resolve_request_handle); | ||
2227 | GNUNET_SCHEDULER_shutdown (); | 2460 | GNUNET_SCHEDULER_shutdown (); |
2228 | return; | 2461 | return GNUNET_SYSERR; |
2229 | } | 2462 | } |
2230 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key); | 2463 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key); |
2231 | /* start listening */ | 2464 | /* start listening */ |
2232 | listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, | 2465 | |
2233 | listen_sock, | 2466 | lt = GNUNET_new (struct ListenTask); |
2234 | &listen_cb, | 2467 | lt->listen_sock = listen_sock; |
2235 | NULL); | 2468 | |
2236 | queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | 2469 | lt->listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, |
2237 | ch = GNUNET_TRANSPORT_communicator_connect (cfg, | 2470 | listen_sock, |
2238 | COMMUNICATOR_CONFIG_SECTION, | 2471 | &listen_cb, |
2239 | COMMUNICATOR_ADDRESS_PREFIX, | 2472 | lt); |
2240 | GNUNET_TRANSPORT_CC_RELIABLE, | 2473 | |
2241 | &mq_init, | 2474 | if (NULL == queue_map) |
2242 | NULL, | 2475 | queue_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); |
2243 | &enc_notify_cb, | 2476 | |
2244 | NULL); | 2477 | if (NULL == ch ) |
2478 | ch = GNUNET_TRANSPORT_communicator_connect (cfg, | ||
2479 | COMMUNICATOR_CONFIG_SECTION, | ||
2480 | COMMUNICATOR_ADDRESS_PREFIX, | ||
2481 | GNUNET_TRANSPORT_CC_RELIABLE, | ||
2482 | &mq_init, | ||
2483 | NULL, | ||
2484 | &enc_notify_cb, | ||
2485 | NULL); | ||
2486 | |||
2245 | if (NULL == ch) | 2487 | if (NULL == ch) |
2246 | { | 2488 | { |
2247 | GNUNET_break (0); | 2489 | GNUNET_break (0); |
2490 | GNUNET_RESOLVER_request_cancel (resolve_request_handle); | ||
2248 | GNUNET_SCHEDULER_shutdown (); | 2491 | GNUNET_SCHEDULER_shutdown (); |
2249 | return; | 2492 | return GNUNET_SYSERR; |
2493 | } | ||
2494 | |||
2495 | return GNUNET_OK; | ||
2496 | |||
2497 | } | ||
2498 | |||
2499 | /** | ||
2500 | * This method reads from the DLL addrs_head to register them at the NAT service. | ||
2501 | */ | ||
2502 | static void | ||
2503 | nat_register () | ||
2504 | { | ||
2505 | |||
2506 | struct sockaddr **saddrs; | ||
2507 | socklen_t *saddr_lens; | ||
2508 | int i; | ||
2509 | struct Addresses *pos; | ||
2510 | |||
2511 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2512 | "nat here\n"); | ||
2513 | |||
2514 | i = 0; | ||
2515 | saddrs = GNUNET_malloc ((addrs_lens + 1) * sizeof(struct sockaddr *)); | ||
2516 | |||
2517 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2518 | "2 nat here\n"); | ||
2519 | |||
2520 | saddr_lens = GNUNET_malloc ((addrs_lens + 1) * sizeof(socklen_t)); | ||
2521 | |||
2522 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2523 | "3 nat here\n"); | ||
2524 | |||
2525 | for (pos = addrs_head; NULL != pos; pos = pos->next) | ||
2526 | { | ||
2527 | |||
2528 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2529 | "5 nat here\n"); | ||
2530 | |||
2531 | saddr_lens[i] = addrs_head->addr_len; | ||
2532 | saddrs[i] = GNUNET_malloc (saddr_lens[i]); | ||
2533 | saddrs[i] = addrs_head->addr; | ||
2534 | |||
2535 | i++; | ||
2536 | |||
2537 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2538 | "6 nat here\n"); | ||
2539 | |||
2250 | } | 2540 | } |
2541 | |||
2251 | nat = GNUNET_NAT_register (cfg, | 2542 | nat = GNUNET_NAT_register (cfg, |
2252 | COMMUNICATOR_CONFIG_SECTION, | 2543 | COMMUNICATOR_CONFIG_SECTION, |
2253 | IPPROTO_TCP, | 2544 | IPPROTO_TCP, |
2254 | 1 /* one address */, | 2545 | addrs_lens, |
2255 | (const struct sockaddr **) &in, | 2546 | (const struct sockaddr **) saddrs, |
2256 | &in_len, | 2547 | saddr_lens, |
2257 | &nat_address_cb, | 2548 | &nat_address_cb, |
2258 | NULL /* FIXME: support reversal: #5529 */, | 2549 | NULL /* FIXME: support reversal: #5529 */, |
2259 | NULL /* closure */); | 2550 | NULL /* closure */); |
2551 | |||
2552 | if (NULL == nat) | ||
2553 | { | ||
2554 | GNUNET_break (0); | ||
2555 | GNUNET_RESOLVER_request_cancel (resolve_request_handle); | ||
2556 | GNUNET_SCHEDULER_shutdown (); | ||
2557 | } | ||
2558 | } | ||
2559 | |||
2560 | /** | ||
2561 | * This method adds addresses to the DLL, that are later register at the NAT service. | ||
2562 | */ | ||
2563 | static void | ||
2564 | add_addr (struct sockaddr *in, socklen_t in_len) | ||
2565 | { | ||
2566 | |||
2567 | struct Addresses *saddrs; | ||
2568 | |||
2569 | saddrs = GNUNET_new (struct Addresses); | ||
2570 | saddrs->addr = in; | ||
2571 | saddrs->addr_len = in_len; | ||
2572 | GNUNET_CONTAINER_DLL_insert (addrs_head, addrs_tail, saddrs); | ||
2573 | addrs_lens++; | ||
2574 | } | ||
2575 | |||
2576 | /** | ||
2577 | * This method is the callback called by the resolver API, and wraps method init_socket. | ||
2578 | * | ||
2579 | * @param cls The port we will bind to. | ||
2580 | * @param addr The address we will bind to. | ||
2581 | * @param in_len The length of the address we will bind to. | ||
2582 | */ | ||
2583 | static void | ||
2584 | init_socket_resolv (void *cls, | ||
2585 | const struct sockaddr *addr, | ||
2586 | socklen_t in_len) | ||
2587 | { | ||
2588 | struct sockaddr_in *v4; | ||
2589 | struct sockaddr_in6 *v6; | ||
2590 | struct sockaddr *in; | ||
2591 | unsigned int *port; | ||
2592 | |||
2593 | port = cls; | ||
2594 | if (NULL != addr) | ||
2595 | { | ||
2596 | if (AF_INET == addr->sa_family) | ||
2597 | { | ||
2598 | v4 = (struct sockaddr_in *) addr; | ||
2599 | in = tcp_address_to_sockaddr_numeric_v4 (&in_len, *v4, *port);// _global); | ||
2600 | add_addr (in, in_len); | ||
2601 | } | ||
2602 | else if (AF_INET6 == addr->sa_family) | ||
2603 | { | ||
2604 | v6 = (struct sockaddr_in6 *) addr; | ||
2605 | in = tcp_address_to_sockaddr_numeric_v6 (&in_len, *v6, *port);// _global); | ||
2606 | add_addr (in, in_len); | ||
2607 | } | ||
2608 | else | ||
2609 | { | ||
2610 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2611 | "Address family %u not suitable (not AF_INET %u nor AF_INET6 %u \n", | ||
2612 | addr->sa_family, | ||
2613 | AF_INET, | ||
2614 | AF_INET6); | ||
2615 | return; | ||
2616 | } | ||
2617 | init_socket (in, | ||
2618 | in_len); | ||
2619 | } | ||
2620 | else | ||
2621 | { | ||
2622 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2623 | "Address is NULL. This might be an error or the resolver finished resolving.\n"); | ||
2624 | nat_register (); | ||
2625 | } | ||
2626 | } | ||
2627 | |||
2628 | /** | ||
2629 | * Setup communicator and launch network interactions. | ||
2630 | * | ||
2631 | * @param cls NULL (always) | ||
2632 | * @param args remaining command-line arguments | ||
2633 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
2634 | * @param c configuration | ||
2635 | */ | ||
2636 | static void | ||
2637 | run (void *cls, | ||
2638 | char *const *args, | ||
2639 | const char *cfgfile, | ||
2640 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
2641 | { | ||
2642 | char *bindto; | ||
2643 | struct sockaddr *in; | ||
2644 | socklen_t in_len; | ||
2645 | struct sockaddr_in v4; | ||
2646 | struct sockaddr_in6 v6; | ||
2647 | char *start; | ||
2648 | unsigned int port; | ||
2649 | char dummy[2]; | ||
2650 | char *rest = NULL; | ||
2651 | struct PortOnlyIpv4Ipv6 *po; | ||
2652 | |||
2653 | (void) cls; | ||
2654 | cfg = c; | ||
2655 | if (GNUNET_OK != | ||
2656 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
2657 | COMMUNICATOR_CONFIG_SECTION, | ||
2658 | "BINDTO", | ||
2659 | &bindto)) | ||
2660 | { | ||
2661 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
2662 | COMMUNICATOR_CONFIG_SECTION, | ||
2663 | "BINDTO"); | ||
2664 | return; | ||
2665 | } | ||
2666 | if (GNUNET_OK != | ||
2667 | GNUNET_CONFIGURATION_get_value_number (cfg, | ||
2668 | COMMUNICATOR_CONFIG_SECTION, | ||
2669 | "MAX_QUEUE_LENGTH", | ||
2670 | &max_queue_length)) | ||
2671 | max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; | ||
2672 | if (GNUNET_OK != | ||
2673 | GNUNET_CONFIGURATION_get_value_time (cfg, | ||
2674 | COMMUNICATOR_CONFIG_SECTION, | ||
2675 | "REKEY_INTERVAL", | ||
2676 | &rekey_interval)) | ||
2677 | rekey_interval = DEFAULT_REKEY_INTERVAL; | ||
2678 | |||
2679 | |||
2680 | // cp = GNUNET_strdup (bindto); | ||
2681 | start = extract_address (bindto); | ||
2682 | |||
2683 | if (1 == sscanf (bindto, "%u%1s", &port, dummy)) | ||
2684 | { | ||
2685 | po = tcp_address_to_sockaddr_port_only (bindto, &port); | ||
2686 | |||
2687 | if (NULL != &po->addr_ipv4) | ||
2688 | { | ||
2689 | init_socket (po->addr_ipv4, *po->addr_len_ipv4); | ||
2690 | add_addr (po->addr_ipv4, *po->addr_len_ipv4); | ||
2691 | } | ||
2692 | |||
2693 | if (NULL != &po->addr_ipv6) | ||
2694 | { | ||
2695 | init_socket (po->addr_ipv6, *po->addr_len_ipv6); | ||
2696 | add_addr (po->addr_ipv6, *po->addr_len_ipv6); | ||
2697 | } | ||
2698 | |||
2699 | nat_register (); | ||
2700 | } | ||
2701 | else if (1 == inet_pton (AF_INET, start, &v4.sin_addr)) | ||
2702 | { | ||
2703 | port = extract_port (bindto); | ||
2704 | |||
2705 | in = tcp_address_to_sockaddr_numeric_v4 (&in_len, v4, port); | ||
2706 | init_socket (in, in_len); | ||
2707 | add_addr (in, in_len); | ||
2708 | nat_register (); | ||
2709 | } | ||
2710 | else if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr)) | ||
2711 | { | ||
2712 | port = extract_port (bindto); | ||
2713 | in = tcp_address_to_sockaddr_numeric_v6 (&in_len, v6, port); | ||
2714 | init_socket (in, in_len); | ||
2715 | add_addr (in, in_len); | ||
2716 | nat_register (); | ||
2717 | } | ||
2718 | else | ||
2719 | { | ||
2720 | port = extract_port (bindto); | ||
2721 | |||
2722 | resolve_request_handle = GNUNET_RESOLVER_ip_get (strtok_r (bindto, ":", | ||
2723 | &rest), | ||
2724 | AF_UNSPEC, | ||
2725 | GNUNET_TIME_UNIT_MINUTES, | ||
2726 | &init_socket_resolv, | ||
2727 | &port); | ||
2728 | } | ||
2729 | GNUNET_free (bindto); | ||
2260 | } | 2730 | } |
2261 | 2731 | ||
2262 | 2732 | ||