diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-07-13 14:53:30 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-07-13 14:53:30 +0000 |
commit | 3104aa430ae360599dd54369a8cb1fd61f07894c (patch) | |
tree | 6b8d87ddc782d50e51d1107bb13597218b5e9a1f /src/util/network.c | |
parent | 13a3089d561ed7332da25a7c461cdcc633c6b855 (diff) | |
download | gnunet-3104aa430ae360599dd54369a8cb1fd61f07894c.tar.gz gnunet-3104aa430ae360599dd54369a8cb1fd61f07894c.zip |
automatically clean up left-over Unix domain socket files when trying to bind (fixes #3723)
Diffstat (limited to 'src/util/network.c')
-rw-r--r-- | src/util/network.c | 58 |
1 files changed, 54 insertions, 4 deletions
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); |