diff options
Diffstat (limited to 'src')
-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 |
3 files changed, 84 insertions, 14 deletions
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); |