diff options
-rw-r--r-- | src/dhtu/plugin_dhtu_ip.c | 390 |
1 files changed, 347 insertions, 43 deletions
diff --git a/src/dhtu/plugin_dhtu_ip.c b/src/dhtu/plugin_dhtu_ip.c index c76744d9a..19fe19192 100644 --- a/src/dhtu/plugin_dhtu_ip.c +++ b/src/dhtu/plugin_dhtu_ip.c | |||
@@ -167,9 +167,14 @@ struct Plugin | |||
167 | struct GNUNET_SCHEDULER_Task *scan_task; | 167 | struct GNUNET_SCHEDULER_Task *scan_task; |
168 | 168 | ||
169 | /** | 169 | /** |
170 | * Port we bind to. FIXME: initialize... | 170 | * Task that reads incoming UDP packets. |
171 | */ | 171 | */ |
172 | char *my_port; | 172 | struct GNUNET_SCHEDULER_Task *read_task; |
173 | |||
174 | /** | ||
175 | * Port we bind to. | ||
176 | */ | ||
177 | char *port; | ||
173 | 178 | ||
174 | /** | 179 | /** |
175 | * How often have we scanned for IPs? | 180 | * How often have we scanned for IPs? |
@@ -179,7 +184,7 @@ struct Plugin | |||
179 | /** | 184 | /** |
180 | * My UDP socket. | 185 | * My UDP socket. |
181 | */ | 186 | */ |
182 | int sock; | 187 | struct GNUNET_NETWORK_Handle *sock; |
183 | }; | 188 | }; |
184 | 189 | ||
185 | 190 | ||
@@ -266,7 +271,7 @@ ip_try_connect (void *cls, | |||
266 | colon = strchr (addr, ':'); | 271 | colon = strchr (addr, ':'); |
267 | if (NULL == colon) | 272 | if (NULL == colon) |
268 | { | 273 | { |
269 | port = plugin->my_port; | 274 | port = plugin->port; |
270 | } | 275 | } |
271 | else | 276 | else |
272 | { | 277 | { |
@@ -359,17 +364,93 @@ ip_send (void *cls, | |||
359 | { | 364 | { |
360 | struct Plugin *plugin = cls; | 365 | struct Plugin *plugin = cls; |
361 | 366 | ||
362 | sendto (plugin->sock, | 367 | GNUNET_NETWORK_socket_sendto (plugin->sock, |
363 | msg, | 368 | msg, |
364 | msg_size, | 369 | msg_size, |
365 | 0, | 370 | (const struct sockaddr *) &target->addr, |
366 | (const struct sockaddr *) &target->addr, | 371 | target->addrlen); |
367 | target->addrlen); | ||
368 | finished_cb (finished_cb_cls); | 372 | finished_cb (finished_cb_cls); |
369 | } | 373 | } |
370 | 374 | ||
371 | 375 | ||
372 | /** | 376 | /** |
377 | * Create a new source on which we may be receiving traffic. | ||
378 | * | ||
379 | * @param plugin our plugin | ||
380 | * @param addr our address | ||
381 | * @param addrlen number of bytes in @a addr | ||
382 | * @return new source object | ||
383 | */ | ||
384 | static struct GNUNET_DHTU_Source * | ||
385 | create_source (struct Plugin *plugin, | ||
386 | const struct sockaddr *addr, | ||
387 | socklen_t addrlen) | ||
388 | { | ||
389 | struct GNUNET_DHTU_Source *src; | ||
390 | |||
391 | src = GNUNET_new (struct GNUNET_DHTU_Source); | ||
392 | src->addrlen = addrlen; | ||
393 | memcpy (&src->addr, | ||
394 | addr, | ||
395 | addrlen); | ||
396 | src->scan_generation = plugin->scan_generation; | ||
397 | switch (addr->sa_family) | ||
398 | { | ||
399 | case AF_INET: | ||
400 | { | ||
401 | const struct sockaddr_in *s4 = (const struct sockaddr_in *) addr; | ||
402 | char buf[INET_ADDRSTRLEN]; | ||
403 | |||
404 | GNUNET_assert (sizeof (struct sockaddr_in) == addrlen); | ||
405 | GNUNET_CRYPTO_hash (&s4->sin_addr, | ||
406 | sizeof (struct in_addr), | ||
407 | &src->id.hc); | ||
408 | GNUNET_asprintf (&src->address, | ||
409 | "ip+udp://%s:%u", | ||
410 | inet_ntop (AF_INET, | ||
411 | &s4->sin_addr, | ||
412 | buf, | ||
413 | sizeof (buf)), | ||
414 | ntohs (s4->sin_port)); | ||
415 | } | ||
416 | break; | ||
417 | case AF_INET6: | ||
418 | { | ||
419 | const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) addr; | ||
420 | char buf[INET6_ADDRSTRLEN]; | ||
421 | |||
422 | GNUNET_assert (sizeof (struct sockaddr_in6) == addrlen); | ||
423 | GNUNET_CRYPTO_hash (&s6->sin6_addr, | ||
424 | sizeof (struct in6_addr), | ||
425 | &src->id.hc); | ||
426 | GNUNET_asprintf (&src->address, | ||
427 | "ip+udp://[%s]:%u", | ||
428 | inet_ntop (AF_INET6, | ||
429 | &s6->sin6_addr, | ||
430 | buf, | ||
431 | sizeof (buf)), | ||
432 | ntohs (s6->sin6_port)); | ||
433 | } | ||
434 | break; | ||
435 | default: | ||
436 | GNUNET_break (0); | ||
437 | GNUNET_free (src); | ||
438 | return NULL; | ||
439 | } | ||
440 | GNUNET_CONTAINER_DLL_insert (plugin->src_head, | ||
441 | plugin->src_tail, | ||
442 | src); | ||
443 | plugin->env->address_add_cb (plugin->env->cls, | ||
444 | &src->id, | ||
445 | NULL, /* no key */ | ||
446 | src->address, | ||
447 | src, | ||
448 | &src->app_ctx); | ||
449 | return src; | ||
450 | } | ||
451 | |||
452 | |||
453 | /** | ||
373 | * Callback function invoked for each interface found. | 454 | * Callback function invoked for each interface found. |
374 | * | 455 | * |
375 | * @param cls closure | 456 | * @param cls closure |
@@ -406,36 +487,9 @@ process_ifcs (void *cls, | |||
406 | return GNUNET_OK; | 487 | return GNUNET_OK; |
407 | } | 488 | } |
408 | } | 489 | } |
409 | src = GNUNET_new (struct GNUNET_DHTU_Source); | 490 | (void) create_source (plugin, |
410 | src->addrlen = addrlen; | 491 | addr, |
411 | memcpy (&src->addr, | 492 | addrlen); |
412 | addr, | ||
413 | addrlen); | ||
414 | src->scan_generation = plugin->scan_generation; | ||
415 | switch (addr->sa_family) | ||
416 | { | ||
417 | case AF_INET: | ||
418 | // hash v4 address | ||
419 | // convert address to src->address | ||
420 | break; | ||
421 | case AF_INET6: | ||
422 | // hash v6 address | ||
423 | // convert address to src->address | ||
424 | break; | ||
425 | default: | ||
426 | GNUNET_break (0); | ||
427 | GNUNET_free (src); | ||
428 | return GNUNET_OK; | ||
429 | } | ||
430 | GNUNET_CONTAINER_DLL_insert (plugin->src_head, | ||
431 | plugin->src_tail, | ||
432 | src); | ||
433 | plugin->env->address_add_cb (plugin->env->cls, | ||
434 | &src->id, | ||
435 | NULL, /* no key */ | ||
436 | src->address, | ||
437 | src, | ||
438 | &src->app_ctx); | ||
439 | return GNUNET_OK; | 493 | return GNUNET_OK; |
440 | } | 494 | } |
441 | 495 | ||
@@ -475,6 +529,186 @@ scan (void *cls) | |||
475 | 529 | ||
476 | 530 | ||
477 | /** | 531 | /** |
532 | * Find our source matching @a addr. If none exists, | ||
533 | * create one! | ||
534 | * | ||
535 | * @param plugin the plugin handle | ||
536 | * @param addr IP address to find | ||
537 | * @param addrlen number of bytes in @a addr | ||
538 | * @return matching source object | ||
539 | */ | ||
540 | static struct GNUNET_DHTU_Source * | ||
541 | find_source (struct Plugin *plugin, | ||
542 | const void *addr, | ||
543 | size_t addrlen) | ||
544 | { | ||
545 | for (struct GNUNET_DHTU_Source *src = plugin->src_head; | ||
546 | NULL != src; | ||
547 | src = src->next) | ||
548 | { | ||
549 | if ( (addrlen == sizeof (struct in_addr)) && | ||
550 | (src->addrlen == sizeof (struct sockaddr_in)) ) | ||
551 | { | ||
552 | const struct sockaddr_in *sa = | ||
553 | (const struct sockaddr_in *) &src->addr; | ||
554 | if (0 == memcmp (addr, | ||
555 | &sa->sin_addr, | ||
556 | addrlen)) | ||
557 | return src; | ||
558 | } | ||
559 | if ( (addrlen == sizeof (struct in6_addr)) && | ||
560 | (src->addrlen == sizeof (struct sockaddr_in6)) ) | ||
561 | { | ||
562 | const struct sockaddr_in6 *sa = | ||
563 | (const struct sockaddr_in6 *) &src->addr; | ||
564 | if (0 == memcmp (addr, | ||
565 | &sa->sin6_addr, | ||
566 | addrlen)) | ||
567 | return src; | ||
568 | } | ||
569 | } | ||
570 | |||
571 | { | ||
572 | struct sockaddr_storage sa; | ||
573 | socklen_t salen; | ||
574 | |||
575 | memset (&sa, | ||
576 | 0, | ||
577 | sizeof (sa)); | ||
578 | if (addrlen == sizeof (struct in_addr)) | ||
579 | { | ||
580 | struct sockaddr_in *s4 = | ||
581 | (struct sockaddr_in *) &sa; | ||
582 | |||
583 | s4->sin_family = AF_INET; | ||
584 | memcpy (&s4->sin_addr, | ||
585 | addr, | ||
586 | addrlen); | ||
587 | salen = sizeof (*s4); | ||
588 | } | ||
589 | if (addrlen == sizeof (struct in6_addr)) | ||
590 | { | ||
591 | struct sockaddr_in6 *s6 = | ||
592 | (struct sockaddr_in6 *) &sa; | ||
593 | |||
594 | s6->sin6_family = AF_INET6; | ||
595 | memcpy (&s6->sin6_addr, | ||
596 | addr, | ||
597 | addrlen); | ||
598 | salen = sizeof (*s6); | ||
599 | } | ||
600 | return create_source (plugin, | ||
601 | (const struct sockaddr *) &sa, | ||
602 | salen); | ||
603 | } | ||
604 | } | ||
605 | |||
606 | |||
607 | /** | ||
608 | * UDP socket is ready to receive. Read. | ||
609 | * | ||
610 | * @param cls our `struct Plugin *` | ||
611 | */ | ||
612 | static void | ||
613 | read_cb (void *cls) | ||
614 | { | ||
615 | struct Plugin *plugin = cls; | ||
616 | ssize_t ret; | ||
617 | char buf[65536]; | ||
618 | struct sockaddr_storage sa; | ||
619 | struct iovec iov = { | ||
620 | .iov_base = buf, | ||
621 | .iov_len = sizeof (buf) | ||
622 | }; | ||
623 | char ctl[1024]; | ||
624 | struct msghdr mh = { | ||
625 | .msg_name = &sa, | ||
626 | .msg_namelen = sizeof (sa), | ||
627 | .msg_iov = &iov, | ||
628 | .msg_iovlen = 1, | ||
629 | .msg_control = ctl, | ||
630 | .msg_controllen = sizeof (ctl) | ||
631 | }; | ||
632 | |||
633 | ret = recvmsg (GNUNET_NETWORK_get_fd (plugin->sock), | ||
634 | &mh, | ||
635 | MSG_DONTWAIT); | ||
636 | if (ret >= 0) | ||
637 | { | ||
638 | struct GNUNET_DHTU_Target *dst = NULL; | ||
639 | struct GNUNET_DHTU_Source *src = NULL; | ||
640 | struct cmsghdr *cmsg; | ||
641 | struct msghdr *msh = mh.msg_control; | ||
642 | |||
643 | /* find IP where we received message */ | ||
644 | for (cmsg = CMSG_FIRSTHDR (msh); | ||
645 | NULL != cmsg; | ||
646 | cmsg = CMSG_NXTHDR (msh, | ||
647 | cmsg)) | ||
648 | { | ||
649 | if ( (cmsg->cmsg_level == IPPROTO_IP) && | ||
650 | (cmsg->cmsg_type == IP_ORIGDSTADDR) ) | ||
651 | { | ||
652 | if (CMSG_LEN (sizeof (struct in_addr)) == | ||
653 | cmsg->cmsg_len) | ||
654 | { | ||
655 | struct in6_addr ia; | ||
656 | |||
657 | memcpy (&ia, | ||
658 | CMSG_DATA (cmsg), | ||
659 | sizeof (ia)); | ||
660 | src = find_source (plugin, | ||
661 | &ia, | ||
662 | sizeof (ia)); | ||
663 | break; | ||
664 | } | ||
665 | else | ||
666 | GNUNET_break (0); | ||
667 | } | ||
668 | if ( (cmsg->cmsg_level == IPPROTO_IPV6) && | ||
669 | (cmsg->cmsg_type == IP_ORIGDSTADDR) ) | ||
670 | { | ||
671 | if (CMSG_LEN (sizeof (struct in6_addr)) == | ||
672 | cmsg->cmsg_len) | ||
673 | { | ||
674 | struct in6_addr ia; | ||
675 | |||
676 | memcpy (&ia, | ||
677 | CMSG_DATA (cmsg), | ||
678 | sizeof (ia)); | ||
679 | src = find_source (plugin, | ||
680 | &ia, | ||
681 | sizeof (ia)); | ||
682 | break; | ||
683 | } | ||
684 | else | ||
685 | GNUNET_break (0); | ||
686 | } | ||
687 | } | ||
688 | // FIXME: find or create 'dst'! | ||
689 | if ( (NULL == src) || | ||
690 | (NULL == dst) ) | ||
691 | { | ||
692 | GNUNET_break (0); | ||
693 | } | ||
694 | else | ||
695 | { | ||
696 | plugin->env->receive_cb (plugin->env->cls, | ||
697 | dst->app_ctx, | ||
698 | src->app_ctx, | ||
699 | buf, | ||
700 | ret); | ||
701 | } | ||
702 | } | ||
703 | plugin->read_task = GNUNET_SCHEDULER_add_read_net ( | ||
704 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
705 | plugin->sock, | ||
706 | &read_cb, | ||
707 | plugin); | ||
708 | } | ||
709 | |||
710 | |||
711 | /** | ||
478 | * Entry point for the plugin. | 712 | * Entry point for the plugin. |
479 | * | 713 | * |
480 | * @param cls closure (the `struct GNUNET_DHTU_PluginEnvironment`) | 714 | * @param cls closure (the `struct GNUNET_DHTU_PluginEnvironment`) |
@@ -486,14 +720,81 @@ libgnunet_plugin_dhtu_ip_init (void *cls) | |||
486 | struct GNUNET_DHTU_PluginEnvironment *env = cls; | 720 | struct GNUNET_DHTU_PluginEnvironment *env = cls; |
487 | struct GNUNET_DHTU_PluginFunctions *api; | 721 | struct GNUNET_DHTU_PluginFunctions *api; |
488 | struct Plugin *plugin; | 722 | struct Plugin *plugin; |
723 | char *port; | ||
724 | unsigned int nport; | ||
725 | int sock; | ||
489 | 726 | ||
727 | if (GNUNET_OK != | ||
728 | GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
729 | "DHTU-IP", | ||
730 | "UDP_PORT", | ||
731 | &port)) | ||
732 | { | ||
733 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
734 | "DHTU-IP", | ||
735 | "UDP_PORT"); | ||
736 | return NULL; | ||
737 | } | ||
738 | { | ||
739 | char dummy; | ||
740 | |||
741 | if ( (1 != sscanf (port, | ||
742 | "%u%c", | ||
743 | &nport, | ||
744 | &dummy)) || | ||
745 | (nport > UINT16_MAX) ) | ||
746 | { | ||
747 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
748 | "DHTU-IP", | ||
749 | "UDP_PORT", | ||
750 | "must be number below 65536"); | ||
751 | GNUNET_free (port); | ||
752 | return NULL; | ||
753 | } | ||
754 | } | ||
490 | plugin = GNUNET_new (struct Plugin); | 755 | plugin = GNUNET_new (struct Plugin); |
491 | plugin->env = env; | 756 | plugin->env = env; |
492 | // FIXME: get port configuration! | 757 | plugin->port = port; |
758 | sock = socket (AF_INET6, | ||
759 | SOCK_DGRAM, | ||
760 | IPPROTO_UDP); | ||
761 | if (-1 == sock) | ||
762 | { | ||
763 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
764 | "socket"); | ||
765 | GNUNET_free (plugin->port); | ||
766 | GNUNET_free (plugin); | ||
767 | return NULL; | ||
768 | } | ||
769 | { | ||
770 | struct sockaddr_in6 sa = { | ||
771 | .sin6_family = AF_INET6, | ||
772 | .sin6_port = htons ((uint16_t) nport) | ||
773 | }; | ||
774 | |||
775 | if (0 != | ||
776 | bind (sock, | ||
777 | &sa, | ||
778 | sizeof (sa))) | ||
779 | { | ||
780 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
781 | "socket"); | ||
782 | GNUNET_break (0 == | ||
783 | close (sock)); | ||
784 | GNUNET_free (plugin->port); | ||
785 | GNUNET_free (plugin); | ||
786 | return NULL; | ||
787 | } | ||
788 | } | ||
789 | plugin->sock = GNUNET_NETWORK_socket_box_native (sock); | ||
790 | plugin->read_task = GNUNET_SCHEDULER_add_read_net ( | ||
791 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
792 | plugin->sock, | ||
793 | &read_cb, | ||
794 | plugin); | ||
795 | // FIXME: deal with NSE callback... | ||
493 | plugin->scan_task = GNUNET_SCHEDULER_add_now (&scan, | 796 | plugin->scan_task = GNUNET_SCHEDULER_add_now (&scan, |
494 | plugin); | 797 | plugin); |
495 | // FIXME: bind, start receive loop | ||
496 | // FIXME: deal with NSE callback... | ||
497 | api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions); | 798 | api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions); |
498 | api->cls = plugin; | 799 | api->cls = plugin; |
499 | api->sign = &ip_sign; | 800 | api->sign = &ip_sign; |
@@ -519,6 +820,9 @@ libgnunet_plugin_dhtu_ip_done (void *cls) | |||
519 | struct Plugin *plugin = api->cls; | 820 | struct Plugin *plugin = api->cls; |
520 | 821 | ||
521 | GNUNET_SCHEDULER_cancel (plugin->scan_task); | 822 | GNUNET_SCHEDULER_cancel (plugin->scan_task); |
823 | GNUNET_break (0 == | ||
824 | GNUNET_NETWORK_socket_close (plugin->sock)); | ||
825 | GNUNET_free (plugin->port); | ||
522 | GNUNET_free (plugin); | 826 | GNUNET_free (plugin); |
523 | GNUNET_free (api); | 827 | GNUNET_free (api); |
524 | return NULL; | 828 | return NULL; |