From: Philipp Tölke Date: Mon, 10 Jan 2011 21:41:37 +0000 (+0000) Subject: first shot at gnunet-daemon-exit; not tested yet X-Git-Tag: initial-import-from-subversion-38251~19350 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=4270c2b4b36307511203e4ddcf3d0b5d8e635a99;p=oweals%2Fgnunet.git first shot at gnunet-daemon-exit; not tested yet --- diff --git a/src/vpn/Makefile.am b/src/vpn/Makefile.am index 24986b9d0..1f5f5c5c0 100644 --- a/src/vpn/Makefile.am +++ b/src/vpn/Makefile.am @@ -22,7 +22,7 @@ endif bin_PROGRAMS = \ - gnunet-daemon-vpn gnunet-service-dns $(VPNBIN) $(HIJACKBIN) + gnunet-daemon-exit gnunet-daemon-vpn gnunet-service-dns $(VPNBIN) $(HIJACKBIN) gnunet_helper_vpn_SOURCES = \ @@ -56,6 +56,14 @@ gnunet_service_dns_LDADD = \ $(top_builddir)/src/dht/libgnunetdht.la \ $(GN_LIBINTL) +gnunet_daemon_exit_SOURCES = \ + gnunet-daemon-exit.c +gnunet_daemon_exit_LDADD = \ + $(top_builddir)/src/core/libgnunetcore.la \ + $(top_builddir)/src/statistics/libgnunetstatistics.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) + #check_PROGRAMS = \ # test_XXX diff --git a/src/vpn/gnunet-daemon-exit.c b/src/vpn/gnunet-daemon-exit.c new file mode 100644 index 000000000..68c32eaec --- /dev/null +++ b/src/vpn/gnunet-daemon-exit.c @@ -0,0 +1,296 @@ +/* + This file is part of GNUnet. + (C) 2010 Christian Grothoff + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file vpn/gnunet-daemon-exit.c + * @brief + * @author Philipp Toelke + */ +#include +#include +#include +#include +#include +#include + +#include "gnunet-vpn-packet.h" + +/** + * Final status code. + */ +static int ret; + +/** + * The handle to core + */ +static struct GNUNET_CORE_Handle *core_handle; + +/** + * This hashmap contains the mapping from peer, service-descriptor, + * source-port and destination-port to a socket + */ +static struct GNUNET_CONTAINER_MultiHashMap *udp_connections; + +/** + * FIXME + */ +struct udp_state +{ + struct GNUNET_PeerIdentity peer; + GNUNET_HashCode desc; + short spt; + short dpt; +}; + +/** + * FIXME + */ +struct send_cls +{ + struct GNUNET_NETWORK_Handle *sock; + struct udp_state state; +}; + +/** + * Function scheduled as very last function, cleans up after us + */ +static void +cleanup(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) { + GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); + + if (core_handle != NULL) + { + GNUNET_CORE_disconnect(core_handle); + core_handle = NULL; + } +} + +static size_t +send_udp_service (void *cls, size_t size, void *buf) +{ + struct GNUNET_MessageHeader *hdr = cls; + GNUNET_assert(size >= ntohs(hdr->size)); + + memcpy(buf, cls, ntohs(hdr->size)); + size_t ret = ntohs(hdr->size); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending %d bytes back!\n", ntohs(hdr->size)); + GNUNET_free(cls); + return ret; +} + +void +receive_from_network (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) + { + GNUNET_free(cls); + return; + } + struct send_cls *data = cls; + + char buf[1400]; + + struct sockaddr_in addr_in; + socklen_t addr_len = sizeof(struct sockaddr_in); + ssize_t len = GNUNET_NETWORK_socket_recvfrom (data->sock, buf, 1400, (struct sockaddr*)&addr_in, &addr_len); + + if (len < 0) { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Problem reading from socket: %m\n"); + goto out; + } + + size_t len_udp = len + sizeof (struct udp_pkt); + size_t len_pkt = len_udp + sizeof (struct GNUNET_MessageHeader) + sizeof(GNUNET_HashCode); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending data back: data: %d; udp: %d, pkt:%d\n", len, len_udp, len_pkt); + + struct GNUNET_MessageHeader *hdr = GNUNET_malloc (len_pkt); + GNUNET_HashCode *desc = (GNUNET_HashCode *) (hdr + 1); + struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1); + + hdr->size = htons (len_pkt); + hdr->type = htons (GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK); + + pkt->dpt = htons(data->state.spt); + pkt->spt = addr_in.sin_port; + pkt->len = htons (len_udp); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "UDP from %d to %d\n", ntohs(pkt->spt), ntohs(pkt->dpt)); + /* The chksm can only be computed knowing the ip-addresses */ + + memcpy (desc, &data->state.desc, sizeof (GNUNET_HashCode)); + memcpy (pkt + 1, buf, len); + + GNUNET_CORE_notify_transmit_ready (core_handle, 42, + GNUNET_TIME_relative_divide(GNUNET_CONSTANTS_MAX_CORK_DELAY, 2), + &data->state.peer, len_pkt, + send_udp_service, hdr); + +out: + GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, data->sock, + receive_from_network, cls); +} + +void +send_to_network (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) + return; + struct send_cls *data = cls; + struct udp_pkt *pkt = (struct udp_pkt *) (data + 1); + + struct sockaddr_in a4; + memset(&a4, 0, sizeof(struct sockaddr_in)); + a4.sin_family = AF_INET; + a4.sin_port = htons(data->state.dpt); + memcpy(&a4.sin_addr.s_addr, (char[]){127, 0, 0, 1}, 4); + + GNUNET_NETWORK_socket_sendto (data->sock, pkt + 1, + ntohs (pkt->len) - sizeof (struct udp_pkt), + (struct sockaddr*)&a4, sizeof a4); + + GNUNET_free(cls); + +} + +static int +receive_udp_service (void *cls, const struct GNUNET_PeerIdentity *other, + const struct GNUNET_MessageHeader *message, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received UDP-Packet from peer %s\n", + GNUNET_i2s (other)); + GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1); + struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1); + + /* FIXME -> check acl etc */ + GNUNET_assert (ntohs (pkt->len) == + ntohs (message->size) - + sizeof (struct GNUNET_MessageHeader) - + sizeof (GNUNET_HashCode)); + + size_t state_size = sizeof (struct udp_state); + size_t cls_size = sizeof (struct send_cls) + ntohs (pkt->len); + struct send_cls *send = GNUNET_malloc (cls_size); + struct udp_state *state = &send->state; + unsigned int new = GNUNET_NO; + + memcpy (&state->peer, other, sizeof (struct GNUNET_PeerIdentity)); + memcpy (&state->desc, desc, sizeof (GNUNET_HashCode)); + state->spt = ntohs (pkt->spt); + + /* Hash without the dpt, so that eg tftp works */ + state->dpt = 0; + + memcpy (send + 1, pkt, ntohs (pkt->len)); + + GNUNET_HashCode hash; + GNUNET_CRYPTO_hash (state, state_size, &hash); + + state->dpt = ntohs (pkt->dpt); + + struct GNUNET_NETWORK_Handle *sock = + GNUNET_CONTAINER_multihashmap_get (udp_connections, &hash); + + if (sock == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating new Socket!\n"); + sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0); + GNUNET_assert(sock != NULL); + new = GNUNET_YES; + } + + send->sock = sock; + + GNUNET_CONTAINER_multihashmap_put (udp_connections, &hash, sock, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + + + if (new) + { + struct send_cls *recv = GNUNET_malloc (sizeof (struct send_cls)); + memcpy (recv, send, sizeof (struct send_cls)); + GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock, + receive_from_network, recv); + } + + GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, sock, + send_to_network, send); + + return GNUNET_OK; +} + +/** + * Main function that will be run by the scheduler. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg_) +{ + const static struct GNUNET_CORE_MessageHandler handlers[] = { + {receive_udp_service, GNUNET_MESSAGE_TYPE_SERVICE_UDP, 0}, + {NULL, 0, 0} + }; + core_handle = GNUNET_CORE_connect(cfg_, + 42, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + NULL, + 0, + handlers); + + udp_connections = GNUNET_CONTAINER_multihashmap_create(65536); + GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); +} + +/** + * The main function to obtain template from gnunetd. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, char *const *argv) { + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + return (GNUNET_OK == + GNUNET_PROGRAM_run (argc, + argv, + "gnunet-daemon-exit", + gettext_noop ("help text"), + options, &run, NULL)) ? ret : 1; +} + +/* end of gnunet-daemon-exit.c */ +