diff options
-rw-r--r-- | doc/man/gnunet.conf.5 | 4 | ||||
-rw-r--r-- | src/arm/gnunet-service-arm.c | 25 | ||||
-rw-r--r-- | src/include/gnunet_network_lib.h | 15 | ||||
-rw-r--r-- | src/util/network.c | 58 |
4 files changed, 88 insertions, 14 deletions
diff --git a/doc/man/gnunet.conf.5 b/doc/man/gnunet.conf.5 index 2ef88c11e..3df3b437a 100644 --- a/doc/man/gnunet.conf.5 +++ b/doc/man/gnunet.conf.5 | |||
@@ -28,6 +28,10 @@ The following options are generic and shared by all services: | |||
28 | Start the service always when the peer starts. Set to YES for services that should always be launched, even if no other service explicitly needs them. | 28 | Start the service always when the peer starts. Set to YES for services that should always be launched, even if no other service explicitly needs them. |
29 | .IP AUTOSTART | 29 | .IP AUTOSTART |
30 | Set to YES to automatically start the service when it is requested by another service. YES for most GNUnet services. | 30 | Set to YES to automatically start the service when it is requested by another service. YES for most GNUnet services. |
31 | .IP NOARMBIND | ||
32 | Set to YES to never have ARM bind to the respective socket. This option is mostly for debugging in situations where ARM cannot pass the pre-bound socket to the child due to interference from PREFIX-commands. This option is only effective in combination with FORCESTART being YES. NO by default. | ||
33 | .IP PREFIX | ||
34 | PREFIX the given command (with its arguments) to the actual BINARY to be executed. Useful to run certain services under special supervisors (like strace or valgrind). Typically used in combination with FORCESTART and NOARMBIND. Empty by default. | ||
31 | .IP ACCEPT_FROM | 35 | .IP ACCEPT_FROM |
32 | A semi-column separated list of IPv4 addresses that are allowed to use the service; usually 127.0.0.1. | 36 | A semi-column separated list of IPv4 addresses that are allowed to use the service; usually 127.0.0.1. |
33 | .IP ACCEPT_FROM6 | 37 | .IP ACCEPT_FROM6 |
diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c index 0dffafeeb..a411546d7 100644 --- a/src/arm/gnunet-service-arm.c +++ b/src/arm/gnunet-service-arm.c | |||
@@ -603,7 +603,8 @@ accept_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
603 | * @param sl service entry for the service in question | 603 | * @param sl service entry for the service in question |
604 | */ | 604 | */ |
605 | static void | 605 | static void |
606 | create_listen_socket (struct sockaddr *sa, socklen_t addr_len, | 606 | create_listen_socket (struct sockaddr *sa, |
607 | socklen_t addr_len, | ||
607 | struct ServiceList *sl) | 608 | struct ServiceList *sl) |
608 | { | 609 | { |
609 | static int on = 1; | 610 | static int on = 1; |
@@ -652,14 +653,18 @@ create_listen_socket (struct sockaddr *sa, socklen_t addr_len, | |||
652 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 653 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
653 | "setsockopt"); | 654 | "setsockopt"); |
654 | #endif | 655 | #endif |
655 | 656 | #ifndef WINDOWS | |
657 | if (AF_UNIX == sa->sa_family) | ||
658 | GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa); | ||
659 | #endif | ||
656 | if (GNUNET_OK != | 660 | if (GNUNET_OK != |
657 | GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len)) | 661 | GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len)) |
658 | { | 662 | { |
659 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 663 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
660 | _ | 664 | _("Unable to bind listening socket for service `%s' to address `%s': %s\n"), |
661 | ("Unable to bind listening socket for service `%s' to address `%s': %s\n"), | 665 | sl->name, |
662 | sl->name, GNUNET_a2s (sa, addr_len), STRERROR (errno)); | 666 | GNUNET_a2s (sa, addr_len), |
667 | STRERROR (errno)); | ||
663 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); | 668 | GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); |
664 | GNUNET_free (sa); | 669 | GNUNET_free (sa); |
665 | return; | 670 | return; |
@@ -1394,11 +1399,11 @@ setup_service (void *cls, | |||
1394 | "FORCESTART")) | 1399 | "FORCESTART")) |
1395 | { | 1400 | { |
1396 | sl->force_start = GNUNET_YES; | 1401 | sl->force_start = GNUNET_YES; |
1397 | /* FIXME: we might like the pre-binding even for | 1402 | if (GNUNET_YES == |
1398 | _certain_ services that have force_start set, | 1403 | GNUNET_CONFIGURATION_get_value_yesno (cfg, |
1399 | otherwise interdependencies may again force | 1404 | section, |
1400 | client's to retry connections during startup. */ | 1405 | "NOARMBIND")) |
1401 | return; | 1406 | return; |
1402 | } | 1407 | } |
1403 | else | 1408 | else |
1404 | { | 1409 | { |
diff --git a/src/include/gnunet_network_lib.h b/src/include/gnunet_network_lib.h index f70509830..83d820a5b 100644 --- a/src/include/gnunet_network_lib.h +++ b/src/include/gnunet_network_lib.h | |||
@@ -106,6 +106,21 @@ char * | |||
106 | GNUNET_NETWORK_shorten_unixpath (char *unixpath); | 106 | GNUNET_NETWORK_shorten_unixpath (char *unixpath); |
107 | 107 | ||
108 | 108 | ||
109 | #ifndef WINDOWS | ||
110 | /** | ||
111 | * If services crash, they can leave a unix domain socket file on the | ||
112 | * disk. This needs to be manually removed, because otherwise both | ||
113 | * bind() and connect() for the respective address will fail. In this | ||
114 | * function, we test if such a left-over file exists, and if so, | ||
115 | * remove it (unless there is a listening service at the address). | ||
116 | * | ||
117 | * @param un unix domain socket address to check | ||
118 | */ | ||
119 | void | ||
120 | GNUNET_NETWORK_unix_precheck (const struct sockaddr_un *un); | ||
121 | #endif | ||
122 | |||
123 | |||
109 | /** | 124 | /** |
110 | * Accept a new connection on a socket. Configure it for non-blocking | 125 | * Accept a new connection on a socket. Configure it for non-blocking |
111 | * IO and mark it as non-inheritable to child processes (set the | 126 | * IO and mark it as non-inheritable to child processes (set the |
diff --git a/src/util/network.c b/src/util/network.c index d141732c2..489966426 100644 --- a/src/util/network.c +++ b/src/util/network.c | |||
@@ -147,6 +147,53 @@ GNUNET_NETWORK_shorten_unixpath (char *unixpath) | |||
147 | } | 147 | } |
148 | 148 | ||
149 | 149 | ||
150 | #ifndef WINDOWS | ||
151 | /** | ||
152 | * If services crash, they can leave a unix domain socket file on the | ||
153 | * disk. This needs to be manually removed, because otherwise both | ||
154 | * bind() and connect() for the respective address will fail. In this | ||
155 | * function, we test if such a left-over file exists, and if so, | ||
156 | * remove it (unless there is a listening service at the address). | ||
157 | * | ||
158 | * @param un unix domain socket address to check | ||
159 | */ | ||
160 | void | ||
161 | GNUNET_NETWORK_unix_precheck (const struct sockaddr_un *un) | ||
162 | { | ||
163 | int s; | ||
164 | int eno; | ||
165 | struct stat sbuf; | ||
166 | int ret; | ||
167 | |||
168 | s = socket (AF_UNIX, SOCK_STREAM, 0); | ||
169 | ret = connect (s, | ||
170 | (struct sockaddr *) un, | ||
171 | sizeof (struct sockaddr_un)); | ||
172 | eno = errno; | ||
173 | GNUNET_break (0 == close (s)); | ||
174 | if (0 == ret) | ||
175 | return; /* another process is listening, do not remove! */ | ||
176 | if (ECONNREFUSED != eno) | ||
177 | return; /* some other error, likely "no such file or directory" -- all well */ | ||
178 | /* should unlink, but sanity checks first */ | ||
179 | if (0 != stat (un->sun_path, | ||
180 | &sbuf)) | ||
181 | return; /* failed to 'stat', likely does not exist after all */ | ||
182 | if (S_IFSOCK != (S_IFMT & sbuf.st_mode)) | ||
183 | return; /* refuse to unlink anything except sockets */ | ||
184 | /* finally, really unlink */ | ||
185 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
186 | "Removing left-over `%s' from previous exeuction\n", | ||
187 | un->sun_path); | ||
188 | if (0 != unlink (un->sun_path)) | ||
189 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
190 | "unlink", | ||
191 | un->sun_path); | ||
192 | } | ||
193 | #endif | ||
194 | |||
195 | |||
196 | |||
150 | #ifndef FD_COPY | 197 | #ifndef FD_COPY |
151 | #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) | 198 | #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) |
152 | #endif | 199 | #endif |
@@ -447,6 +494,8 @@ GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc, | |||
447 | #endif | 494 | #endif |
448 | #endif | 495 | #endif |
449 | #ifndef WINDOWS | 496 | #ifndef WINDOWS |
497 | if (AF_UNIX == address->sa_family) | ||
498 | GNUNET_NETWORK_unix_precheck ((const struct sockaddr_un *) address); | ||
450 | { | 499 | { |
451 | const int on = 1; | 500 | const int on = 1; |
452 | 501 | ||
@@ -459,8 +508,6 @@ GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc, | |||
459 | LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, | 508 | LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, |
460 | "setsockopt"); | 509 | "setsockopt"); |
461 | } | 510 | } |
462 | #endif | ||
463 | #ifndef WINDOWS | ||
464 | { | 511 | { |
465 | /* set permissions of newly created non-abstract UNIX domain socket to | 512 | /* set permissions of newly created non-abstract UNIX domain socket to |
466 | "user-only"; applications can choose to relax this later */ | 513 | "user-only"; applications can choose to relax this later */ |
@@ -476,7 +523,10 @@ GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc, | |||
476 | old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH); | 523 | old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH); |
477 | #endif | 524 | #endif |
478 | 525 | ||
479 | ret = bind (desc->fd, address, address_len); | 526 | ret = bind (desc->fd, |
527 | address, | ||
528 | address_len); | ||
529 | |||
480 | #ifndef WINDOWS | 530 | #ifndef WINDOWS |
481 | if (not_abstract) | 531 | if (not_abstract) |
482 | (void) umask (old_mask); | 532 | (void) umask (old_mask); |
@@ -486,7 +536,7 @@ GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc, | |||
486 | if (SOCKET_ERROR == ret) | 536 | if (SOCKET_ERROR == ret) |
487 | SetErrnoFromWinsockError (WSAGetLastError ()); | 537 | SetErrnoFromWinsockError (WSAGetLastError ()); |
488 | #endif | 538 | #endif |
489 | if (ret != 0) | 539 | if (0 != ret) |
490 | return GNUNET_SYSERR; | 540 | return GNUNET_SYSERR; |
491 | #ifndef MINGW | 541 | #ifndef MINGW |
492 | desc->addr = GNUNET_malloc (address_len); | 542 | desc->addr = GNUNET_malloc (address_len); |