summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-10-21 22:24:47 +0000
committerChristian Grothoff <christian@grothoff.org>2016-10-21 22:24:47 +0000
commit4ab32191fbd53680ff5192fc7d53a21c67ae772d (patch)
treeb95df8e4b5db6938c1040f156f12fcc99172452c
parenta7e626e2a613e86f3ebf6ff6f8cfec1cc2a9758b (diff)
downloadgnunet-4ab32191fbd53680ff5192fc7d53a21c67ae772d.tar.gz
gnunet-4ab32191fbd53680ff5192fc7d53a21c67ae772d.zip
eliminate last residue of old service api in ARM
-rw-r--r--src/arm/gnunet-service-arm.c395
1 files changed, 391 insertions, 4 deletions
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c
index 5bf823656..7af3659a4 100644
--- a/src/arm/gnunet-service-arm.c
+++ b/src/arm/gnunet-service-arm.c
@@ -29,6 +29,11 @@
29#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
30#include "arm.h" 30#include "arm.h"
31 31
32#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
33
34#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
35
36
32#if HAVE_WAIT4 37#if HAVE_WAIT4
33/** 38/**
34 * Name of the file for writing resource utilization summaries to. 39 * Name of the file for writing resource utilization summaries to.
@@ -260,6 +265,388 @@ static struct GNUNET_NotificationContext *notifier;
260 265
261 266
262/** 267/**
268 * Add the given UNIX domain path as an address to the
269 * list (as the first entry).
270 *
271 * @param saddrs array to update
272 * @param saddrlens where to store the address length
273 * @param unixpath path to add
274 * @param abstract #GNUNET_YES to add an abstract UNIX domain socket. This
275 * parameter is ignore on systems other than LINUX
276 */
277static void
278add_unixpath (struct sockaddr **saddrs,
279 socklen_t *saddrlens,
280 const char *unixpath,
281 int abstract)
282{
283#ifdef AF_UNIX
284 struct sockaddr_un *un;
285
286 un = GNUNET_new (struct sockaddr_un);
287 un->sun_family = AF_UNIX;
288 strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1);
289#ifdef LINUX
290 if (GNUNET_YES == abstract)
291 un->sun_path[0] = '\0';
292#endif
293#if HAVE_SOCKADDR_IN_SIN_LEN
294 un->sun_len = (u_char) sizeof (struct sockaddr_un);
295#endif
296 *saddrs = (struct sockaddr *) un;
297 *saddrlens = sizeof (struct sockaddr_un);
298#else
299 /* this function should never be called
300 * unless AF_UNIX is defined! */
301 GNUNET_assert (0);
302#endif
303}
304
305
306/**
307 * Get the list of addresses that a server for the given service
308 * should bind to.
309 *
310 * @param service_name name of the service
311 * @param cfg configuration (which specifies the addresses)
312 * @param addrs set (call by reference) to an array of pointers to the
313 * addresses the server should bind to and listen on; the
314 * array will be NULL-terminated (on success)
315 * @param addr_lens set (call by reference) to an array of the lengths
316 * of the respective `struct sockaddr` struct in the @a addrs
317 * array (on success)
318 * @return number of addresses found on success,
319 * #GNUNET_SYSERR if the configuration
320 * did not specify reasonable finding information or
321 * if it specified a hostname that could not be resolved;
322 * #GNUNET_NO if the number of addresses configured is
323 * zero (in this case, `*addrs` and `*addr_lens` will be
324 * set to NULL).
325 */
326static int
327get_server_addresses (const char *service_name,
328 const struct GNUNET_CONFIGURATION_Handle *cfg,
329 struct sockaddr ***addrs,
330 socklen_t ** addr_lens)
331{
332 int disablev6;
333 struct GNUNET_NETWORK_Handle *desc;
334 unsigned long long port;
335 char *unixpath;
336 struct addrinfo hints;
337 struct addrinfo *res;
338 struct addrinfo *pos;
339 struct addrinfo *next;
340 unsigned int i;
341 int resi;
342 int ret;
343 int abstract;
344 struct sockaddr **saddrs;
345 socklen_t *saddrlens;
346 char *hostname;
347
348 *addrs = NULL;
349 *addr_lens = NULL;
350 desc = NULL;
351 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
352 {
353 if (GNUNET_SYSERR ==
354 (disablev6 =
355 GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6")))
356 return GNUNET_SYSERR;
357 }
358 else
359 disablev6 = GNUNET_NO;
360
361 if (! disablev6)
362 {
363 /* probe IPv6 support */
364 desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
365 if (NULL == desc)
366 {
367 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
368 (EACCES == errno))
369 {
370 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
371 return GNUNET_SYSERR;
372 }
373 LOG (GNUNET_ERROR_TYPE_INFO,
374 _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
375 service_name, STRERROR (errno));
376 disablev6 = GNUNET_YES;
377 }
378 else
379 {
380 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
381 desc = NULL;
382 }
383 }
384
385 port = 0;
386 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
387 {
388 if (GNUNET_OK !=
389 GNUNET_CONFIGURATION_get_value_number (cfg, service_name,
390 "PORT", &port))
391 {
392 LOG (GNUNET_ERROR_TYPE_ERROR,
393 _("Require valid port number for service `%s' in configuration!\n"),
394 service_name);
395 }
396 if (port > 65535)
397 {
398 LOG (GNUNET_ERROR_TYPE_ERROR,
399 _("Require valid port number for service `%s' in configuration!\n"),
400 service_name);
401 return GNUNET_SYSERR;
402 }
403 }
404
405 if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
406 {
407 GNUNET_break (GNUNET_OK ==
408 GNUNET_CONFIGURATION_get_value_string (cfg, service_name,
409 "BINDTO", &hostname));
410 }
411 else
412 hostname = NULL;
413
414 unixpath = NULL;
415 abstract = GNUNET_NO;
416#ifdef AF_UNIX
417 if ((GNUNET_YES ==
418 GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
419 (GNUNET_OK ==
420 GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH",
421 &unixpath)) &&
422 (0 < strlen (unixpath)))
423 {
424 /* probe UNIX support */
425 struct sockaddr_un s_un;
426
427 if (strlen (unixpath) >= sizeof (s_un.sun_path))
428 {
429 LOG (GNUNET_ERROR_TYPE_WARNING,
430 _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
431 (unsigned long long) sizeof (s_un.sun_path));
432 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
433 LOG (GNUNET_ERROR_TYPE_INFO,
434 _("Using `%s' instead\n"),
435 unixpath);
436 }
437#ifdef LINUX
438 abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
439 "TESTING",
440 "USE_ABSTRACT_SOCKETS");
441 if (GNUNET_SYSERR == abstract)
442 abstract = GNUNET_NO;
443#endif
444 if ((GNUNET_YES != abstract)
445 && (GNUNET_OK !=
446 GNUNET_DISK_directory_create_for_file (unixpath)))
447 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
448 "mkdir",
449 unixpath);
450 }
451 if (NULL != unixpath)
452 {
453 desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
454 if (NULL == desc)
455 {
456 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
457 (EACCES == errno))
458 {
459 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket");
460 GNUNET_free_non_null (hostname);
461 GNUNET_free (unixpath);
462 return GNUNET_SYSERR;
463 }
464 LOG (GNUNET_ERROR_TYPE_INFO,
465 _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
466 service_name,
467 STRERROR (errno));
468 GNUNET_free (unixpath);
469 unixpath = NULL;
470 }
471 else
472 {
473 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc));
474 desc = NULL;
475 }
476 }
477#endif
478
479 if ((0 == port) && (NULL == unixpath))
480 {
481 LOG (GNUNET_ERROR_TYPE_ERROR,
482 _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
483 service_name);
484 GNUNET_free_non_null (hostname);
485 return GNUNET_SYSERR;
486 }
487 if (0 == port)
488 {
489 saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *));
490 saddrlens = GNUNET_malloc (2 * sizeof (socklen_t));
491 add_unixpath (saddrs, saddrlens, unixpath, abstract);
492 GNUNET_free_non_null (unixpath);
493 GNUNET_free_non_null (hostname);
494 *addrs = saddrs;
495 *addr_lens = saddrlens;
496 return 1;
497 }
498
499 if (NULL != hostname)
500 {
501 LOG (GNUNET_ERROR_TYPE_DEBUG,
502 "Resolving `%s' since that is where `%s' will bind to.\n",
503 hostname,
504 service_name);
505 memset (&hints, 0, sizeof (struct addrinfo));
506 if (disablev6)
507 hints.ai_family = AF_INET;
508 hints.ai_protocol = IPPROTO_TCP;
509 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
510 (NULL == res))
511 {
512 LOG (GNUNET_ERROR_TYPE_ERROR,
513 _("Failed to resolve `%s': %s\n"),
514 hostname,
515 gai_strerror (ret));
516 GNUNET_free (hostname);
517 GNUNET_free_non_null (unixpath);
518 return GNUNET_SYSERR;
519 }
520 next = res;
521 i = 0;
522 while (NULL != (pos = next))
523 {
524 next = pos->ai_next;
525 if ((disablev6) && (pos->ai_family == AF_INET6))
526 continue;
527 i++;
528 }
529 if (0 == i)
530 {
531 LOG (GNUNET_ERROR_TYPE_ERROR,
532 _("Failed to find %saddress for `%s'.\n"),
533 disablev6 ? "IPv4 " : "",
534 hostname);
535 freeaddrinfo (res);
536 GNUNET_free (hostname);
537 GNUNET_free_non_null (unixpath);
538 return GNUNET_SYSERR;
539 }
540 resi = i;
541 if (NULL != unixpath)
542 resi++;
543 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
544 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
545 i = 0;
546 if (NULL != unixpath)
547 {
548 add_unixpath (saddrs, saddrlens, unixpath, abstract);
549 i++;
550 }
551 next = res;
552 while (NULL != (pos = next))
553 {
554 next = pos->ai_next;
555 if ((disablev6) && (AF_INET6 == pos->ai_family))
556 continue;
557 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
558 continue; /* not TCP */
559 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
560 continue; /* huh? */
561 LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
562 service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
563 if (AF_INET == pos->ai_family)
564 {
565 GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
566 saddrlens[i] = pos->ai_addrlen;
567 saddrs[i] = GNUNET_malloc (saddrlens[i]);
568 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
569 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
570 }
571 else
572 {
573 GNUNET_assert (AF_INET6 == pos->ai_family);
574 GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
575 saddrlens[i] = pos->ai_addrlen;
576 saddrs[i] = GNUNET_malloc (saddrlens[i]);
577 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
578 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
579 }
580 i++;
581 }
582 GNUNET_free (hostname);
583 freeaddrinfo (res);
584 resi = i;
585 }
586 else
587 {
588 /* will bind against everything, just set port */
589 if (disablev6)
590 {
591 /* V4-only */
592 resi = 1;
593 if (NULL != unixpath)
594 resi++;
595 i = 0;
596 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
597 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
598 if (NULL != unixpath)
599 {
600 add_unixpath (saddrs, saddrlens, unixpath, abstract);
601 i++;
602 }
603 saddrlens[i] = sizeof (struct sockaddr_in);
604 saddrs[i] = GNUNET_malloc (saddrlens[i]);
605#if HAVE_SOCKADDR_IN_SIN_LEN
606 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
607#endif
608 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
609 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
610 }
611 else
612 {
613 /* dual stack */
614 resi = 2;
615 if (NULL != unixpath)
616 resi++;
617 saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *));
618 saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t));
619 i = 0;
620 if (NULL != unixpath)
621 {
622 add_unixpath (saddrs, saddrlens, unixpath, abstract);
623 i++;
624 }
625 saddrlens[i] = sizeof (struct sockaddr_in6);
626 saddrs[i] = GNUNET_malloc (saddrlens[i]);
627#if HAVE_SOCKADDR_IN_SIN_LEN
628 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
629#endif
630 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
631 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
632 i++;
633 saddrlens[i] = sizeof (struct sockaddr_in);
634 saddrs[i] = GNUNET_malloc (saddrlens[i]);
635#if HAVE_SOCKADDR_IN_SIN_LEN
636 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
637#endif
638 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
639 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
640 }
641 }
642 GNUNET_free_non_null (unixpath);
643 *addrs = saddrs;
644 *addr_lens = saddrlens;
645 return resi;
646}
647
648
649/**
263 * Signal our client that we will start or stop the 650 * Signal our client that we will start or stop the
264 * service. 651 * service.
265 * 652 *
@@ -1619,10 +2006,10 @@ setup_service (void *cls,
1619 "AUTOSTART")) 2006 "AUTOSTART"))
1620 return; 2007 return;
1621 } 2008 }
1622 if (0 >= (ret = GNUNET_SERVICE_get_server_addresses (section, 2009 if (0 >= (ret = get_server_addresses (section,
1623 cfg, 2010 cfg,
1624 &addrs, 2011 &addrs,
1625 &addr_lens))) 2012 &addr_lens)))
1626 return; 2013 return;
1627 /* this will free (or capture) addrs[i] */ 2014 /* this will free (or capture) addrs[i] */
1628 for (i = 0; i < ret; i++) 2015 for (i = 0; i < ret; i++)