diff options
Diffstat (limited to 'src/util/service.c')
-rw-r--r-- | src/util/service.c | 179 |
1 files changed, 117 insertions, 62 deletions
diff --git a/src/util/service.c b/src/util/service.c index 034cff170..af17a7f3e 100644 --- a/src/util/service.c +++ b/src/util/service.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #include "gnunet_server_lib.h" | 35 | #include "gnunet_server_lib.h" |
36 | #include "gnunet_service_lib.h" | 36 | #include "gnunet_service_lib.h" |
37 | 37 | ||
38 | #define DEBUG_SERVICE GNUNET_NO | ||
39 | |||
38 | /* ******************* access control ******************** */ | 40 | /* ******************* access control ******************** */ |
39 | 41 | ||
40 | /** | 42 | /** |
@@ -433,9 +435,9 @@ struct GNUNET_SERVICE_Context | |||
433 | struct GNUNET_SCHEDULER_Handle *sched; | 435 | struct GNUNET_SCHEDULER_Handle *sched; |
434 | 436 | ||
435 | /** | 437 | /** |
436 | * Address to bind to. | 438 | * NULL-terminated array of addresses to bind to. |
437 | */ | 439 | */ |
438 | struct sockaddr *addr; | 440 | struct sockaddr **addrs; |
439 | 441 | ||
440 | /** | 442 | /** |
441 | * Name of our service. | 443 | * Name of our service. |
@@ -519,9 +521,9 @@ struct GNUNET_SERVICE_Context | |||
519 | enum GNUNET_SERVICE_Options options; | 521 | enum GNUNET_SERVICE_Options options; |
520 | 522 | ||
521 | /** | 523 | /** |
522 | * Length of addr. | 524 | * Array of the lengths of the entries in addrs. |
523 | */ | 525 | */ |
524 | socklen_t addrlen; | 526 | socklen_t * addrlens; |
525 | 527 | ||
526 | }; | 528 | }; |
527 | 529 | ||
@@ -766,8 +768,10 @@ setup_service (struct GNUNET_SERVICE_Context *sctx) | |||
766 | struct addrinfo hints; | 768 | struct addrinfo hints; |
767 | struct addrinfo *res; | 769 | struct addrinfo *res; |
768 | struct addrinfo *pos; | 770 | struct addrinfo *pos; |
771 | struct addrinfo *next; | ||
769 | int ret; | 772 | int ret; |
770 | int tolerant; | 773 | int tolerant; |
774 | unsigned int i; | ||
771 | struct GNUNET_NETWORK_Handle *desc; | 775 | struct GNUNET_NETWORK_Handle *desc; |
772 | 776 | ||
773 | if (GNUNET_CONFIGURATION_have_value (sctx->cfg, | 777 | if (GNUNET_CONFIGURATION_have_value (sctx->cfg, |
@@ -884,6 +888,12 @@ setup_service (struct GNUNET_SERVICE_Context *sctx) | |||
884 | 888 | ||
885 | if (hostname != NULL) | 889 | if (hostname != NULL) |
886 | { | 890 | { |
891 | #if DEBUG_SERVICE | ||
892 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
893 | "Resolving `%s' since that is where `%s' will bind to.\n", | ||
894 | hostname, | ||
895 | sctx->serviceName); | ||
896 | #endif | ||
887 | memset (&hints, 0, sizeof (struct addrinfo)); | 897 | memset (&hints, 0, sizeof (struct addrinfo)); |
888 | if (disablev6) | 898 | if (disablev6) |
889 | hints.ai_family = AF_INET; | 899 | hints.ai_family = AF_INET; |
@@ -896,13 +906,16 @@ setup_service (struct GNUNET_SERVICE_Context *sctx) | |||
896 | GNUNET_free (hostname); | 906 | GNUNET_free (hostname); |
897 | return GNUNET_SYSERR; | 907 | return GNUNET_SYSERR; |
898 | } | 908 | } |
899 | pos = res; | 909 | next = res; |
900 | while ((NULL != pos) && | 910 | i = 0; |
901 | (((disablev6) && | 911 | while (NULL != (pos = next)) |
902 | (pos->ai_family != AF_INET)) || | 912 | { |
903 | ((pos->ai_family != AF_INET) && (pos->ai_family != AF_INET6)))) | 913 | next = pos->ai_next; |
904 | pos = pos->ai_next; | 914 | if ( (disablev6) && (pos->ai_family == AF_INET6)) |
905 | if (pos == NULL) | 915 | continue; |
916 | i++; | ||
917 | } | ||
918 | if (0 == i) | ||
906 | { | 919 | { |
907 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 920 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
908 | _("Failed to find %saddress for `%s'.\n"), | 921 | _("Failed to find %saddress for `%s'.\n"), |
@@ -911,32 +924,42 @@ setup_service (struct GNUNET_SERVICE_Context *sctx) | |||
911 | GNUNET_free (hostname); | 924 | GNUNET_free (hostname); |
912 | return GNUNET_SYSERR; | 925 | return GNUNET_SYSERR; |
913 | } | 926 | } |
927 | sctx->addrs = GNUNET_malloc ((i+1) * sizeof(struct sockaddr*)); | ||
928 | sctx->addrlens = GNUNET_malloc ((i+1) * sizeof (socklen_t)); | ||
929 | i = 0; | ||
930 | next = res; | ||
931 | while (NULL != (pos = next)) | ||
932 | { | ||
933 | next = pos->ai_next; | ||
934 | if ( (disablev6) && (pos->ai_family == AF_INET6)) | ||
935 | continue; | ||
936 | #if DEBUG_SERVICE | ||
937 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
938 | "Service `%s' will bind to `%s'\n", | ||
939 | sctx->serviceName, | ||
940 | GNUNET_a2s (pos->ai_addr, | ||
941 | pos->ai_addrlen)); | ||
942 | #endif | ||
943 | if (pos->ai_family == AF_INET) | ||
944 | { | ||
945 | GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in)); | ||
946 | sctx->addrlens[i] = pos->ai_addrlen; | ||
947 | sctx->addrs[i] = GNUNET_malloc (sctx->addrlens[i]); | ||
948 | memcpy (sctx->addrs[i], pos->ai_addr, sctx->addrlens[i]); | ||
949 | ((struct sockaddr_in *) sctx->addrs[i])->sin_port = htons (port); | ||
950 | } | ||
951 | else | ||
952 | { | ||
953 | GNUNET_assert (pos->ai_family == AF_INET6); | ||
954 | GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in6)); | ||
955 | sctx->addrlens[i] = pos->ai_addrlen; | ||
956 | sctx->addrs[i] = GNUNET_malloc (sctx->addrlens[i]); | ||
957 | memcpy (sctx->addrs[i], pos->ai_addr, sctx->addrlens[i]); | ||
958 | ((struct sockaddr_in6 *) sctx->addrs[i])->sin6_port = htons (port); | ||
959 | } | ||
960 | i++; | ||
961 | } | ||
914 | GNUNET_free (hostname); | 962 | GNUNET_free (hostname); |
915 | if (pos->ai_family == AF_INET) | ||
916 | { | ||
917 | GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in)); | ||
918 | sctx->addrlen = pos->ai_addrlen; | ||
919 | sctx->addr = GNUNET_malloc (sctx->addrlen); | ||
920 | memcpy (sctx->addr, res->ai_addr, sctx->addrlen); | ||
921 | ((struct sockaddr_in *) sctx->addr)->sin_port = htons (port); | ||
922 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
923 | _ | ||
924 | ("Configured to bind to %s address; %s connections to this service will fail!\n"), | ||
925 | "IPv4", "IPv6"); | ||
926 | } | ||
927 | else | ||
928 | { | ||
929 | GNUNET_assert (pos->ai_family == AF_INET6); | ||
930 | GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in6)); | ||
931 | sctx->addrlen = pos->ai_addrlen; | ||
932 | sctx->addr = GNUNET_malloc (sctx->addrlen); | ||
933 | memcpy (sctx->addr, res->ai_addr, sctx->addrlen); | ||
934 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
935 | _ | ||
936 | ("Configured to bind to %s address; %s connections to this service will fail!\n"), | ||
937 | "IPv6", "IPv4"); | ||
938 | ((struct sockaddr_in6 *) sctx->addr)->sin6_port = htons (port); | ||
939 | } | ||
940 | freeaddrinfo (res); | 963 | freeaddrinfo (res); |
941 | } | 964 | } |
942 | else | 965 | else |
@@ -945,28 +968,38 @@ setup_service (struct GNUNET_SERVICE_Context *sctx) | |||
945 | if (disablev6) | 968 | if (disablev6) |
946 | { | 969 | { |
947 | /* V4-only */ | 970 | /* V4-only */ |
948 | sctx->addrlen = sizeof (struct sockaddr_in); | 971 | sctx->addrs = GNUNET_malloc (2 * sizeof(struct sockaddr*)); |
949 | sctx->addr = GNUNET_malloc (sctx->addrlen); | 972 | sctx->addrlens = GNUNET_malloc (2 * sizeof (socklen_t)); |
973 | sctx->addrlens[0] = sizeof (struct sockaddr_in); | ||
974 | sctx->addrs[0] = GNUNET_malloc (sctx->addrlens[0]); | ||
950 | #if HAVE_SOCKADDR_IN_SIN_LEN | 975 | #if HAVE_SOCKADDR_IN_SIN_LEN |
951 | ((struct sockaddr_in *) sctx->addr)->sin_len = sctx->addrlen; | 976 | ((struct sockaddr_in *) sctx->addrs[0])->sin_len = sctx->addrlens[0]; |
952 | #endif | 977 | #endif |
953 | ((struct sockaddr_in *) sctx->addr)->sin_family = AF_INET; | 978 | ((struct sockaddr_in *) sctx->addrs[0])->sin_family = AF_INET; |
954 | ((struct sockaddr_in *) sctx->addr)->sin_port = htons (port); | 979 | ((struct sockaddr_in *) sctx->addrs[0])->sin_port = htons (port); |
955 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
956 | _ | ||
957 | ("Configured to bind to %s address; %s connections to this service will fail!\n"), | ||
958 | "IPv4", "IPv6"); | ||
959 | } | 980 | } |
960 | else | 981 | else |
961 | { | 982 | { |
962 | /* dual stack */ | 983 | /* dual stack */ |
963 | sctx->addrlen = sizeof (struct sockaddr_in6); | 984 | sctx->addrs = GNUNET_malloc (3 * sizeof(struct sockaddr*)); |
964 | sctx->addr = GNUNET_malloc (sctx->addrlen); | 985 | sctx->addrlens = GNUNET_malloc (3 * sizeof (socklen_t)); |
986 | |||
987 | sctx->addrlens[0] = sizeof (struct sockaddr_in6); | ||
988 | sctx->addrs[0] = GNUNET_malloc (sctx->addrlens[0]); | ||
989 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
990 | ((struct sockaddr_in6 *) sctx->addrs[0])->sin6_len = sctx->addrlen[0]; | ||
991 | #endif | ||
992 | ((struct sockaddr_in6 *) sctx->addrs[0])->sin6_family = AF_INET6; | ||
993 | ((struct sockaddr_in6 *) sctx->addrs[0])->sin6_port = htons (port); | ||
994 | |||
995 | sctx->addrlens[1] = sizeof (struct sockaddr_in); | ||
996 | sctx->addrs[1] = GNUNET_malloc (sctx->addrlens[1]); | ||
965 | #if HAVE_SOCKADDR_IN_SIN_LEN | 997 | #if HAVE_SOCKADDR_IN_SIN_LEN |
966 | ((struct sockaddr_in6 *) sctx->addr)->sin6_len = sctx->addrlen; | 998 | ((struct sockaddr_in *) sctx->addrs[1])->sin_len = sctx->addrlens[1]; |
967 | #endif | 999 | #endif |
968 | ((struct sockaddr_in6 *) sctx->addr)->sin6_family = AF_INET6; | 1000 | ((struct sockaddr_in *) sctx->addrs[1])->sin_family = AF_INET; |
969 | ((struct sockaddr_in6 *) sctx->addr)->sin6_port = htons (port); | 1001 | ((struct sockaddr_in *) sctx->addrs[1])->sin_port = htons (port); |
1002 | |||
970 | } | 1003 | } |
971 | } | 1004 | } |
972 | sctx->maxbuf = (size_t) maxbuf; | 1005 | sctx->maxbuf = (size_t) maxbuf; |
@@ -1090,15 +1123,21 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1090 | sctx->server = GNUNET_SERVER_create (tc->sched, | 1123 | sctx->server = GNUNET_SERVER_create (tc->sched, |
1091 | &check_access, | 1124 | &check_access, |
1092 | sctx, | 1125 | sctx, |
1093 | sctx->addr, | 1126 | sctx->addrs, |
1094 | sctx->addrlen, | 1127 | sctx->addrlens, |
1095 | sctx->maxbuf, | 1128 | sctx->maxbuf, |
1096 | sctx->timeout, sctx->require_found); | 1129 | sctx->timeout, sctx->require_found); |
1097 | if (sctx->server == NULL) | 1130 | if (sctx->server == NULL) |
1098 | { | 1131 | { |
1099 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1132 | i = 0; |
1100 | _("Failed to start `%s' at `%s'\n"), | 1133 | while (sctx->addrs[i] != NULL) |
1101 | sctx->serviceName, GNUNET_a2s (sctx->addr, sctx->addrlen)); | 1134 | { |
1135 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1136 | _("Failed to start `%s' at `%s'\n"), | ||
1137 | sctx->serviceName, | ||
1138 | GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i])); | ||
1139 | i++; | ||
1140 | } | ||
1102 | sctx->ret = GNUNET_SYSERR; | 1141 | sctx->ret = GNUNET_SYSERR; |
1103 | return; | 1142 | return; |
1104 | } | 1143 | } |
@@ -1123,9 +1162,15 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1123 | sctx->ready_confirm_fd = -1; | 1162 | sctx->ready_confirm_fd = -1; |
1124 | write_pid_file (sctx, getpid ()); | 1163 | write_pid_file (sctx, getpid ()); |
1125 | } | 1164 | } |
1126 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1165 | i = 0; |
1127 | _("Service `%s' runs at %s\n"), | 1166 | while (sctx->addrs[i] != NULL) |
1128 | sctx->serviceName, GNUNET_a2s (sctx->addr, sctx->addrlen)); | 1167 | { |
1168 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1169 | _("Service `%s' runs at %s\n"), | ||
1170 | sctx->serviceName, | ||
1171 | GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i])); | ||
1172 | i++; | ||
1173 | } | ||
1129 | sctx->task (sctx->task_cls, tc->sched, sctx->server, sctx->cfg); | 1174 | sctx->task (sctx->task_cls, tc->sched, sctx->server, sctx->cfg); |
1130 | } | 1175 | } |
1131 | 1176 | ||
@@ -1295,6 +1340,7 @@ GNUNET_SERVICE_run (int argc, | |||
1295 | char *loglev; | 1340 | char *loglev; |
1296 | char *logfile; | 1341 | char *logfile; |
1297 | int do_daemonize; | 1342 | int do_daemonize; |
1343 | unsigned int i; | ||
1298 | struct GNUNET_SERVICE_Context sctx; | 1344 | struct GNUNET_SERVICE_Context sctx; |
1299 | struct GNUNET_CONFIGURATION_Handle *cfg; | 1345 | struct GNUNET_CONFIGURATION_Handle *cfg; |
1300 | struct GNUNET_GETOPT_CommandLineOption service_options[] = { | 1346 | struct GNUNET_GETOPT_CommandLineOption service_options[] = { |
@@ -1358,7 +1404,11 @@ shutdown: | |||
1358 | } | 1404 | } |
1359 | 1405 | ||
1360 | GNUNET_CONFIGURATION_destroy (cfg); | 1406 | GNUNET_CONFIGURATION_destroy (cfg); |
1361 | GNUNET_free_non_null (sctx.addr); | 1407 | i = 0; |
1408 | while (sctx.addrs[i] != NULL) | ||
1409 | GNUNET_free (sctx.addrs[i++]); | ||
1410 | GNUNET_free_non_null (sctx.addrs); | ||
1411 | GNUNET_free_non_null (sctx.addrlens); | ||
1362 | GNUNET_free_non_null (logfile); | 1412 | GNUNET_free_non_null (logfile); |
1363 | GNUNET_free (loglev); | 1413 | GNUNET_free (loglev); |
1364 | GNUNET_free (cfg_fn); | 1414 | GNUNET_free (cfg_fn); |
@@ -1402,8 +1452,8 @@ GNUNET_SERVICE_start (const char *serviceName, | |||
1402 | (NULL == (sctx->server = GNUNET_SERVER_create (sched, | 1452 | (NULL == (sctx->server = GNUNET_SERVER_create (sched, |
1403 | &check_access, | 1453 | &check_access, |
1404 | sctx, | 1454 | sctx, |
1405 | sctx->addr, | 1455 | sctx->addrs, |
1406 | sctx->addrlen, | 1456 | sctx->addrlens, |
1407 | sctx->maxbuf, | 1457 | sctx->maxbuf, |
1408 | sctx->timeout, | 1458 | sctx->timeout, |
1409 | sctx->require_found)))) | 1459 | sctx->require_found)))) |
@@ -1442,10 +1492,15 @@ GNUNET_SERVICE_get_server (struct GNUNET_SERVICE_Context *ctx) | |||
1442 | void | 1492 | void |
1443 | GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx) | 1493 | GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx) |
1444 | { | 1494 | { |
1495 | unsigned int i; | ||
1445 | if (NULL != sctx->server) | 1496 | if (NULL != sctx->server) |
1446 | GNUNET_SERVER_destroy (sctx->server); | 1497 | GNUNET_SERVER_destroy (sctx->server); |
1447 | GNUNET_free_non_null (sctx->my_handlers); | 1498 | GNUNET_free_non_null (sctx->my_handlers); |
1448 | GNUNET_free_non_null (sctx->addr); | 1499 | i = 0; |
1500 | while (sctx->addrs[i] != NULL) | ||
1501 | GNUNET_free (sctx->addrs[i++]); | ||
1502 | GNUNET_free_non_null (sctx->addrs); | ||
1503 | GNUNET_free_non_null (sctx->addrlens); | ||
1449 | GNUNET_free_non_null (sctx->v4_denied); | 1504 | GNUNET_free_non_null (sctx->v4_denied); |
1450 | GNUNET_free_non_null (sctx->v6_denied); | 1505 | GNUNET_free_non_null (sctx->v6_denied); |
1451 | GNUNET_free_non_null (sctx->v4_allowed); | 1506 | GNUNET_free_non_null (sctx->v4_allowed); |