diff options
Diffstat (limited to 'src/vpn')
-rw-r--r-- | src/vpn/gnunet-service-vpn.c | 222 |
1 files changed, 120 insertions, 102 deletions
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c index d18530dab..4c0978d5c 100644 --- a/src/vpn/gnunet-service-vpn.c +++ b/src/vpn/gnunet-service-vpn.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2010, 2011, 2012 Christian Grothoff | 3 | Copyright (C) 2010, 2011, 2012, 2016 Christian Grothoff |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -377,11 +377,6 @@ static char *vpn_argv[7]; | |||
377 | static unsigned long long ipv6prefix; | 377 | static unsigned long long ipv6prefix; |
378 | 378 | ||
379 | /** | 379 | /** |
380 | * Notification context for sending replies to clients. | ||
381 | */ | ||
382 | static struct GNUNET_SERVER_NotificationContext *nc; | ||
383 | |||
384 | /** | ||
385 | * If there are more than this number of address-mappings, old ones | 380 | * If there are more than this number of address-mappings, old ones |
386 | * will be removed | 381 | * will be removed |
387 | */ | 382 | */ |
@@ -489,12 +484,12 @@ get_channel_key_from_ips (int af, | |||
489 | * @param addr resulting IP address | 484 | * @param addr resulting IP address |
490 | */ | 485 | */ |
491 | static void | 486 | static void |
492 | send_client_reply (struct GNUNET_SERVER_Client *client, | 487 | send_client_reply (struct GNUNET_SERVICE_Client *client, |
493 | uint64_t request_id, | 488 | uint64_t request_id, |
494 | int result_af, | 489 | int result_af, |
495 | const void *addr) | 490 | const void *addr) |
496 | { | 491 | { |
497 | char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)] GNUNET_ALIGN; | 492 | struct GNUNET_MQ_Envelope *env; |
498 | struct RedirectToIpResponseMessage *res; | 493 | struct RedirectToIpResponseMessage *res; |
499 | size_t rlen; | 494 | size_t rlen; |
500 | 495 | ||
@@ -513,19 +508,16 @@ send_client_reply (struct GNUNET_SERVER_Client *client, | |||
513 | GNUNET_assert (0); | 508 | GNUNET_assert (0); |
514 | return; | 509 | return; |
515 | } | 510 | } |
516 | res = (struct RedirectToIpResponseMessage *) buf; | 511 | env = GNUNET_MQ_msg_extra (res, |
517 | res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen); | 512 | rlen, |
518 | res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP); | 513 | GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP); |
519 | res->result_af = htonl (result_af); | 514 | res->result_af = htonl (result_af); |
520 | res->request_id = request_id; | 515 | res->request_id = request_id; |
521 | GNUNET_memcpy (&res[1], | 516 | GNUNET_memcpy (&res[1], |
522 | addr, | 517 | addr, |
523 | rlen); | 518 | rlen); |
524 | GNUNET_SERVER_notification_context_add (nc, client); | 519 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), |
525 | GNUNET_SERVER_notification_context_unicast (nc, | 520 | env); |
526 | client, | ||
527 | &res->header, | ||
528 | GNUNET_NO); | ||
529 | } | 521 | } |
530 | 522 | ||
531 | 523 | ||
@@ -2606,39 +2598,21 @@ allocate_response_ip (int *result_af, | |||
2606 | 2598 | ||
2607 | /** | 2599 | /** |
2608 | * A client asks us to setup a redirection via some exit node to a | 2600 | * A client asks us to setup a redirection via some exit node to a |
2609 | * particular IP. Setup the redirection and give the client the | 2601 | * particular IP. Check if @a msg is well-formed. |
2610 | * allocated IP. | 2602 | * allocated IP. |
2611 | * | 2603 | * |
2612 | * @param cls unused | 2604 | * @param cls client requesting client |
2613 | * @param client requesting client | 2605 | * @param msg redirection request |
2614 | * @param message redirection request (a `struct RedirectToIpRequestMessage`) | 2606 | * @return #GNUNET_OK if @a msg is well-formed |
2615 | */ | 2607 | */ |
2616 | static void | 2608 | static int |
2617 | service_redirect_to_ip (void *cls, | 2609 | check_client_redirect_to_ip (void *cls, |
2618 | struct GNUNET_SERVER_Client *client, | 2610 | const struct RedirectToIpRequestMessage *msg) |
2619 | const struct GNUNET_MessageHeader *message) | ||
2620 | { | 2611 | { |
2621 | size_t mlen; | ||
2622 | size_t alen; | 2612 | size_t alen; |
2623 | const struct RedirectToIpRequestMessage *msg; | ||
2624 | int addr_af; | 2613 | int addr_af; |
2625 | int result_af; | ||
2626 | struct in_addr v4; | ||
2627 | struct in6_addr v6; | ||
2628 | void *addr; | ||
2629 | struct DestinationEntry *de; | ||
2630 | struct GNUNET_HashCode key; | ||
2631 | 2614 | ||
2632 | /* validate and parse request */ | 2615 | alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage); |
2633 | mlen = ntohs (message->size); | ||
2634 | if (mlen < sizeof (struct RedirectToIpRequestMessage)) | ||
2635 | { | ||
2636 | GNUNET_break (0); | ||
2637 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
2638 | return; | ||
2639 | } | ||
2640 | alen = mlen - sizeof (struct RedirectToIpRequestMessage); | ||
2641 | msg = (const struct RedirectToIpRequestMessage *) message; | ||
2642 | addr_af = (int) htonl (msg->addr_af); | 2616 | addr_af = (int) htonl (msg->addr_af); |
2643 | switch (addr_af) | 2617 | switch (addr_af) |
2644 | { | 2618 | { |
@@ -2646,31 +2620,55 @@ service_redirect_to_ip (void *cls, | |||
2646 | if (alen != sizeof (struct in_addr)) | 2620 | if (alen != sizeof (struct in_addr)) |
2647 | { | 2621 | { |
2648 | GNUNET_break (0); | 2622 | GNUNET_break (0); |
2649 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2623 | return GNUNET_SYSERR; |
2650 | return; | ||
2651 | } | 2624 | } |
2652 | break; | 2625 | break; |
2653 | case AF_INET6: | 2626 | case AF_INET6: |
2654 | if (alen != sizeof (struct in6_addr)) | 2627 | if (alen != sizeof (struct in6_addr)) |
2655 | { | 2628 | { |
2656 | GNUNET_break (0); | 2629 | GNUNET_break (0); |
2657 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2630 | return GNUNET_SYSERR; |
2658 | return; | ||
2659 | } | 2631 | } |
2660 | break; | 2632 | break; |
2661 | default: | 2633 | default: |
2662 | GNUNET_break (0); | 2634 | GNUNET_break (0); |
2663 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2635 | return GNUNET_SYSERR; |
2664 | return; | ||
2665 | } | 2636 | } |
2637 | return GNUNET_OK; | ||
2638 | } | ||
2639 | |||
2640 | |||
2641 | /** | ||
2642 | * A client asks us to setup a redirection via some exit node to a | ||
2643 | * particular IP. Setup the redirection and give the client the | ||
2644 | * allocated IP. | ||
2645 | * | ||
2646 | * @param cls client requesting client | ||
2647 | * @param msg redirection request | ||
2648 | */ | ||
2649 | static void | ||
2650 | handle_client_redirect_to_ip (void *cls, | ||
2651 | const struct RedirectToIpRequestMessage *msg) | ||
2652 | { | ||
2653 | struct GNUNET_SERVICE_Client *client = cls; | ||
2654 | size_t alen; | ||
2655 | int addr_af; | ||
2656 | int result_af; | ||
2657 | struct in_addr v4; | ||
2658 | struct in6_addr v6; | ||
2659 | void *addr; | ||
2660 | struct DestinationEntry *de; | ||
2661 | struct GNUNET_HashCode key; | ||
2666 | 2662 | ||
2663 | alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage); | ||
2664 | addr_af = (int) htonl (msg->addr_af); | ||
2667 | /* allocate response IP */ | 2665 | /* allocate response IP */ |
2668 | result_af = (int) htonl (msg->result_af); | 2666 | result_af = (int) htonl (msg->result_af); |
2669 | if (GNUNET_OK != allocate_response_ip (&result_af, | 2667 | if (GNUNET_OK != allocate_response_ip (&result_af, |
2670 | &addr, | 2668 | &addr, |
2671 | &v4, &v6)) | 2669 | &v4, &v6)) |
2672 | { | 2670 | { |
2673 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2671 | GNUNET_SERVICE_client_drop (client); |
2674 | return; | 2672 | return; |
2675 | } | 2673 | } |
2676 | /* send reply with our IP address */ | 2674 | /* send reply with our IP address */ |
@@ -2681,7 +2679,7 @@ service_redirect_to_ip (void *cls, | |||
2681 | if (result_af == AF_UNSPEC) | 2679 | if (result_af == AF_UNSPEC) |
2682 | { | 2680 | { |
2683 | /* failure, we're done */ | 2681 | /* failure, we're done */ |
2684 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 2682 | GNUNET_SERVICE_client_continue (client); |
2685 | return; | 2683 | return; |
2686 | } | 2684 | } |
2687 | 2685 | ||
@@ -2691,9 +2689,14 @@ service_redirect_to_ip (void *cls, | |||
2691 | 2689 | ||
2692 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2690 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2693 | "Allocated address %s for redirection via exit to %s\n", | 2691 | "Allocated address %s for redirection via exit to %s\n", |
2694 | inet_ntop (result_af, addr, sbuf, sizeof (sbuf)), | 2692 | inet_ntop (result_af, |
2693 | addr, | ||
2694 | sbuf, | ||
2695 | sizeof (sbuf)), | ||
2695 | inet_ntop (addr_af, | 2696 | inet_ntop (addr_af, |
2696 | &msg[1], dbuf, sizeof (dbuf))); | 2697 | &msg[1], |
2698 | dbuf, | ||
2699 | sizeof (dbuf))); | ||
2697 | } | 2700 | } |
2698 | 2701 | ||
2699 | /* setup destination record */ | 2702 | /* setup destination record */ |
@@ -2701,8 +2704,8 @@ service_redirect_to_ip (void *cls, | |||
2701 | de->is_service = GNUNET_NO; | 2704 | de->is_service = GNUNET_NO; |
2702 | de->details.exit_destination.af = addr_af; | 2705 | de->details.exit_destination.af = addr_af; |
2703 | GNUNET_memcpy (&de->details.exit_destination.ip, | 2706 | GNUNET_memcpy (&de->details.exit_destination.ip, |
2704 | &msg[1], | 2707 | &msg[1], |
2705 | alen); | 2708 | alen); |
2706 | get_destination_key_from_ip (result_af, | 2709 | get_destination_key_from_ip (result_af, |
2707 | addr, | 2710 | addr, |
2708 | &key); | 2711 | &key); |
@@ -2720,7 +2723,7 @@ service_redirect_to_ip (void *cls, | |||
2720 | 1, GNUNET_NO); | 2723 | 1, GNUNET_NO); |
2721 | while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings) | 2724 | while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings) |
2722 | expire_destination (de); | 2725 | expire_destination (de); |
2723 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 2726 | GNUNET_SERVICE_client_continue (client); |
2724 | } | 2727 | } |
2725 | 2728 | ||
2726 | 2729 | ||
@@ -2729,16 +2732,14 @@ service_redirect_to_ip (void *cls, | |||
2729 | * offering a service. Setup the redirection and give the client the | 2732 | * offering a service. Setup the redirection and give the client the |
2730 | * allocated IP. | 2733 | * allocated IP. |
2731 | * | 2734 | * |
2732 | * @param cls unused | 2735 | * @param cls requesting client |
2733 | * @param client requesting client | 2736 | * @param msg redirection request |
2734 | * @param message redirection request (a `struct RedirectToPeerRequestMessage`) | ||
2735 | */ | 2737 | */ |
2736 | static void | 2738 | static void |
2737 | service_redirect_to_service (void *cls, | 2739 | handle_client_redirect_to_service (void *cls, |
2738 | struct GNUNET_SERVER_Client *client, | 2740 | const struct RedirectToServiceRequestMessage *msg) |
2739 | const struct GNUNET_MessageHeader *message) | ||
2740 | { | 2741 | { |
2741 | const struct RedirectToServiceRequestMessage *msg; | 2742 | struct GNUNET_SERVICE_Client *client = cls; |
2742 | int result_af; | 2743 | int result_af; |
2743 | struct in_addr v4; | 2744 | struct in_addr v4; |
2744 | struct in6_addr v6; | 2745 | struct in6_addr v6; |
@@ -2747,9 +2748,6 @@ service_redirect_to_service (void *cls, | |||
2747 | struct GNUNET_HashCode key; | 2748 | struct GNUNET_HashCode key; |
2748 | struct DestinationChannel *dt; | 2749 | struct DestinationChannel *dt; |
2749 | 2750 | ||
2750 | /* parse request */ | ||
2751 | msg = (const struct RedirectToServiceRequestMessage *) message; | ||
2752 | |||
2753 | /* allocate response IP */ | 2751 | /* allocate response IP */ |
2754 | result_af = (int) htonl (msg->result_af); | 2752 | result_af = (int) htonl (msg->result_af); |
2755 | if (GNUNET_OK != | 2753 | if (GNUNET_OK != |
@@ -2759,8 +2757,7 @@ service_redirect_to_service (void *cls, | |||
2759 | &v6)) | 2757 | &v6)) |
2760 | { | 2758 | { |
2761 | GNUNET_break (0); | 2759 | GNUNET_break (0); |
2762 | GNUNET_SERVER_receive_done (client, | 2760 | GNUNET_SERVICE_client_drop (client); |
2763 | GNUNET_SYSERR); | ||
2764 | return; | 2761 | return; |
2765 | } | 2762 | } |
2766 | send_client_reply (client, | 2763 | send_client_reply (client, |
@@ -2772,8 +2769,7 @@ service_redirect_to_service (void *cls, | |||
2772 | /* failure, we're done */ | 2769 | /* failure, we're done */ |
2773 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 2770 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
2774 | _("Failed to allocate IP address for new destination\n")); | 2771 | _("Failed to allocate IP address for new destination\n")); |
2775 | GNUNET_SERVER_receive_done (client, | 2772 | GNUNET_SERVICE_client_continue (client); |
2776 | GNUNET_OK); | ||
2777 | return; | 2773 | return; |
2778 | } | 2774 | } |
2779 | 2775 | ||
@@ -2817,8 +2813,7 @@ service_redirect_to_service (void *cls, | |||
2817 | de->dt_tail, | 2813 | de->dt_tail, |
2818 | dt); | 2814 | dt); |
2819 | /* we're done */ | 2815 | /* we're done */ |
2820 | GNUNET_SERVER_receive_done (client, | 2816 | GNUNET_SERVICE_client_continue (client); |
2821 | GNUNET_OK); | ||
2822 | } | 2817 | } |
2823 | 2818 | ||
2824 | 2819 | ||
@@ -2938,11 +2933,6 @@ cleanup (void *cls) | |||
2938 | GNUNET_HELPER_wait (helper_handle); | 2933 | GNUNET_HELPER_wait (helper_handle); |
2939 | helper_handle = NULL; | 2934 | helper_handle = NULL; |
2940 | } | 2935 | } |
2941 | if (NULL != nc) | ||
2942 | { | ||
2943 | GNUNET_SERVER_notification_context_destroy (nc); | ||
2944 | nc = NULL; | ||
2945 | } | ||
2946 | if (NULL != stats) | 2936 | if (NULL != stats) |
2947 | { | 2937 | { |
2948 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | 2938 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); |
@@ -2954,25 +2944,50 @@ cleanup (void *cls) | |||
2954 | 2944 | ||
2955 | 2945 | ||
2956 | /** | 2946 | /** |
2947 | * Callback called when a client connects to the service. | ||
2948 | * | ||
2949 | * @param cls closure for the service | ||
2950 | * @param c the new client that connected to the service | ||
2951 | * @param mq the message queue used to send messages to the client | ||
2952 | * @return @a c | ||
2953 | */ | ||
2954 | static void * | ||
2955 | client_connect_cb (void *cls, | ||
2956 | struct GNUNET_SERVICE_Client *c, | ||
2957 | struct GNUNET_MQ_Handle *mq) | ||
2958 | { | ||
2959 | return c; | ||
2960 | } | ||
2961 | |||
2962 | |||
2963 | /** | ||
2964 | * Callback called when a client disconnected from the service | ||
2965 | * | ||
2966 | * @param cls closure for the service | ||
2967 | * @param c the client that disconnected | ||
2968 | * @param internal_cls should be equal to @a c | ||
2969 | */ | ||
2970 | static void | ||
2971 | client_disconnect_cb (void *cls, | ||
2972 | struct GNUNET_SERVICE_Client *c, | ||
2973 | void *internal_cls) | ||
2974 | { | ||
2975 | GNUNET_assert (c == internal_cls); | ||
2976 | } | ||
2977 | |||
2978 | |||
2979 | /** | ||
2957 | * Main function that will be run by the scheduler. | 2980 | * Main function that will be run by the scheduler. |
2958 | * | 2981 | * |
2959 | * @param cls closure | 2982 | * @param cls closure |
2960 | * @param server the initialized server | ||
2961 | * @param cfg_ configuration | 2983 | * @param cfg_ configuration |
2984 | * @param service the initialized service | ||
2962 | */ | 2985 | */ |
2963 | static void | 2986 | static void |
2964 | run (void *cls, | 2987 | run (void *cls, |
2965 | struct GNUNET_SERVER_Handle *server, | 2988 | const struct GNUNET_CONFIGURATION_Handle *cfg_, |
2966 | const struct GNUNET_CONFIGURATION_Handle *cfg_) | 2989 | struct GNUNET_SERVICE_Handle *service) |
2967 | { | 2990 | { |
2968 | static const struct GNUNET_SERVER_MessageHandler service_handlers[] = { | ||
2969 | /* callback, cls, type, size */ | ||
2970 | { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0}, | ||
2971 | { &service_redirect_to_service, NULL, | ||
2972 | GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE, | ||
2973 | sizeof (struct RedirectToServiceRequestMessage) }, | ||
2974 | {NULL, NULL, 0, 0} | ||
2975 | }; | ||
2976 | static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = { | 2991 | static const struct GNUNET_CADET_MessageHandler cadet_handlers[] = { |
2977 | { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0}, | 2992 | { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0}, |
2978 | { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0}, | 2993 | { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0}, |
@@ -3128,27 +3143,30 @@ run (void *cls, | |||
3128 | helper_handle = GNUNET_HELPER_start (GNUNET_NO, | 3143 | helper_handle = GNUNET_HELPER_start (GNUNET_NO, |
3129 | "gnunet-helper-vpn", vpn_argv, | 3144 | "gnunet-helper-vpn", vpn_argv, |
3130 | &message_token, NULL, NULL); | 3145 | &message_token, NULL, NULL); |
3131 | nc = GNUNET_SERVER_notification_context_create (server, 1); | ||
3132 | GNUNET_SERVER_add_handlers (server, service_handlers); | ||
3133 | GNUNET_SCHEDULER_add_shutdown (&cleanup, | 3146 | GNUNET_SCHEDULER_add_shutdown (&cleanup, |
3134 | NULL); | 3147 | NULL); |
3135 | } | 3148 | } |
3136 | 3149 | ||
3137 | 3150 | ||
3138 | /** | 3151 | /** |
3139 | * The main function of the VPN service. | 3152 | * Define "main" method using service macro. |
3140 | * | ||
3141 | * @param argc number of arguments from the command line | ||
3142 | * @param argv command line arguments | ||
3143 | * @return 0 ok, 1 on error | ||
3144 | */ | 3153 | */ |
3145 | int | 3154 | GNUNET_SERVICE_MAIN |
3146 | main (int argc, char *const *argv) | 3155 | ("vpn", |
3147 | { | 3156 | GNUNET_SERVICE_OPTION_NONE, |
3148 | return (GNUNET_OK == | 3157 | &run, |
3149 | GNUNET_SERVICE_run (argc, argv, "vpn", | 3158 | &client_connect_cb, |
3150 | GNUNET_SERVICE_OPTION_NONE, | 3159 | &client_disconnect_cb, |
3151 | &run, NULL)) ? global_ret : 1; | 3160 | NULL, |
3152 | } | 3161 | GNUNET_MQ_hd_var_size (client_redirect_to_ip, |
3162 | GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, | ||
3163 | struct RedirectToIpRequestMessage, | ||
3164 | NULL), | ||
3165 | GNUNET_MQ_hd_fixed_size (client_redirect_to_service, | ||
3166 | GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE, | ||
3167 | struct RedirectToServiceRequestMessage, | ||
3168 | NULL), | ||
3169 | GNUNET_MQ_handler_end ()); | ||
3170 | |||
3153 | 3171 | ||
3154 | /* end of gnunet-service-vpn.c */ | 3172 | /* end of gnunet-service-vpn.c */ |