aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_udp.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_udp.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_udp.c')
-rw-r--r--src/transport/plugin_transport_udp.c325
1 files changed, 267 insertions, 58 deletions
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index 3e59f89dc..c7be2e18e 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -71,13 +71,64 @@ struct UDPMessage
71}; 71};
72 72
73 73
74/**
75 * Network format for IPv4 addresses.
76 */
77struct IPv4UdpAddress
78{
79 /**
80 * IPv4 address, in network byte order.
81 */
82 uint32_t ipv4_addr;
83
84 /**
85 * Port number, in network byte order.
86 */
87 uint16_t u_port;
88
89};
90
91
92/**
93 * Network format for IPv6 addresses.
94 */
95struct IPv6UdpAddress
96{
97 /**
98 * IPv6 address.
99 */
100 unsigned char ipv6_addr[16];
101
102 /**
103 * Port number, in network byte order.
104 */
105 uint16_t u6_port;
106
107};
108
109
110/**
111 *
112 */
74struct PrettyPrinterContext 113struct PrettyPrinterContext
75{ 114{
115 /**
116 *
117 */
76 GNUNET_TRANSPORT_AddressStringCallback asc; 118 GNUNET_TRANSPORT_AddressStringCallback asc;
119
120 /**
121 * Closure for 'asc'.
122 */
77 void *asc_cls; 123 void *asc_cls;
124
125 /**
126 *
127 */
78 uint16_t port; 128 uint16_t port;
79}; 129};
80 130
131
81/** 132/**
82 * Encapsulation of all of the state of the plugin. 133 * Encapsulation of all of the state of the plugin.
83 */ 134 */
@@ -134,7 +185,7 @@ struct Plugin
134/* *********** globals ************* */ 185/* *********** globals ************* */
135 186
136/** 187/**
137 * the socket that we transmit all data with 188 * The socket that we transmit all data with
138 */ 189 */
139static struct GNUNET_NETWORK_Handle *udp_sock; 190static struct GNUNET_NETWORK_Handle *udp_sock;
140 191
@@ -146,7 +197,8 @@ static struct GNUNET_NETWORK_Handle *udp_sock;
146 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed 197 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
147 */ 198 */
148void 199void
149udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) 200udp_disconnect (void *cls,
201 const struct GNUNET_PeerIdentity *target)
150{ 202{
151 /* nothing to do, UDP is stateless */ 203 /* nothing to do, UDP is stateless */
152} 204}
@@ -154,6 +206,8 @@ udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
154/** 206/**
155 * Shutdown the server process (stop receiving inbound traffic). Maybe 207 * Shutdown the server process (stop receiving inbound traffic). Maybe
156 * restarted later! 208 * restarted later!
209 *
210 * @param cls closure, the 'struct Plugin*'
157 */ 211 */
158static int 212static int
159udp_transport_server_stop (void *cls) 213udp_transport_server_stop (void *cls)
@@ -178,7 +232,7 @@ udp_transport_server_stop (void *cls)
178 * Function that can be used by the transport service to transmit 232 * Function that can be used by the transport service to transmit
179 * a message using the plugin. 233 * a message using the plugin.
180 * 234 *
181 * @param cls closure 235 * @param cls closure, the 'struct Plugin*'
182 * @param target who should receive this message (ignored by UDP) 236 * @param target who should receive this message (ignored by UDP)
183 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together 237 * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
184 * @param msgbuf_size the size of the msgbuf to send 238 * @param msgbuf_size the size of the msgbuf to send
@@ -217,6 +271,13 @@ udp_plugin_send (void *cls,
217 struct UDPMessage *message; 271 struct UDPMessage *message;
218 int ssize; 272 int ssize;
219 ssize_t sent; 273 ssize_t sent;
274 int af;
275 const void *sb;
276 size_t sbs;
277 struct sockaddr_in a4;
278 struct sockaddr_in6 a6;
279 const struct IPv4UdpAddress *t4;
280 const struct IPv6UdpAddress *t6;
220 281
221 GNUNET_assert (NULL == session); 282 GNUNET_assert (NULL == session);
222 GNUNET_assert(udp_sock != NULL); 283 GNUNET_assert(udp_sock != NULL);
@@ -231,13 +292,45 @@ udp_plugin_send (void *cls,
231 if (force_address == GNUNET_SYSERR) 292 if (force_address == GNUNET_SYSERR)
232 return -1; /* never reliable */ 293 return -1; /* never reliable */
233 294
295 if (addrlen == sizeof (struct IPv6UdpAddress))
296 {
297 t6 = addr;
298 af = AF_INET6;
299 memset (&a6, 0, sizeof (a6));
300 a6.sin6_family = AF_INET6;
301 a6.sin6_port = t6->u6_port;
302 memcpy (a6.sin6_addr.s6_addr,
303 t6->ipv6_addr,
304 16);
305 sb = &a6;
306 sbs = sizeof (a6);
307 }
308 else if (addrlen == sizeof (struct IPv4UdpAddress))
309 {
310 t4 = addr;
311 af = AF_INET;
312 memset (&a4, 0, sizeof (a4));
313 a4.sin_family = AF_INET;
314 a4.sin_port = t4->u_port;
315 a4.sin_addr.s_addr = t4->ipv4_addr;
316 sb = &a4;
317 sbs = sizeof (a4);
318 }
319 else
320 {
321 GNUNET_break_op (0);
322 return -1;
323 }
324
234 /* Build the message to be sent */ 325 /* Build the message to be sent */
235 message = GNUNET_malloc (sizeof (struct UDPMessage) + msgbuf_size); 326 message = GNUNET_malloc (sizeof (struct UDPMessage) + msgbuf_size);
236 ssize = sizeof (struct UDPMessage) + msgbuf_size; 327 ssize = sizeof (struct UDPMessage) + msgbuf_size;
237 328
238#if DEBUG_UDP 329#if DEBUG_UDP
239 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ 330 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp",
240 ("In udp_send, ssize is %d, sending message to %s\n"), ssize, GNUNET_a2s((const struct sockaddr *)addr, addrlen)); 331 "In udp_send, ssize is %d, sending message to `%s'\n",
332 ssize,
333 GNUNET_a2s(sb, sbs));
241#endif 334#endif
242 message->header.size = htons (ssize); 335 message->header.size = htons (ssize);
243 message->header.type = htons (0); 336 message->header.type = htons (0);
@@ -246,8 +339,7 @@ udp_plugin_send (void *cls,
246 memcpy (&message[1], msgbuf, msgbuf_size); 339 memcpy (&message[1], msgbuf, msgbuf_size);
247 sent = 340 sent =
248 GNUNET_NETWORK_socket_sendto (udp_sock, message, ssize, 341 GNUNET_NETWORK_socket_sendto (udp_sock, message, ssize,
249 addr, 342 sb, sbs);
250 addrlen);
251 if ( (cont != NULL) && 343 if ( (cont != NULL) &&
252 (sent != -1) ) 344 (sent != -1) )
253 cont (cont_cls, target, GNUNET_OK); 345 cont (cont_cls, target, GNUNET_OK);
@@ -259,6 +351,13 @@ udp_plugin_send (void *cls,
259/** 351/**
260 * Add the IP of our network interface to the list of 352 * Add the IP of our network interface to the list of
261 * our external IP addresses. 353 * our external IP addresses.
354 *
355 * @param cls closure (the 'struct Plugin*')
356 * @param name name of the interface (can be NULL for unknown)
357 * @param isDefault is this presumably the default interface
358 * @param addr address of this interface (can be NULL for unknown or unassigned)
359 * @param addrlen length of the address
360 * @return GNUNET_OK to continue iterating
262 */ 361 */
263static int 362static int
264process_interfaces (void *cls, 363process_interfaces (void *cls,
@@ -268,29 +367,42 @@ process_interfaces (void *cls,
268{ 367{
269 struct Plugin *plugin = cls; 368 struct Plugin *plugin = cls;
270 int af; 369 int af;
271 struct sockaddr_in *v4; 370 struct IPv4UdpAddress t4;
272 struct sockaddr_in6 *v6; 371 struct IPv6UdpAddress t6;
372 void *arg;
373 uint16_t args;
273 374
274 af = addr->sa_family; 375 af = addr->sa_family;
275 if (af == AF_INET) 376 if (af == AF_INET)
276 { 377 {
277 v4 = (struct sockaddr_in *) addr; 378 t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
278 v4->sin_port = htons (plugin->adv_port); 379 t4.u_port = htons (plugin->adv_port);
380 arg = &t4;
381 args = sizeof (t4);
382 }
383 else if (af == AF_INET6)
384 {
385 memcpy (t6.ipv6_addr,
386 ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
387 16);
388 t6.u6_port = htons (plugin->adv_port);
389 arg = &t6;
390 args = sizeof (t6);
279 } 391 }
280 else 392 else
281 { 393 {
282 GNUNET_assert (af == AF_INET6); 394 GNUNET_break (0);
283 v6 = (struct sockaddr_in6 *) addr; 395 return GNUNET_OK;
284 v6->sin6_port = htons (plugin->adv_port);
285 } 396 }
286 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO | 397 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO |
287 GNUNET_ERROR_TYPE_BULK, 398 GNUNET_ERROR_TYPE_BULK,
288 "udp", _("Found address `%s' (%s)\n"), 399 "udp",
289 GNUNET_a2s (addr, addrlen), name); 400 _("Found address `%s' (%s)\n"),
401 GNUNET_a2s (addr, addrlen),
402 name);
290 plugin->env->notify_address (plugin->env->cls, 403 plugin->env->notify_address (plugin->env->cls,
291 "udp", 404 "udp",
292 addr, addrlen, GNUNET_TIME_UNIT_FOREVER_REL); 405 arg, args, GNUNET_TIME_UNIT_FOREVER_REL);
293
294 return GNUNET_OK; 406 return GNUNET_OK;
295} 407}
296 408
@@ -346,6 +458,12 @@ udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
346 int tsize; 458 int tsize;
347 char *msgbuf; 459 char *msgbuf;
348 const struct GNUNET_MessageHeader *currhdr; 460 const struct GNUNET_MessageHeader *currhdr;
461 struct IPv4UdpAddress t4;
462 struct IPv6UdpAddress t6;
463 const struct sockaddr_in *s4;
464 const struct sockaddr_in6 *s6;
465 const void *ca;
466 size_t calen;
349 467
350#if DEBUG_UDP 468#if DEBUG_UDP
351 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ 469 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
@@ -411,6 +529,31 @@ udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
411 ("offset is %d, tsize is %d (UDPMessage size is %d)\n"), 529 ("offset is %d, tsize is %d (UDPMessage size is %d)\n"),
412 offset, tsize, sizeof(struct UDPMessage)); 530 offset, tsize, sizeof(struct UDPMessage));
413#endif 531#endif
532
533 if (fromlen == sizeof (struct sockaddr_in))
534 {
535 s4 = (const struct sockaddr_in*) &addr;
536 t4.u_port = s4->sin_port;
537 t4.ipv4_addr = s4->sin_addr.s_addr;
538 ca = &t4;
539 calen = sizeof (struct IPv4UdpAddress);
540 }
541 else if (fromlen == sizeof (struct sockaddr_in6))
542 {
543 s6 = (const struct sockaddr_in6*) &addr;
544 t6.u6_port = s6->sin6_port;
545 memcpy (t6.ipv6_addr,
546 s6->sin6_addr.s6_addr,
547 16);
548 ca = &t6;
549 calen = sizeof (struct IPv6UdpAddress);
550 }
551 else
552 {
553 GNUNET_break (0);
554 ca = NULL;
555 calen = 0;
556 }
414 while (offset < tsize) 557 while (offset < tsize)
415 { 558 {
416 currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset]; 559 currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
@@ -421,7 +564,7 @@ udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
421#endif 564#endif
422 plugin->env->receive (plugin->env->cls, 565 plugin->env->receive (plugin->env->cls,
423 sender, currhdr, UDP_DIRECT_DISTANCE, 566 sender, currhdr, UDP_DIRECT_DISTANCE,
424 NULL, (const char *)&addr, fromlen); 567 NULL, ca, calen);
425 offset += ntohs(currhdr->size); 568 offset += ntohs(currhdr->size);
426#if DEBUG_UDP 569#if DEBUG_UDP
427 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _ 570 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
@@ -446,6 +589,7 @@ udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
446/** 589/**
447 * Create a UDP socket. If possible, use IPv6, otherwise 590 * Create a UDP socket. If possible, use IPv6, otherwise
448 * try IPv4. 591 * try IPv4.
592 * @param cls closure, the 'struct Plugin*'
449 */ 593 */
450static struct GNUNET_NETWORK_Handle * 594static struct GNUNET_NETWORK_Handle *
451udp_transport_server_start (void *cls) 595udp_transport_server_start (void *cls)
@@ -550,43 +694,30 @@ check_port (struct Plugin *plugin, uint16_t in_port)
550 * @param addrlen length of addr 694 * @param addrlen length of addr
551 * @return GNUNET_OK if this is a plausible address for this peer 695 * @return GNUNET_OK if this is a plausible address for this peer
552 * and transport, GNUNET_SYSERR if not 696 * and transport, GNUNET_SYSERR if not
553 *
554 * TODO: perhaps make everything work with sockaddr_storage, it may
555 * be a cleaner way to handle addresses in UDP
556 */ 697 */
557static int 698static int
558udp_check_address (void *cls, void *addr, size_t addrlen) 699udp_check_address (void *cls, void *addr, size_t addrlen)
559{ 700{
560 struct Plugin *plugin = cls; 701 struct Plugin *plugin = cls;
561 char buf[sizeof (struct sockaddr_in6)]; 702 struct IPv4UdpAddress *v4;
562 703 struct IPv6UdpAddress *v6;
563 struct sockaddr_in *v4;
564 struct sockaddr_in6 *v6;
565 704
566 if ((addrlen != sizeof (struct sockaddr_in)) && 705 if ((addrlen != sizeof (struct IPv4UdpAddress)) &&
567 (addrlen != sizeof (struct sockaddr_in6))) 706 (addrlen != sizeof (struct IPv6UdpAddress)))
568 { 707 {
569 GNUNET_break_op (0); 708 GNUNET_break_op (0);
570 return GNUNET_SYSERR; 709 return GNUNET_SYSERR;
571 } 710 }
572 memcpy (buf, addr, sizeof (struct sockaddr_in6)); 711 if (addrlen == sizeof (struct IPv4UdpAddress))
573 if (addrlen == sizeof (struct sockaddr_in))
574 { 712 {
575 v4 = (struct sockaddr_in *) buf; 713 v4 = (struct IPv4UdpAddress *) addr;
576 v4->sin_port = htons (check_port (plugin, ntohs (v4->sin_port))); 714 v4->u_port = htons (check_port (plugin, ntohs (v4->u_port)));
577 } 715 }
578 else 716 else
579 { 717 {
580 v6 = (struct sockaddr_in6 *) buf; 718 v6 = (struct IPv6UdpAddress *) addr;
581 v6->sin6_port = htons (check_port (plugin, ntohs (v6->sin6_port))); 719 v6->u6_port = htons (check_port (plugin, ntohs (v6->u6_port)));
582 } 720 }
583#if DEBUG_UDP
584 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
585 "tcp",
586 "Informing transport service about my address `%s'.\n",
587 GNUNET_a2s (addr, addrlen));
588#endif
589 return GNUNET_OK;
590 return GNUNET_OK; 721 return GNUNET_OK;
591} 722}
592 723
@@ -637,12 +768,43 @@ udp_plugin_address_pretty_printer (void *cls,
637 void *asc_cls) 768 void *asc_cls)
638{ 769{
639 struct Plugin *plugin = cls; 770 struct Plugin *plugin = cls;
640 const struct sockaddr_in *v4;
641 const struct sockaddr_in6 *v6;
642 struct PrettyPrinterContext *ppc; 771 struct PrettyPrinterContext *ppc;
772 const void *sb;
773 struct sockaddr_in a4;
774 struct sockaddr_in6 a6;
775 const struct IPv4UdpAddress *t4;
776 const struct IPv6UdpAddress *t6;
777 int af;
778 size_t sbs;
779 uint16_t port;
643 780
644 if ((addrlen != sizeof (struct sockaddr_in)) && 781 if (addrlen == sizeof (struct IPv6UdpAddress))
645 (addrlen != sizeof (struct sockaddr_in6))) 782 {
783 t6 = addr;
784 af = AF_INET6;
785 memset (&a6, 0, sizeof (a6));
786 a6.sin6_family = AF_INET6;
787 a6.sin6_port = t6->u6_port;
788 port = ntohs (t6->u6_port);
789 memcpy (a6.sin6_addr.s6_addr,
790 t6->ipv6_addr,
791 16);
792 sb = &a6;
793 sbs = sizeof (a6);
794 }
795 else if (addrlen == sizeof (struct IPv4UdpAddress))
796 {
797 t4 = addr;
798 af = AF_INET;
799 memset (&a4, 0, sizeof (a4));
800 a4.sin_family = AF_INET;
801 a4.sin_port = t4->u_port;
802 a4.sin_addr.s_addr = t4->ipv4_addr;
803 port = ntohs (t4->u_port);
804 sb = &a4;
805 sbs = sizeof (a4);
806 }
807 else
646 { 808 {
647 /* invalid address */ 809 /* invalid address */
648 GNUNET_break_op (0); 810 GNUNET_break_op (0);
@@ -652,28 +814,75 @@ udp_plugin_address_pretty_printer (void *cls,
652 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext)); 814 ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
653 ppc->asc = asc; 815 ppc->asc = asc;
654 ppc->asc_cls = asc_cls; 816 ppc->asc_cls = asc_cls;
655 if (addrlen == sizeof (struct sockaddr_in)) 817 ppc->port = port;
818 GNUNET_RESOLVER_hostname_get (plugin->env->sched,
819 plugin->env->cfg,
820 sb,
821 sbs,
822 !numeric, timeout, &append_port, ppc);
823}
824
825
826
827/**
828 * Function called for a quick conversion of the binary address to
829 * a numeric address. Note that the caller must not free the
830 * address and that the next call to this function is allowed
831 * to override the address again.
832 *
833 * @param cls closure
834 * @param addr binary address
835 * @param addr_len length of the address
836 * @return string representing the same address
837 */
838static const char*
839udp_address_to_string (void *cls,
840 const void *addr,
841 size_t addrlen)
842{
843 static char buf[INET6_ADDRSTRLEN];
844 const void *sb;
845 struct sockaddr_in a4;
846 struct sockaddr_in6 a6;
847 const struct IPv4UdpAddress *t4;
848 const struct IPv6UdpAddress *t6;
849 int af;
850
851 if (addrlen == sizeof (struct IPv6UdpAddress))
656 { 852 {
657 v4 = (const struct sockaddr_in *) addr; 853 t6 = addr;
658 ppc->port = ntohs (v4->sin_port); 854 af = AF_INET6;
855 memset (&a6, 0, sizeof (a6));
856 a6.sin6_family = AF_INET6;
857 a6.sin6_port = t6->u6_port;
858 memcpy (a6.sin6_addr.s6_addr,
859 t6->ipv6_addr,
860 16);
861 sb = &a6;
659 } 862 }
660 else 863 else if (addrlen == sizeof (struct IPv4UdpAddress))
661 { 864 {
662 v6 = (const struct sockaddr_in6 *) addr; 865 t4 = addr;
663 ppc->port = ntohs (v6->sin6_port); 866 af = AF_INET;
664 867 memset (&a4, 0, sizeof (a4));
868 a4.sin_family = AF_INET;
869 a4.sin_port = t4->u_port;
870 a4.sin_addr.s_addr = t4->ipv4_addr;
871 sb = &a4;
665 } 872 }
666 GNUNET_RESOLVER_hostname_get (plugin->env->sched, 873 else
667 plugin->env->cfg, 874 return NULL;
668 addr, 875
669 addrlen, 876 return inet_ntop (af, sb, buf, INET6_ADDRSTRLEN);
670 !numeric, timeout, &append_port, ppc);
671} 877}
672 878
673 879
674/** 880/**
675 * The exported method. Makes the core api available via a global and 881 * The exported method. Makes the core api available via a global and
676 * returns the udp transport API. 882 * returns the udp transport API.
883 *
884 * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
885 * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error
677 */ 886 */
678void * 887void *
679libgnunet_plugin_transport_udp_init (void *cls) 888libgnunet_plugin_transport_udp_init (void *cls)
@@ -737,7 +946,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
737 api->disconnect = &udp_disconnect; 946 api->disconnect = &udp_disconnect;
738 api->address_pretty_printer = &udp_plugin_address_pretty_printer; 947 api->address_pretty_printer = &udp_plugin_address_pretty_printer;
739 api->check_address = &udp_check_address; 948 api->check_address = &udp_check_address;
740 949 api->address_to_string = &udp_address_to_string;
741 plugin->service = service; 950 plugin->service = service;
742 951
743 /* FIXME: do the two calls below periodically again and 952 /* FIXME: do the two calls below periodically again and