aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_tcp.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-05-02 11:48:52 +0000
committerChristian Grothoff <christian@grothoff.org>2010-05-02 11:48:52 +0000
commitf4b1f639e8799d29e823a7cd563a97d314d4f471 (patch)
treebe4854b5c5591ea04b2de4032e554dc392f8d0e0 /src/transport/plugin_transport_tcp.c
parentf1df9f057d50cd695ee3b86538f27306ea74369f (diff)
downloadgnunet-f4b1f639e8799d29e823a7cd563a97d314d4f471.tar.gz
gnunet-f4b1f639e8799d29e823a7cd563a97d314d4f471.zip
fixing major issue with how IP addresses go over the network (previously ill-defined) -- thanks amatus
Diffstat (limited to 'src/transport/plugin_transport_tcp.c')
-rw-r--r--src/transport/plugin_transport_tcp.c293
1 files changed, 234 insertions, 59 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index e71e751f6..2e7d3dadd 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -64,6 +64,42 @@ struct WelcomeMessage
64 64
65 65
66/** 66/**
67 * Network format for IPv4 addresses.
68 */
69struct IPv4TcpAddress
70{
71 /**
72 * IPv4 address, in network byte order.
73 */
74 uint32_t ipv4_addr;
75
76 /**
77 * Port number, in network byte order.
78 */
79 uint16_t t_port;
80
81};
82
83
84/**
85 * Network format for IPv6 addresses.
86 */
87struct IPv6TcpAddress
88{
89 /**
90 * IPv6 address.
91 */
92 unsigned char ipv6_addr[16];
93
94 /**
95 * Port number, in network byte order.
96 */
97 uint16_t t6_port;
98
99};
100
101
102/**
67 * Encapsulation of all of the state of the plugin. 103 * Encapsulation of all of the state of the plugin.
68 */ 104 */
69struct Plugin; 105struct Plugin;
@@ -262,6 +298,60 @@ struct Plugin
262}; 298};
263 299
264 300
301
302
303/**
304 * Function called for a quick conversion of the binary address to
305 * a numeric address. Note that the caller must not free the
306 * address and that the next call to this function is allowed
307 * to override the address again.
308 *
309 * @param cls closure ('struct Plugin*')
310 * @param addr binary address
311 * @param addr_len length of the address
312 * @return string representing the same address
313 */
314static const char*
315tcp_address_to_string (void *cls,
316 const void *addr,
317 size_t addrlen)
318{
319 static char buf[INET6_ADDRSTRLEN];
320 const void *sb;
321 struct sockaddr_in a4;
322 struct sockaddr_in6 a6;
323 const struct IPv4TcpAddress *t4;
324 const struct IPv6TcpAddress *t6;
325 int af;
326
327 if (addrlen == sizeof (struct IPv6TcpAddress))
328 {
329 t6 = addr;
330 af = AF_INET6;
331 memset (&a6, 0, sizeof (a6));
332 a6.sin6_family = AF_INET6;
333 a6.sin6_port = t6->t6_port;
334 memcpy (a6.sin6_addr.s6_addr,
335 t6->ipv6_addr,
336 16);
337 sb = &a6;
338 }
339 else if (addrlen == sizeof (struct IPv4TcpAddress))
340 {
341 t4 = addr;
342 af = AF_INET;
343 memset (&a4, 0, sizeof (a4));
344 a4.sin_family = AF_INET;
345 a4.sin_port = t4->t_port;
346 a4.sin_addr.s_addr = t4->ipv4_addr;
347 sb = &a4;
348 }
349 else
350 return NULL;
351 return inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
352}
353
354
265/** 355/**
266 * Find the session handle for the given client. 356 * Find the session handle for the given client.
267 * 357 *
@@ -520,8 +610,10 @@ disconnect_session (struct Session *session)
520 "Disconnecting from `%4s' at %s (session %p).\n", 610 "Disconnecting from `%4s' at %s (session %p).\n",
521 GNUNET_i2s (&session->target), 611 GNUNET_i2s (&session->target),
522 (session->connect_addr != NULL) ? 612 (session->connect_addr != NULL) ?
523 GNUNET_a2s (session->connect_addr, 613 tcp_address_to_string (session->plugin,
524 session->connect_alen) : "*", session); 614 session->connect_addr,
615 session->connect_alen) : "*",
616 session);
525#endif 617#endif
526 /* remove from session list */ 618 /* remove from session list */
527 prev = NULL; 619 prev = NULL;
@@ -680,6 +772,12 @@ tcp_plugin_send (void *cls,
680 struct PendingMessage *pm; 772 struct PendingMessage *pm;
681 struct GNUNET_CONNECTION_Handle *sa; 773 struct GNUNET_CONNECTION_Handle *sa;
682 int af; 774 int af;
775 const void *sb;
776 size_t sbs;
777 struct sockaddr_in a4;
778 struct sockaddr_in6 a6;
779 const struct IPv4TcpAddress *t4;
780 const struct IPv6TcpAddress *t6;
683 781
684 GNUNET_STATISTICS_update (plugin->env->stats, 782 GNUNET_STATISTICS_update (plugin->env->stats,
685 gettext_noop ("# bytes TCP was asked to transmit"), 783 gettext_noop ("# bytes TCP was asked to transmit"),
@@ -746,13 +844,29 @@ tcp_plugin_send (void *cls,
746 } 844 }
747 if (session == NULL) 845 if (session == NULL)
748 { 846 {
749 if (sizeof (struct sockaddr_in) == addrlen) 847 if (addrlen == sizeof (struct IPv6TcpAddress))
750 { 848 {
751 af = AF_INET; 849 t6 = addr;
850 af = AF_INET6;
851 memset (&a6, 0, sizeof (a6));
852 a6.sin6_family = AF_INET6;
853 a6.sin6_port = t6->t6_port;
854 memcpy (a6.sin6_addr.s6_addr,
855 t6->ipv6_addr,
856 16);
857 sb = &a6;
858 sbs = sizeof (a6);
752 } 859 }
753 else if (sizeof (struct sockaddr_in6) == addrlen) 860 else if (addrlen == sizeof (struct IPv4TcpAddress))
754 { 861 {
755 af = AF_INET6; 862 t4 = addr;
863 af = AF_INET;
864 memset (&a4, 0, sizeof (a4));
865 a4.sin_family = AF_INET;
866 a4.sin_port = t4->t_port;
867 a4.sin_addr.s_addr = t4->ipv4_addr;
868 sb = &a4;
869 sbs = sizeof (a4);
756 } 870 }
757 else 871 else
758 { 872 {
@@ -760,7 +874,7 @@ tcp_plugin_send (void *cls,
760 return -1; 874 return -1;
761 } 875 }
762 sa = GNUNET_CONNECTION_create_from_sockaddr (plugin->env->sched, 876 sa = GNUNET_CONNECTION_create_from_sockaddr (plugin->env->sched,
763 af, addr, addrlen, 877 af, sb, sbs,
764 GNUNET_SERVER_MAX_MESSAGE_SIZE); 878 GNUNET_SERVER_MAX_MESSAGE_SIZE);
765 if (sa == NULL) 879 if (sa == NULL)
766 { 880 {
@@ -769,7 +883,7 @@ tcp_plugin_send (void *cls,
769 "tcp", 883 "tcp",
770 "Failed to create connection to `%4s' at `%s'\n", 884 "Failed to create connection to `%4s' at `%s'\n",
771 GNUNET_i2s (target), 885 GNUNET_i2s (target),
772 GNUNET_a2s (addr, addrlen)); 886 GNUNET_a2s (sb, sbs));
773#endif 887#endif
774 GNUNET_STATISTICS_update (plugin->env->stats, 888 GNUNET_STATISTICS_update (plugin->env->stats,
775 gettext_noop ("# bytes discarded by TCP (failed to connect)"), 889 gettext_noop ("# bytes discarded by TCP (failed to connect)"),
@@ -782,7 +896,7 @@ tcp_plugin_send (void *cls,
782 "tcp", 896 "tcp",
783 "Asked to transmit to `%4s', creating fresh session using address `%s'.\n", 897 "Asked to transmit to `%4s', creating fresh session using address `%s'.\n",
784 GNUNET_i2s (target), 898 GNUNET_i2s (target),
785 GNUNET_a2s (addr, addrlen)); 899 GNUNET_a2s (sb, sbs));
786#endif 900#endif
787 session = create_session (plugin, 901 session = create_session (plugin,
788 target, 902 target,
@@ -948,12 +1062,43 @@ tcp_plugin_address_pretty_printer (void *cls,
948 void *asc_cls) 1062 void *asc_cls)
949{ 1063{
950 struct Plugin *plugin = cls; 1064 struct Plugin *plugin = cls;
951 const struct sockaddr_in *v4;
952 const struct sockaddr_in6 *v6;
953 struct PrettyPrinterContext *ppc; 1065 struct PrettyPrinterContext *ppc;
1066 const void *sb;
1067 size_t sbs;
1068 struct sockaddr_in a4;
1069 struct sockaddr_in6 a6;
1070 const struct IPv4TcpAddress *t4;
1071 const struct IPv6TcpAddress *t6;
1072 int af;
1073 uint16_t port;
954 1074
955 if ((addrlen != sizeof (struct sockaddr_in)) && 1075 if (addrlen == sizeof (struct IPv6TcpAddress))
956 (addrlen != sizeof (struct sockaddr_in6))) 1076 {
1077 t6 = addr;
1078 af = AF_INET6;
1079 memset (&a6, 0, sizeof (a6));
1080 a6.sin6_family = AF_INET6;
1081 a6.sin6_port = t6->t6_port;
1082 memcpy (a6.sin6_addr.s6_addr,
1083 t6->ipv6_addr,
1084 16);
1085 port = ntohs (t6->t6_port);
1086 sb = &a6;
1087 sbs = sizeof (a6);
1088 }
1089 else if (addrlen == sizeof (struct IPv4TcpAddress))
1090 {
1091 t4 = addr;
1092 af = AF_INET;
1093 memset (&a4, 0, sizeof (a4));
1094 a4.sin_family = AF_INET;
1095 a4.sin_port = t4->t_port;
1096 a4.sin_addr.s_addr = t4->ipv4_addr;
1097 port = ntohs (t4->t_port);
1098 sb = &a4;
1099 sbs = sizeof (a4);
1100 }
1101 else
957 { 1102 {
958 /* invalid address */ 1103 /* invalid address */
959 GNUNET_break_op (0); 1104 GNUNET_break_op (0);
@@ -963,21 +1108,11 @@ tcp_plugin_address_pretty_printer (void *cls,
963 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext)); 1108 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
964 ppc->asc = asc; 1109 ppc->asc = asc;
965 ppc->asc_cls = asc_cls; 1110 ppc->asc_cls = asc_cls;
966 if (addrlen == sizeof (struct sockaddr_in)) 1111 ppc->port = port;
967 {
968 v4 = (const struct sockaddr_in *) addr;
969 ppc->port = ntohs (v4->sin_port);
970 }
971 else
972 {
973 v6 = (const struct sockaddr_in6 *) addr;
974 ppc->port = ntohs (v6->sin6_port);
975
976 }
977 GNUNET_RESOLVER_hostname_get (plugin->env->sched, 1112 GNUNET_RESOLVER_hostname_get (plugin->env->sched,
978 plugin->env->cfg, 1113 plugin->env->cfg,
979 addr, 1114 sb,
980 addrlen, 1115 sbs,
981 !numeric, timeout, &append_port, ppc); 1116 !numeric, timeout, &append_port, ppc);
982} 1117}
983 1118
@@ -1004,45 +1139,40 @@ check_port (struct Plugin *plugin, uint16_t in_port)
1004 1139
1005/** 1140/**
1006 * Another peer has suggested an address for this peer and transport 1141 * Another peer has suggested an address for this peer and transport
1007 * plugin. Check that this could be a valid address. 1142 * plugin. Check that this could be a valid address. This function
1143 * is not expected to 'validate' the address in the sense of trying to
1144 * connect to it but simply to see if the binary format is technically
1145 * legal for establishing a connection.
1008 * 1146 *
1009 * @param cls closure, our 'struct Plugin*' 1147 * @param cls closure, our 'struct Plugin*'
1010 * @param addr pointer to the address 1148 * @param addr pointer to the address
1011 * @param addrlen length of addr 1149 * @param addrlen length of addr
1012 * @return GNUNET_OK if this is a plausible address for this peer 1150 * @return GNUNET_OK if this is a plausible address for this peer
1013 * and transport 1151 * and transport, GNUNET_SYSERR if not
1014 */ 1152 */
1015static int 1153static int
1016tcp_plugin_check_address (void *cls, void *addr, size_t addrlen) 1154tcp_plugin_check_address (void *cls, void *addr, size_t addrlen)
1017{ 1155{
1018 struct Plugin *plugin = cls; 1156 struct Plugin *plugin = cls;
1019 char buf[sizeof (struct sockaddr_in6)]; 1157 struct IPv4TcpAddress *v4;
1020 struct sockaddr_in *v4; 1158 struct IPv6TcpAddress *v6;
1021 struct sockaddr_in6 *v6;
1022 1159
1023 if ((addrlen != sizeof (struct sockaddr_in)) && 1160 if ((addrlen != sizeof (struct IPv4TcpAddress)) &&
1024 (addrlen != sizeof (struct sockaddr_in6))) 1161 (addrlen != sizeof (struct IPv6TcpAddress)))
1025 { 1162 {
1026 GNUNET_break_op (0); 1163 GNUNET_break_op (0);
1027 return GNUNET_SYSERR; 1164 return GNUNET_SYSERR;
1028 } 1165 }
1029 memcpy (buf, addr, sizeof (struct sockaddr_in6)); 1166 if (addrlen == sizeof (struct IPv4TcpAddress))
1030 if (addrlen == sizeof (struct sockaddr_in))
1031 { 1167 {
1032 v4 = (struct sockaddr_in *) buf; 1168 v4 = (struct IPv4TcpAddress *) addr;
1033 v4->sin_port = htons (check_port (plugin, ntohs (v4->sin_port))); 1169 v4->t_port = htons (check_port (plugin, ntohs (v4->t_port)));
1034 } 1170 }
1035 else 1171 else
1036 { 1172 {
1037 v6 = (struct sockaddr_in6 *) buf; 1173 v6 = (struct IPv6TcpAddress *) addr;
1038 v6->sin6_port = htons (check_port (plugin, ntohs (v6->sin6_port))); 1174 v6->t6_port = htons (check_port (plugin, ntohs (v6->t6_port)));
1039 } 1175 }
1040#if DEBUG_TCP
1041 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1042 "tcp",
1043 "Informing transport service about my address `%s'.\n",
1044 GNUNET_a2s (addr, addrlen));
1045#endif
1046 return GNUNET_OK; 1176 return GNUNET_OK;
1047} 1177}
1048 1178
@@ -1065,6 +1195,11 @@ handle_tcp_welcome (void *cls,
1065 struct Session *session; 1195 struct Session *session;
1066 size_t alen; 1196 size_t alen;
1067 void *vaddr; 1197 void *vaddr;
1198 struct IPv4TcpAddress *t4;
1199 struct IPv6TcpAddress *t6;
1200 const struct sockaddr_in *s4;
1201 const struct sockaddr_in6 *s6;
1202
1068 1203
1069#if DEBUG_TCP 1204#if DEBUG_TCP
1070 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1205 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
@@ -1094,8 +1229,27 @@ handle_tcp_welcome (void *cls,
1094 GNUNET_a2s (vaddr, alen), 1229 GNUNET_a2s (vaddr, alen),
1095 client); 1230 client);
1096#endif 1231#endif
1097 session->connect_addr = vaddr; 1232 if (alen == sizeof (struct sockaddr_in))
1098 session->connect_alen = alen; 1233 {
1234 s4 = vaddr;
1235 t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress));
1236 t4->t_port = s4->sin_port;
1237 t4->ipv4_addr = s4->sin_addr.s_addr;
1238 session->connect_addr = t4;
1239 session->connect_alen = sizeof (struct IPv4TcpAddress);
1240 }
1241 else if (alen == sizeof (struct sockaddr_in6))
1242 {
1243 s6 = vaddr;
1244 t6 = GNUNET_malloc (sizeof (struct IPv6TcpAddress));
1245 t6->t6_port = s6->sin6_port;
1246 memcpy (t6->ipv6_addr,
1247 s6->sin6_addr.s6_addr,
1248 16);
1249 session->connect_addr = t6;
1250 session->connect_alen = sizeof (struct IPv6TcpAddress);
1251 }
1252 GNUNET_free (vaddr);
1099 } 1253 }
1100 else 1254 else
1101 { 1255 {
@@ -1227,7 +1381,8 @@ static struct GNUNET_SERVER_MessageHandler my_handlers[] = {
1227 * @param client identification of the client 1381 * @param client identification of the client
1228 */ 1382 */
1229static void 1383static void
1230disconnect_notify (void *cls, struct GNUNET_SERVER_Client *client) 1384disconnect_notify (void *cls,
1385 struct GNUNET_SERVER_Client *client)
1231{ 1386{
1232 struct Plugin *plugin = cls; 1387 struct Plugin *plugin = cls;
1233 struct Session *session; 1388 struct Session *session;
@@ -1243,8 +1398,10 @@ disconnect_notify (void *cls, struct GNUNET_SERVER_Client *client)
1243 "Destroying session of `%4s' with %s (%p) due to network-level disconnect.\n", 1398 "Destroying session of `%4s' with %s (%p) due to network-level disconnect.\n",
1244 GNUNET_i2s (&session->target), 1399 GNUNET_i2s (&session->target),
1245 (session->connect_addr != NULL) ? 1400 (session->connect_addr != NULL) ?
1246 GNUNET_a2s (session->connect_addr, 1401 tcp_address_to_string (session->plugin,
1247 session->connect_alen) : "*", client); 1402 session->connect_addr,
1403 session->connect_alen) : "*",
1404 client);
1248#endif 1405#endif
1249 disconnect_session (session); 1406 disconnect_session (session);
1250} 1407}
@@ -1259,6 +1416,7 @@ disconnect_notify (void *cls, struct GNUNET_SERVER_Client *client)
1259 * @param isDefault do we think this may be our default interface 1416 * @param isDefault do we think this may be our default interface
1260 * @param addr address of the interface 1417 * @param addr address of the interface
1261 * @param addrlen number of bytes in addr 1418 * @param addrlen number of bytes in addr
1419 * @return GNUNET_OK to continue iterating
1262 */ 1420 */
1263static int 1421static int
1264process_interfaces (void *cls, 1422process_interfaces (void *cls,
@@ -1268,28 +1426,41 @@ process_interfaces (void *cls,
1268{ 1426{
1269 struct Plugin *plugin = cls; 1427 struct Plugin *plugin = cls;
1270 int af; 1428 int af;
1271 struct sockaddr_in *v4; 1429 struct IPv4TcpAddress t4;
1272 struct sockaddr_in6 *v6; 1430 struct IPv6TcpAddress t6;
1431 void *arg;
1432 uint16_t args;
1273 1433
1274 af = addr->sa_family; 1434 af = addr->sa_family;
1275 if (af == AF_INET) 1435 if (af == AF_INET)
1276 { 1436 {
1277 v4 = (struct sockaddr_in *) addr; 1437 t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1278 v4->sin_port = htons (plugin->adv_port); 1438 t4.t_port = htons (plugin->adv_port);
1439 arg = &t4;
1440 args = sizeof (t4);
1441 }
1442 else if (af == AF_INET6)
1443 {
1444 memcpy (t6.ipv6_addr,
1445 ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1446 16);
1447 t6.t6_port = htons (plugin->adv_port);
1448 arg = &t6;
1449 args = sizeof (t6);
1279 } 1450 }
1280 else 1451 else
1281 { 1452 {
1282 GNUNET_assert (af == AF_INET6); 1453 GNUNET_break (0);
1283 v6 = (struct sockaddr_in6 *) addr; 1454 return GNUNET_OK;
1284 v6->sin6_port = htons (plugin->adv_port);
1285 } 1455 }
1286 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO | 1456 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO |
1287 GNUNET_ERROR_TYPE_BULK, 1457 GNUNET_ERROR_TYPE_BULK,
1288 "tcp", _("Found address `%s' (%s)\n"), 1458 "tcp",
1459 _("Found address `%s' (%s)\n"),
1289 GNUNET_a2s (addr, addrlen), name); 1460 GNUNET_a2s (addr, addrlen), name);
1290 plugin->env->notify_address (plugin->env->cls, 1461 plugin->env->notify_address (plugin->env->cls,
1291 "tcp", 1462 "tcp",
1292 addr, addrlen, GNUNET_TIME_UNIT_FOREVER_REL); 1463 arg, args, GNUNET_TIME_UNIT_FOREVER_REL);
1293 return GNUNET_OK; 1464 return GNUNET_OK;
1294} 1465}
1295 1466
@@ -1320,6 +1491,9 @@ process_hostname_ips (void *cls,
1320 1491
1321/** 1492/**
1322 * Entry point for the plugin. 1493 * Entry point for the plugin.
1494 *
1495 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
1496 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
1323 */ 1497 */
1324void * 1498void *
1325libgnunet_plugin_transport_tcp_init (void *cls) 1499libgnunet_plugin_transport_tcp_init (void *cls)
@@ -1377,6 +1551,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
1377 api->disconnect = &tcp_plugin_disconnect; 1551 api->disconnect = &tcp_plugin_disconnect;
1378 api->address_pretty_printer = &tcp_plugin_address_pretty_printer; 1552 api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
1379 api->check_address = &tcp_plugin_check_address; 1553 api->check_address = &tcp_plugin_check_address;
1554 api->address_to_string = &tcp_address_to_string;
1380 plugin->service = service; 1555 plugin->service = service;
1381 plugin->server = GNUNET_SERVICE_get_server (service); 1556 plugin->server = GNUNET_SERVICE_get_server (service);
1382 plugin->handlers = GNUNET_malloc (sizeof (my_handlers)); 1557 plugin->handlers = GNUNET_malloc (sizeof (my_handlers));