aboutsummaryrefslogtreecommitdiff
path: root/src/nat/gnunet-nat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/gnunet-nat.c')
-rw-r--r--src/nat/gnunet-nat.c432
1 files changed, 217 insertions, 215 deletions
diff --git a/src/nat/gnunet-nat.c b/src/nat/gnunet-nat.c
index 6c533374e..d82898f56 100644
--- a/src/nat/gnunet-nat.c
+++ b/src/nat/gnunet-nat.c
@@ -11,12 +11,12 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19*/ 19 */
20 20
21/** 21/**
22 * @file src/nat/gnunet-nat.c 22 * @file src/nat/gnunet-nat.c
@@ -95,13 +95,13 @@ static struct GNUNET_SCHEDULER_Task *rtask;
95 * terminate. 95 * terminate.
96 */ 96 */
97static void 97static void
98test_finished () 98test_finished()
99{ 99{
100 if (NULL != nh) 100 if (NULL != nh)
101 return; 101 return;
102 if (NULL != rtask) 102 if (NULL != rtask)
103 return; 103 return;
104 GNUNET_SCHEDULER_shutdown (); 104 GNUNET_SCHEDULER_shutdown();
105} 105}
106 106
107 107
@@ -119,21 +119,21 @@ test_finished ()
119 * @param addrlen actual length of the @a addr 119 * @param addrlen actual length of the @a addr
120 */ 120 */
121static void 121static void
122address_cb (void *cls, 122address_cb(void *cls,
123 void **app_ctx, 123 void **app_ctx,
124 int add_remove, 124 int add_remove,
125 enum GNUNET_NAT_AddressClass ac, 125 enum GNUNET_NAT_AddressClass ac,
126 const struct sockaddr *addr, 126 const struct sockaddr *addr,
127 socklen_t addrlen) 127 socklen_t addrlen)
128{ 128{
129 (void) cls; 129 (void)cls;
130 (void) app_ctx; 130 (void)app_ctx;
131 131
132 fprintf (stdout, 132 fprintf(stdout,
133 "%s %s (%d)\n", 133 "%s %s (%d)\n",
134 add_remove ? "+" : "-", 134 add_remove ? "+" : "-",
135 GNUNET_a2s (addr, addrlen), 135 GNUNET_a2s(addr, addrlen),
136 (int) ac); 136 (int)ac);
137} 137}
138 138
139 139
@@ -147,13 +147,13 @@ address_cb (void *cls,
147 * @param remote_addrlen actual length of the @a remote_addr 147 * @param remote_addrlen actual length of the @a remote_addr
148 */ 148 */
149static void 149static void
150reversal_cb (void *cls, 150reversal_cb(void *cls,
151 const struct sockaddr *remote_addr, 151 const struct sockaddr *remote_addr,
152 socklen_t remote_addrlen) 152 socklen_t remote_addrlen)
153{ 153{
154 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 154 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
155 "Connection reversal requested by %s\n", 155 "Connection reversal requested by %s\n",
156 GNUNET_a2s (remote_addr, remote_addrlen)); 156 GNUNET_a2s(remote_addr, remote_addrlen));
157} 157}
158 158
159 159
@@ -163,23 +163,23 @@ reversal_cb (void *cls,
163 * @param cls NULL 163 * @param cls NULL
164 */ 164 */
165static void 165static void
166do_shutdown (void *cls) 166do_shutdown(void *cls)
167{ 167{
168 if (NULL != nh) 168 if (NULL != nh)
169 { 169 {
170 GNUNET_NAT_unregister (nh); 170 GNUNET_NAT_unregister(nh);
171 nh = NULL; 171 nh = NULL;
172 } 172 }
173 if (NULL != ls) 173 if (NULL != ls)
174 { 174 {
175 GNUNET_NETWORK_socket_close (ls); 175 GNUNET_NETWORK_socket_close(ls);
176 ls = NULL; 176 ls = NULL;
177 } 177 }
178 if (NULL != rtask) 178 if (NULL != rtask)
179 { 179 {
180 GNUNET_SCHEDULER_cancel (rtask); 180 GNUNET_SCHEDULER_cancel(rtask);
181 rtask = NULL; 181 rtask = NULL;
182 } 182 }
183} 183}
184 184
185 185
@@ -187,45 +187,45 @@ do_shutdown (void *cls)
187 * Task to receive incoming packets for STUN processing. 187 * Task to receive incoming packets for STUN processing.
188 */ 188 */
189static void 189static void
190stun_read_task (void *cls) 190stun_read_task(void *cls)
191{ 191{
192 ssize_t size; 192 ssize_t size;
193 193
194 rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 194 rtask = GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL,
195 ls, 195 ls,
196 &stun_read_task, 196 &stun_read_task,
197 NULL); 197 NULL);
198 size = GNUNET_NETWORK_socket_recvfrom_amount (ls); 198 size = GNUNET_NETWORK_socket_recvfrom_amount(ls);
199 if (size > 0) 199 if (size > 0)
200 { 200 {
201 GNUNET_break (0); 201 GNUNET_break(0);
202 GNUNET_SCHEDULER_shutdown (); 202 GNUNET_SCHEDULER_shutdown();
203 global_ret = 1; 203 global_ret = 1;
204 return; 204 return;
205 } 205 }
206 { 206 {
207 char buf[size + 1]; 207 char buf[size + 1];
208 struct sockaddr_storage sa; 208 struct sockaddr_storage sa;
209 socklen_t salen = sizeof (sa); 209 socklen_t salen = sizeof(sa);
210 ssize_t ret; 210 ssize_t ret;
211 211
212 ret = GNUNET_NETWORK_socket_recvfrom (ls, 212 ret = GNUNET_NETWORK_socket_recvfrom(ls,
213 buf, 213 buf,
214 size + 1, 214 size + 1,
215 (struct sockaddr *) &sa, 215 (struct sockaddr *)&sa,
216 &salen); 216 &salen);
217 if (ret != size) 217 if (ret != size)
218 { 218 {
219 GNUNET_break (0); 219 GNUNET_break(0);
220 GNUNET_SCHEDULER_shutdown (); 220 GNUNET_SCHEDULER_shutdown();
221 global_ret = 1; 221 global_ret = 1;
222 return; 222 return;
223 } 223 }
224 (void) GNUNET_NAT_stun_handle_packet (nh, 224 (void)GNUNET_NAT_stun_handle_packet(nh,
225 (const struct sockaddr *) &sa, 225 (const struct sockaddr *)&sa,
226 salen, 226 salen,
227 buf, 227 buf,
228 ret); 228 ret);
229 } 229 }
230} 230}
231 231
@@ -239,10 +239,10 @@ stun_read_task (void *cls)
239 * @param c configuration 239 * @param c configuration
240 */ 240 */
241static void 241static void
242run (void *cls, 242run(void *cls,
243 char *const *args, 243 char *const *args,
244 const char *cfgfile, 244 const char *cfgfile,
245 const struct GNUNET_CONFIGURATION_Handle *c) 245 const struct GNUNET_CONFIGURATION_Handle *c)
246{ 246{
247 uint8_t af; 247 uint8_t af;
248 struct sockaddr *local_sa; 248 struct sockaddr *local_sa;
@@ -251,154 +251,156 @@ run (void *cls,
251 size_t remote_len; 251 size_t remote_len;
252 252
253 if (use_tcp && use_udp) 253 if (use_tcp && use_udp)
254 { 254 {
255 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Cannot use TCP and UDP\n"); 255 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE, "Cannot use TCP and UDP\n");
256 global_ret = 1; 256 global_ret = 1;
257 return; 257 return;
258 } 258 }
259 proto = 0; 259 proto = 0;
260 if (use_tcp) 260 if (use_tcp)
261 proto = IPPROTO_TCP; 261 proto = IPPROTO_TCP;
262 if (use_udp) 262 if (use_udp)
263 proto = IPPROTO_UDP; 263 proto = IPPROTO_UDP;
264 264
265 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); 265 GNUNET_SCHEDULER_add_shutdown(&do_shutdown, NULL);
266 266
267 if (0 == proto) 267 if (0 == proto)
268 { 268 {
269 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Must specify either TCP or UDP\n"); 269 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE, "Must specify either TCP or UDP\n");
270 global_ret = 1; 270 global_ret = 1;
271 return; 271 return;
272 } 272 }
273 local_len = 0; 273 local_len = 0;
274 local_sa = NULL; 274 local_sa = NULL;
275 remote_len = 0; 275 remote_len = 0;
276 remote_sa = NULL; 276 remote_sa = NULL;
277 if (NULL != local_addr) 277 if (NULL != local_addr)
278 {
279 local_len =
280 (socklen_t) GNUNET_STRINGS_parse_socket_addr (local_addr, &af, &local_sa);
281 if (0 == local_len)
282 { 278 {
283 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 279 local_len =
284 "Invalid socket address `%s'\n", 280 (socklen_t)GNUNET_STRINGS_parse_socket_addr(local_addr, &af, &local_sa);
285 local_addr); 281 if (0 == local_len)
286 goto fail_and_shutdown; 282 {
283 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
284 "Invalid socket address `%s'\n",
285 local_addr);
286 goto fail_and_shutdown;
287 }
287 } 288 }
288 }
289 289
290 if (NULL != remote_addr) 290 if (NULL != remote_addr)
291 {
292 remote_len =
293 GNUNET_STRINGS_parse_socket_addr (remote_addr, &af, &remote_sa);
294 if (0 == remote_len)
295 { 291 {
296 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 292 remote_len =
297 "Invalid socket address `%s'\n", 293 GNUNET_STRINGS_parse_socket_addr(remote_addr, &af, &remote_sa);
298 remote_addr); 294 if (0 == remote_len)
299 goto fail_and_shutdown; 295 {
296 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
297 "Invalid socket address `%s'\n",
298 remote_addr);
299 goto fail_and_shutdown;
300 }
300 } 301 }
301 }
302 302
303 if (NULL != local_addr) 303 if (NULL != local_addr)
304 {
305 if (NULL == section_name)
306 section_name = GNUNET_strdup ("undefined");
307 nh = GNUNET_NAT_register (c,
308 section_name,
309 proto,
310 1,
311 (const struct sockaddr **) &local_sa,
312 &local_len,
313 &address_cb,
314 (listen_reversal) ? &reversal_cb : NULL,
315 NULL);
316 }
317 else if (listen_reversal)
318 {
319 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
320 "Use of `-W` only effective in combination with `-i`\n");
321 goto fail_and_shutdown;
322 }
323
324 if (NULL != remote_addr)
325 {
326 int ret;
327
328 if ((NULL == nh) || (sizeof (struct sockaddr_in) != local_len))
329 { 304 {
330 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 305 if (NULL == section_name)
331 "Require IPv4 local address to initiate connection reversal\n"); 306 section_name = GNUNET_strdup("undefined");
332 goto fail_and_shutdown; 307 nh = GNUNET_NAT_register(c,
308 section_name,
309 proto,
310 1,
311 (const struct sockaddr **)&local_sa,
312 &local_len,
313 &address_cb,
314 (listen_reversal) ? &reversal_cb : NULL,
315 NULL);
333 } 316 }
334 if (sizeof (struct sockaddr_in) != remote_len) 317 else if (listen_reversal)
335 { 318 {
336 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 319 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
337 "Require IPv4 reversal target address\n"); 320 "Use of `-W` only effective in combination with `-i`\n");
338 goto fail_and_shutdown; 321 goto fail_and_shutdown;
339 } 322 }
340 GNUNET_assert (AF_INET == local_sa->sa_family); 323
341 GNUNET_assert (AF_INET == remote_sa->sa_family); 324 if (NULL != remote_addr)
342 ret = GNUNET_NAT_request_reversal (nh,
343 (const struct sockaddr_in *) local_sa,
344 (const struct sockaddr_in *) remote_sa);
345 switch (ret)
346 { 325 {
347 case GNUNET_SYSERR: 326 int ret;
348 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 327
349 "Connection reversal internal error\n"); 328 if ((NULL == nh) || (sizeof(struct sockaddr_in) != local_len))
350 break; 329 {
351 case GNUNET_NO: 330 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
352 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 331 "Require IPv4 local address to initiate connection reversal\n");
353 "Connection reversal unavailable\n"); 332 goto fail_and_shutdown;
354 break; 333 }
355 case GNUNET_OK: 334 if (sizeof(struct sockaddr_in) != remote_len)
356 /* operation in progress */ 335 {
357 break; 336 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
337 "Require IPv4 reversal target address\n");
338 goto fail_and_shutdown;
339 }
340 GNUNET_assert(AF_INET == local_sa->sa_family);
341 GNUNET_assert(AF_INET == remote_sa->sa_family);
342 ret = GNUNET_NAT_request_reversal(nh,
343 (const struct sockaddr_in *)local_sa,
344 (const struct sockaddr_in *)remote_sa);
345 switch (ret)
346 {
347 case GNUNET_SYSERR:
348 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
349 "Connection reversal internal error\n");
350 break;
351
352 case GNUNET_NO:
353 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
354 "Connection reversal unavailable\n");
355 break;
356
357 case GNUNET_OK:
358 /* operation in progress */
359 break;
360 }
358 } 361 }
359 }
360 362
361 if (do_stun) 363 if (do_stun)
362 {
363 if (NULL == local_addr)
364 {
365 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
366 "Require local address to support STUN requests\n");
367 goto fail_and_shutdown;
368 }
369 if (IPPROTO_UDP != proto)
370 { 364 {
371 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "STUN only supported over UDP\n"); 365 if (NULL == local_addr)
372 goto fail_and_shutdown; 366 {
367 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
368 "Require local address to support STUN requests\n");
369 goto fail_and_shutdown;
370 }
371 if (IPPROTO_UDP != proto)
372 {
373 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE, "STUN only supported over UDP\n");
374 goto fail_and_shutdown;
375 }
376 ls = GNUNET_NETWORK_socket_create(af, SOCK_DGRAM, IPPROTO_UDP);
377 if (NULL == ls)
378 {
379 GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE, "Failed to create socket\n");
380 goto fail_and_shutdown;
381 }
382 if (GNUNET_OK != GNUNET_NETWORK_socket_bind(ls, local_sa, local_len))
383 {
384 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
385 "Failed to bind to %s: %s\n",
386 GNUNET_a2s(local_sa, local_len),
387 strerror(errno));
388 goto fail_and_shutdown;
389 }
390 rtask = GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL,
391 ls,
392 &stun_read_task,
393 NULL);
373 } 394 }
374 ls = GNUNET_NETWORK_socket_create (af, SOCK_DGRAM, IPPROTO_UDP); 395 GNUNET_free_non_null(remote_sa);
375 if (NULL == ls) 396 GNUNET_free_non_null(local_sa);
376 { 397 test_finished();
377 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "Failed to create socket\n");
378 goto fail_and_shutdown;
379 }
380 if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ls, local_sa, local_len))
381 {
382 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
383 "Failed to bind to %s: %s\n",
384 GNUNET_a2s (local_sa, local_len),
385 strerror (errno));
386 goto fail_and_shutdown;
387 }
388 rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
389 ls,
390 &stun_read_task,
391 NULL);
392 }
393 GNUNET_free_non_null (remote_sa);
394 GNUNET_free_non_null (local_sa);
395 test_finished ();
396 return; 398 return;
397fail_and_shutdown: 399fail_and_shutdown:
398 global_ret = 1; 400 global_ret = 1;
399 GNUNET_SCHEDULER_shutdown (); 401 GNUNET_SCHEDULER_shutdown();
400 GNUNET_free_non_null (remote_sa); 402 GNUNET_free_non_null(remote_sa);
401 GNUNET_free_non_null (local_sa); 403 GNUNET_free_non_null(local_sa);
402} 404}
403 405
404 406
@@ -410,63 +412,63 @@ fail_and_shutdown:
410 * @return 0 on success, -1 on error 412 * @return 0 on success, -1 on error
411 */ 413 */
412int 414int
413main (int argc, char *const argv[]) 415main(int argc, char *const argv[])
414{ 416{
415 struct GNUNET_GETOPT_CommandLineOption options[] = { 417 struct GNUNET_GETOPT_CommandLineOption options[] = {
416 418 GNUNET_GETOPT_option_string(
417 GNUNET_GETOPT_option_string (
418 'i', 419 'i',
419 "in", 420 "in",
420 "ADDRESS", 421 "ADDRESS",
421 gettext_noop ("which IP and port are we locally using to bind/listen to"), 422 gettext_noop("which IP and port are we locally using to bind/listen to"),
422 &local_addr), 423 &local_addr),
423 424
424 GNUNET_GETOPT_option_string ( 425 GNUNET_GETOPT_option_string(
425 'r', 426 'r',
426 "remote", 427 "remote",
427 "ADDRESS", 428 "ADDRESS",
428 gettext_noop ( 429 gettext_noop(
429 "which remote IP and port should be asked for connection reversal"), 430 "which remote IP and port should be asked for connection reversal"),
430 &remote_addr), 431 &remote_addr),
431 432
432 GNUNET_GETOPT_option_string ( 433 GNUNET_GETOPT_option_string(
433 'S', 434 'S',
434 "section", 435 "section",
435 NULL, 436 NULL,
436 gettext_noop ( 437 gettext_noop(
437 "name of configuration section to find additional options, such as manual host punching data"), 438 "name of configuration section to find additional options, such as manual host punching data"),
438 &section_name), 439 &section_name),
439 440
440 GNUNET_GETOPT_option_flag ('s', 441 GNUNET_GETOPT_option_flag('s',
441 "stun", 442 "stun",
442 gettext_noop ("enable STUN processing"), 443 gettext_noop("enable STUN processing"),
443 &do_stun), 444 &do_stun),
444 445
445 GNUNET_GETOPT_option_flag ('t', "tcp", gettext_noop ("use TCP"), &use_tcp), 446 GNUNET_GETOPT_option_flag('t', "tcp", gettext_noop("use TCP"), &use_tcp),
446 447
447 GNUNET_GETOPT_option_flag ('u', "udp", gettext_noop ("use UDP"), &use_udp), 448 GNUNET_GETOPT_option_flag('u', "udp", gettext_noop("use UDP"), &use_udp),
448 449
449 GNUNET_GETOPT_option_flag ('W', 450 GNUNET_GETOPT_option_flag('W',
450 "watch", 451 "watch",
451 gettext_noop ( 452 gettext_noop(
452 "watch for connection reversal requests"), 453 "watch for connection reversal requests"),
453 &listen_reversal), 454 &listen_reversal),
454 GNUNET_GETOPT_OPTION_END}; 455 GNUNET_GETOPT_OPTION_END
456 };
455 457
456 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 458 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
457 return 2; 459 return 2;
458 if (GNUNET_OK != 460 if (GNUNET_OK !=
459 GNUNET_PROGRAM_run (argc, 461 GNUNET_PROGRAM_run(argc,
460 argv, 462 argv,
461 "gnunet-nat [options]", 463 "gnunet-nat [options]",
462 _ ("GNUnet NAT traversal autoconfigure daemon"), 464 _("GNUnet NAT traversal autoconfigure daemon"),
463 options, 465 options,
464 &run, 466 &run,
465 NULL)) 467 NULL))
466 { 468 {
467 global_ret = 1; 469 global_ret = 1;
468 } 470 }
469 GNUNET_free ((void *) argv); 471 GNUNET_free((void *)argv);
470 return global_ret; 472 return global_ret;
471} 473}
472 474