2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff
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
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file vpn/gnunet-daemon-exit.c
24 * @author Philipp Toelke
27 #include <gnunet_common.h>
28 #include <gnunet_program_lib.h>
29 #include <gnunet_protocols.h>
30 #include <gnunet_mesh_service.h>
31 #include <gnunet_constants.h>
33 #include "gnunet-vpn-packet.h"
43 static struct GNUNET_MESH_Handle *mesh_handle;
46 * This hashmap contains the mapping from peer, service-descriptor,
47 * source-port and destination-port to a socket
49 static struct GNUNET_CONTAINER_MultiHashMap *udp_connections;
56 struct GNUNET_PeerIdentity peer;
57 struct GNUNET_MESH_Tunnel *tunnel;
68 struct GNUNET_NETWORK_Handle *sock;
69 struct udp_state state;
73 * Function scheduled as very last function, cleans up after us
76 cleanup(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tskctx) {
77 GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN));
79 if (mesh_handle != NULL)
81 GNUNET_MESH_disconnect(mesh_handle);
87 send_udp_service (void *cls, size_t size, void *buf)
89 struct GNUNET_MessageHeader *hdr = cls;
90 GNUNET_assert(size >= ntohs(hdr->size));
92 memcpy(buf, cls, ntohs(hdr->size));
93 size_t ret = ntohs(hdr->size);
94 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending %d bytes back!\n", ntohs(hdr->size));
100 receive_from_network (void *cls,
101 const struct GNUNET_SCHEDULER_TaskContext *tc)
103 if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
108 struct send_cls *data = cls;
112 struct sockaddr_in addr_in;
113 socklen_t addr_len = sizeof(struct sockaddr_in);
114 ssize_t len = GNUNET_NETWORK_socket_recvfrom (data->sock, buf, 1400, (struct sockaddr*)&addr_in, &addr_len);
117 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Problem reading from socket: %m\n");
121 size_t len_udp = len + sizeof (struct udp_pkt);
122 size_t len_pkt = len_udp + sizeof (struct GNUNET_MessageHeader) + sizeof(GNUNET_HashCode);
123 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending data back: data: %d; udp: %d, pkt:%d\n", len, len_udp, len_pkt);
125 struct GNUNET_MessageHeader *hdr = GNUNET_malloc (len_pkt);
126 GNUNET_HashCode *desc = (GNUNET_HashCode *) (hdr + 1);
127 struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1);
129 hdr->size = htons (len_pkt);
130 hdr->type = htons (GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK);
132 pkt->dpt = htons(data->state.spt);
133 pkt->spt = addr_in.sin_port;
134 pkt->len = htons (len_udp);
135 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "UDP from %d to %d\n", ntohs(pkt->spt), ntohs(pkt->dpt));
136 /* The chksm can only be computed knowing the ip-addresses */
138 memcpy (desc, &data->state.desc, sizeof (GNUNET_HashCode));
139 memcpy (pkt + 1, buf, len);
141 GNUNET_MESH_notify_transmit_ready (data->state.tunnel, 42,
143 GNUNET_TIME_relative_divide(GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
145 send_udp_service, hdr);
148 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, data->sock,
149 receive_from_network, cls);
153 send_to_network (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
155 if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)
157 struct send_cls *data = cls;
158 struct udp_pkt *pkt = (struct udp_pkt *) (data + 1);
160 struct sockaddr_in a4;
161 memset(&a4, 0, sizeof(struct sockaddr_in));
162 a4.sin_family = AF_INET;
163 a4.sin_port = htons(data->state.dpt);
164 GNUNET_assert (1 == inet_pton (AF_INET, "127.0.0.1", &a4.sin_addr));
165 GNUNET_NETWORK_socket_sendto (data->sock, pkt + 1,
166 ntohs (pkt->len) - sizeof (struct udp_pkt),
167 (struct sockaddr*)&a4, sizeof a4);
174 * The messages are one GNUNET_HashCode for the service, followed by a struct udp_pkt
177 receive_udp_service (void *cls,
178 struct GNUNET_MESH_Tunnel *tunnel,
180 const struct GNUNET_MessageHeader *message,
181 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
183 GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
184 struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1);
186 /* FIXME -> check acl etc */
187 GNUNET_assert (ntohs (pkt->len) ==
188 ntohs (message->size) -
189 sizeof (struct GNUNET_MessageHeader) -
190 sizeof (GNUNET_HashCode));
192 size_t state_size = sizeof (struct udp_state);
193 size_t cls_size = sizeof (struct send_cls) + ntohs (pkt->len);
194 struct send_cls *send = GNUNET_malloc (cls_size);
195 struct udp_state *state = &send->state;
196 unsigned int new = GNUNET_NO;
198 state->tunnel = tunnel;
199 memcpy (&state->desc, desc, sizeof (GNUNET_HashCode));
200 state->spt = ntohs (pkt->spt);
202 /* Hash without the dpt, so that eg tftp works */
205 memcpy (send + 1, pkt, ntohs (pkt->len));
207 GNUNET_HashCode hash;
208 GNUNET_CRYPTO_hash (state, state_size, &hash);
210 state->dpt = ntohs (pkt->dpt);
212 struct GNUNET_NETWORK_Handle *sock =
213 GNUNET_CONTAINER_multihashmap_get (udp_connections, &hash);
217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating new Socket!\n");
218 sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0);
219 GNUNET_assert(sock != NULL);
225 GNUNET_CONTAINER_multihashmap_put (udp_connections, &hash, sock,
226 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
231 struct send_cls *recv = GNUNET_malloc (sizeof (struct send_cls));
232 memcpy (recv, send, sizeof (struct send_cls));
233 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock,
234 receive_from_network, recv);
237 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, sock,
238 send_to_network, send);
244 * @brief Main function that will be run by the scheduler.
247 * @param args remaining command-line arguments
248 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
249 * @param cfg_ configuration
255 const struct GNUNET_CONFIGURATION_Handle *cfg_)
257 const static struct GNUNET_MESH_MessageHandler handlers[] = {
258 {receive_udp_service, GNUNET_MESSAGE_TYPE_SERVICE_UDP, 0},
261 mesh_handle = GNUNET_MESH_connect(cfg_,
266 udp_connections = GNUNET_CONTAINER_multihashmap_create(65536);
267 GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
271 * The main function to obtain template from gnunetd.
273 * @param argc number of arguments from the command line
274 * @param argv command line arguments
275 * @return 0 ok, 1 on error
278 main (int argc, char *const *argv) {
279 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
280 GNUNET_GETOPT_OPTION_END
284 GNUNET_PROGRAM_run (argc,
286 "gnunet-daemon-exit",
287 gettext_noop ("help text"),
288 options, &run, NULL)) ? ret : 1;
291 /* end of gnunet-daemon-exit.c */