From d409018c1da52d051bf2e95cd97a73e72cb5accd Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 1 Jul 2018 19:38:06 +0200 Subject: move gnunet-timeout to src/util/, fix issues related to #5375 --- contrib/Makefile.am | 11 -- contrib/timeout_watchdog.c | 116 ---------------- contrib/timeout_watchdog_w32.c | 191 -------------------------- doc/man/Makefile.am | 1 + doc/man/gnunet-gns.1 | 2 +- src/gns/gns_api.c | 7 +- src/gns/gnunet-gns.c | 10 +- src/gns/nss/nss_gns.c | 269 +++++++++++++++++++------------------ src/gns/nss/nss_gns_query.c | 25 +++- src/gns/nss/nss_gns_query.h | 30 +++-- src/identity/identity_api_lookup.c | 8 +- src/util/Makefile.am | 16 ++- src/util/client.c | 13 +- src/util/gnunet-timeout-w32.c | 191 ++++++++++++++++++++++++++ src/util/gnunet-timeout.c | 128 ++++++++++++++++++ 15 files changed, 534 insertions(+), 484 deletions(-) delete mode 100644 contrib/timeout_watchdog.c delete mode 100644 contrib/timeout_watchdog_w32.c create mode 100644 src/util/gnunet-timeout-w32.c create mode 100644 src/util/gnunet-timeout.c diff --git a/contrib/Makefile.am b/contrib/Makefile.am index 158e43998..eec3300b9 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -5,17 +5,6 @@ tap32dir = $(pkgdatadir)/openvpn-tap32/tapw32/ tap64dir = $(pkgdatadir)/openvpn-tap32/tapw64/ -noinst_PROGRAMS = \ - timeout_watchdog - -if !MINGW -timeout_watchdog_SOURCES = \ - timeout_watchdog.c -else -timeout_watchdog_SOURCES = \ - timeout_watchdog_w32.c -endif - noinst_SCRIPTS = \ scripts/terminate.py \ scripts/pydiffer.py \ diff --git a/contrib/timeout_watchdog.c b/contrib/timeout_watchdog.c deleted file mode 100644 index 70e840d55..000000000 --- a/contrib/timeout_watchdog.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2010 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -/** - * @file contrib/timeout_watchdog.c - * @brief small tool starting a child process, waiting that it terminates or killing it after a given timeout period - * @author Matthias Wachs - */ - -#include -#include -#include -#include -#include -#include - -static pid_t child; - - -static void -sigchld_handler (int val) -{ - int status = 0; - int ret = 0; - - (void) val; - waitpid (child, &status, 0); - if (WIFEXITED (status) != 0) - { - ret = WEXITSTATUS (status); - printf ("Test process exited with result %u\n", ret); - } - if (WIFSIGNALED (status) != 0) - { - ret = WTERMSIG (status); - printf ("Test process was signaled %u\n", ret); - } - exit (ret); -} - - -static void -sigint_handler (int val) -{ - kill (0, val); - exit (val); -} - - -int -main (int argc, - char *argv[]) -{ - int timeout = 0; - pid_t gpid = 0; - - if (argc < 3) - { - printf - ("arg 1: timeout in sec., arg 2: executable, arg arguments\n"); - exit (1); - } - - timeout = atoi (argv[1]); - - if (timeout == 0) - timeout = 600; - -/* with getpgid() it does not compile, but getpgrp is the BSD version and working */ - gpid = getpgrp (); - - signal (SIGCHLD, sigchld_handler); - signal (SIGABRT, sigint_handler); - signal (SIGFPE, sigint_handler); - signal (SIGILL, sigint_handler); - signal (SIGINT, sigint_handler); - signal (SIGSEGV, sigint_handler); - signal (SIGTERM, sigint_handler); - - child = fork (); - if (child == 0) - { - /* int setpgrp(pid_t pid, pid_t pgid); is not working on this machine */ - //setpgrp (0, pid_t gpid); - if (-1 != gpid) - setpgid (0, gpid); - execvp (argv[2], &argv[2]); - exit (1); - } - if (child > 0) - { - sleep (timeout); - printf ("Child processes were killed after timeout of %u seconds\n", - timeout); - kill (0, SIGTERM); - exit (1); - } - exit (1); -} - -/* end of timeout_watchdog.c */ diff --git a/contrib/timeout_watchdog_w32.c b/contrib/timeout_watchdog_w32.c deleted file mode 100644 index 901eb6207..000000000 --- a/contrib/timeout_watchdog_w32.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2010 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -/** - * @file contrib/timeout_watchdog_w32.c - * @brief small tool starting a child process, waiting that it terminates or killing it after a given timeout period - * @author LRN - */ - -#include -#include -#include - -int -main (int argc, char *argv[]) -{ - int i; - DWORD wait_result; - wchar_t *commandline; - wchar_t **wargv; - wchar_t *arg; - unsigned int cmdlen; - STARTUPINFOW start; - PROCESS_INFORMATION proc; - - wchar_t wpath[MAX_PATH + 1]; - - wchar_t *pathbuf; - DWORD pathbuf_len, alloc_len; - wchar_t *ptr; - wchar_t *non_const_filename; - wchar_t *wcmd; - int wargc; - int timeout = 0; - ssize_t wrote; - - HANDLE job; - - if (argc < 3) - { - printf - ("arg 1: timeout in sec., arg 2: executable, arg arguments\n"); - exit (1); - } - - timeout = atoi (argv[1]); - - if (timeout == 0) - timeout = 600; - - commandline = GetCommandLineW (); - if (commandline == NULL) - { - printf ("Failed to get commandline: %lu\n", GetLastError ()); - exit (2); - } - - wargv = CommandLineToArgvW (commandline, &wargc); - if (wargv == NULL || wargc <= 1) - { - printf ("Failed to get parse commandline: %lu\n", GetLastError ()); - exit (3); - } - - job = CreateJobObject (NULL, NULL); - if (job == NULL) - { - printf ("Failed to create a job: %lu\n", GetLastError ()); - exit (4); - } - - pathbuf_len = GetEnvironmentVariableW (L"PATH", (wchar_t *) &pathbuf, 0); - - alloc_len = pathbuf_len + 1; - - pathbuf = malloc (alloc_len * sizeof (wchar_t)); - - ptr = pathbuf; - - alloc_len = GetEnvironmentVariableW (L"PATH", ptr, pathbuf_len); - - cmdlen = wcslen (wargv[2]); - if (cmdlen < 5 || wcscmp (&wargv[2][cmdlen - 4], L".exe") != 0) - { - non_const_filename = malloc (sizeof (wchar_t) * (cmdlen + 5)); - swprintf (non_const_filename, cmdlen + 5, L"%S.exe", wargv[2]); - } - else - { - non_const_filename = wcsdup (wargv[2]); - } - - /* Check that this is the full path. If it isn't, search. */ - if (non_const_filename[1] == L':') - swprintf (wpath, sizeof (wpath) / sizeof (wchar_t), L"%S", non_const_filename); - else if (!SearchPathW - (pathbuf, non_const_filename, NULL, sizeof (wpath) / sizeof (wchar_t), - wpath, NULL)) - { - printf ("Failed to get find executable: %lu\n", GetLastError ()); - exit (5); - } - free (pathbuf); - free (non_const_filename); - - cmdlen = wcslen (wpath) + 4; - i = 3; - while (NULL != (arg = wargv[i++])) - cmdlen += wcslen (arg) + 4; - - wcmd = malloc (sizeof (wchar_t) * (cmdlen + 1)); - wrote = 0; - i = 2; - while (NULL != (arg = wargv[i++])) - { - /* This is to escape trailing slash */ - wchar_t arg_lastchar = arg[wcslen (arg) - 1]; - if (wrote == 0) - { - wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\" ", wpath, - arg_lastchar == L'\\' ? L"\\" : L""); - } - else - { - if (wcschr (arg, L' ') != NULL) - wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\"%S", arg, - arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" "); - else - wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"%S%S%S", arg, - arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" "); - } - } - - LocalFree (wargv); - - memset (&start, 0, sizeof (start)); - start.cb = sizeof (start); - - if (!CreateProcessW (wpath, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED, - NULL, NULL, &start, &proc)) - { - wprintf (L"Failed to get spawn process `%S' with arguments `%S': %lu\n", wpath, wcmd, GetLastError ()); - exit (6); - } - - AssignProcessToJobObject (job, proc.hProcess); - - ResumeThread (proc.hThread); - CloseHandle (proc.hThread); - - free (wcmd); - - wait_result = WaitForSingleObject (proc.hProcess, timeout * 1000); - if (wait_result == WAIT_OBJECT_0) - { - DWORD status; - wait_result = GetExitCodeProcess (proc.hProcess, &status); - CloseHandle (proc.hProcess); - if (wait_result != 0) - { - printf ("Test process exited with result %lu\n", status); - TerminateJobObject (job, status); - exit (status); - } - printf ("Test process exited (failed to obtain exit status)\n"); - TerminateJobObject (job, 0); - exit (0); - } - printf ("Child processes were killed after timeout of %u seconds\n", - timeout); - TerminateJobObject (job, 1); - CloseHandle (proc.hProcess); - exit (1); -} - -/* end of timeout_watchdog_w32.c */ diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index a6a116dca..37f881d60 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -37,6 +37,7 @@ man_MANS = \ gnunet-statistics.1 \ gnunet-testbed-profiler.1 \ gnunet-testing-run-service.1 \ + gnunet-timeout.1 \ gnunet-transport.1 \ gnunet-transport-certificate-creation.1 \ gnunet-unindex.1 \ diff --git a/doc/man/gnunet-gns.1 b/doc/man/gnunet-gns.1 index 9466dae03..9e4482653 100644 --- a/doc/man/gnunet-gns.1 +++ b/doc/man/gnunet-gns.1 @@ -46,7 +46,7 @@ Print GNUnet version number. .SH RETURN VALUE gnunet\-gns will return 0 on success, 1 on internal failures, 2 on -launch failures, 3 if the given name is not configured to use GNS. +launch failures, 4 if the given name is not configured to use GNS. .SH BUGS diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c index 0ec9209da..3b658da92 100644 --- a/src/gns/gns_api.c +++ b/src/gns/gns_api.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -232,7 +232,6 @@ reconnect (struct GNUNET_GNS_Handle *handle) handle), GNUNET_MQ_handler_end () }; - struct GNUNET_GNS_LookupRequest *lh; GNUNET_assert (NULL == handle->mq); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -244,7 +243,9 @@ reconnect (struct GNUNET_GNS_Handle *handle) handle); if (NULL == handle->mq) return; - for (lh = handle->lookup_head; NULL != lh; lh = lh->next) + for (struct GNUNET_GNS_LookupRequest *lh = handle->lookup_head; + NULL != lh; + lh = lh->next) GNUNET_MQ_send_copy (handle->mq, lh->env); } diff --git a/src/gns/gnunet-gns.c b/src/gns/gnunet-gns.c index 149c8a7bb..463348ed3 100644 --- a/src/gns/gnunet-gns.c +++ b/src/gns/gnunet-gns.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -65,8 +65,9 @@ static struct GNUNET_GNS_LookupWithTldRequest *lr; /** * Global return value. * 0 on success (default), - * 1 on internal failures, 2 on launch failure, - * 3 if the name is not a GNS-supported TLD, + * 1 on internal failures + * 2 on launch failure, + * 4 if the name is not a GNS-supported TLD, */ static int global_ret; @@ -114,7 +115,7 @@ process_lookup_result (void *cls, lr = NULL; if (GNUNET_NO == was_gns) { - global_ret = 3; + global_ret = 4; /* not for GNS */ GNUNET_SCHEDULER_shutdown (); return; } @@ -183,7 +184,6 @@ run (void *cls, global_ret = 2; return; } - GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); diff --git a/src/gns/nss/nss_gns.c b/src/gns/nss/nss_gns.c index 9c9233d35..58aab47fd 100644 --- a/src/gns/nss/nss_gns.c +++ b/src/gns/nss/nss_gns.c @@ -54,121 +54,126 @@ * @return a nss_status code */ enum nss_status -_nss_gns_gethostbyname2_r( - const char *name, - int af, - struct hostent * result, - char *buffer, - size_t buflen, - int *errnop, - int *h_errnop) { - - struct userdata u; - enum nss_status status = NSS_STATUS_UNAVAIL; - int i; - size_t address_length, l, idx, astart; - - if (af == AF_UNSPEC) +_nss_gns_gethostbyname2_r(const char *name, + int af, + struct hostent *result, + char *buffer, + size_t buflen, + int *errnop, + int *h_errnop) +{ + struct userdata u; + enum nss_status status = NSS_STATUS_UNAVAIL; + int i; + size_t address_length; + size_t l; + size_t idx; + size_t astart; + + if (af == AF_UNSPEC) #ifdef NSS_IPV6_ONLY - af = AF_INET6; + af = AF_INET6; #else - af = AF_INET; + af = AF_INET; #endif #ifdef NSS_IPV4_ONLY - if (af != AF_INET) + if (af != AF_INET) #elif NSS_IPV6_ONLY - if (af != AF_INET6) + if (af != AF_INET6) #else - if (af != AF_INET && af != AF_INET6) + if ( (af != AF_INET) && + (af != AF_INET6) ) #endif - { - *errnop = EINVAL; - *h_errnop = NO_RECOVERY; - - goto finish; - } - - address_length = af == AF_INET ? sizeof(ipv4_address_t) : sizeof(ipv6_address_t); - if (buflen < - sizeof(char*)+ /* alias names */ - strlen(name)+1) { /* official name */ - - *errnop = ERANGE; - *h_errnop = NO_RECOVERY; - status = NSS_STATUS_TRYAGAIN; - - goto finish; - } - - u.count = 0; - u.data_len = 0; - - i = gns_resolve_name(af, name, &u); - if (-3 == i) - { - status = NSS_STATUS_NOTFOUND; - goto finish; - } - if (-2 == i) - { - status = NSS_STATUS_UNAVAIL; - goto finish; - } - if ( (-1 == i) || - (u.count == 0) ) - { - *errnop = ETIMEDOUT; - *h_errnop = HOST_NOT_FOUND; - status = NSS_STATUS_NOTFOUND; - goto finish; - } - - - /* Alias names */ - *((char**) buffer) = NULL; - result->h_aliases = (char**) buffer; - idx = sizeof(char*); - - /* Official name */ - strcpy(buffer+idx, name); - result->h_name = buffer+idx; - idx += strlen(name)+1; - - ALIGN(idx); - - result->h_addrtype = af; - result->h_length = address_length; - - /* Check if there's enough space for the addresses */ - if (buflen < idx+u.data_len+sizeof(char*)*(u.count+1)) { - *errnop = ERANGE; - *h_errnop = NO_RECOVERY; - status = NSS_STATUS_TRYAGAIN; - goto finish; - } + { + *errnop = EINVAL; + *h_errnop = NO_RECOVERY; + + goto finish; + } + address_length = (af == AF_INET) ? sizeof(ipv4_address_t) : sizeof(ipv6_address_t); + if (buflen < + sizeof(char*)+ /* alias names */ + strlen(name)+1) + { /* official name */ + *errnop = ERANGE; + *h_errnop = NO_RECOVERY; + status = NSS_STATUS_TRYAGAIN; + + goto finish; + } + u.count = 0; + u.data_len = 0; + i = gns_resolve_name (af, + name, + &u); + if (-3 == i) + { + status = NSS_STATUS_NOTFOUND; + goto finish; + } + if (-2 == i) + { + status = NSS_STATUS_UNAVAIL; + goto finish; + } + if ( (-1 == i) || + (u.count == 0) ) + { + *errnop = ETIMEDOUT; + *h_errnop = HOST_NOT_FOUND; + status = NSS_STATUS_NOTFOUND; + goto finish; + } + /* Alias names */ + *((char**) buffer) = NULL; + result->h_aliases = (char**) buffer; + idx = sizeof(char*); + + /* Official name */ + strcpy (buffer+idx, + name); + result->h_name = buffer+idx; + idx += strlen (name)+1; + + ALIGN(idx); + + result->h_addrtype = af; + result->h_length = address_length; + + /* Check if there's enough space for the addresses */ + if (buflen < idx+u.data_len+sizeof(char*)*(u.count+1)) + { + *errnop = ERANGE; + *h_errnop = NO_RECOVERY; + status = NSS_STATUS_TRYAGAIN; + goto finish; + } /* Addresses */ - astart = idx; - l = u.count*address_length; - if (0 != l) - memcpy(buffer+astart, &u.data, l); - /* address_length is a multiple of 32bits, so idx is still aligned - * correctly */ - idx += l; - - /* Address array address_length is always a multiple of 32bits */ - for (i = 0; i < u.count; i++) - ((char**) (buffer+idx))[i] = buffer+astart+address_length*i; - ((char**) (buffer+idx))[i] = NULL; - result->h_addr_list = (char**) (buffer+idx); - - status = NSS_STATUS_SUCCESS; + astart = idx; + l = u.count*address_length; + if (0 != l) + memcpy (buffer+astart, + &u.data, + l); + /* address_length is a multiple of 32bits, so idx is still aligned + * correctly */ + idx += l; + + /* Address array address_length is always a multiple of 32bits */ + for (i = 0; i < u.count; i++) + ((char**) (buffer+idx))[i] = buffer+astart+address_length*i; + ((char**) (buffer+idx))[i] = NULL; + result->h_addr_list = (char**) (buffer+idx); + + status = NSS_STATUS_SUCCESS; finish: - return status; + return status; } + /** * The gethostbyname hook executed by nsswitch * @@ -176,29 +181,28 @@ finish: * @param result the result hostent * @param buffer the result buffer * @param buflen length of the buffer - * @param errnop idk + * @param errnop[out] the low-level error code to return to the application * @param h_errnop idk * @return a nss_status code */ enum nss_status -_nss_gns_gethostbyname_r ( - const char *name, - struct hostent *result, - char *buffer, - size_t buflen, - int *errnop, - int *h_errnop) { - - return _nss_gns_gethostbyname2_r( - name, - AF_UNSPEC, - result, - buffer, - buflen, - errnop, - h_errnop); +_nss_gns_gethostbyname_r (const char *name, + struct hostent *result, + char *buffer, + size_t buflen, + int *errnop, + int *h_errnop) +{ + return _nss_gns_gethostbyname2_r (name, + AF_UNSPEC, + result, + buffer, + buflen, + errnop, + h_errnop); } + /** * The gethostbyaddr hook executed by nsswitch * We can't do this so we always return NSS_STATUS_UNAVAIL @@ -209,23 +213,22 @@ _nss_gns_gethostbyname_r ( * @param result the result hostent * @param buffer the result buffer * @param buflen length of the buffer - * @param errnop idk + * @param errnop[out] the low-level error code to return to the application * @param h_errnop idk * @return NSS_STATUS_UNAVAIL */ enum nss_status -_nss_gns_gethostbyaddr_r( - const void* addr, - int len, - int af, - struct hostent *result, - char *buffer, - size_t buflen, - int *errnop, - int *h_errnop) { - - *errnop = EINVAL; - *h_errnop = NO_RECOVERY; - //NOTE we allow to leak this into DNS so no NOTFOUND - return NSS_STATUS_UNAVAIL; +_nss_gns_gethostbyaddr_r (const void* addr, + int len, + int af, + struct hostent *result, + char *buffer, + size_t buflen, + int *errnop, + int *h_errnop) +{ + *errnop = EINVAL; + *h_errnop = NO_RECOVERY; + //NOTE we allow to leak this into DNS so no NOTFOUND + return NSS_STATUS_UNAVAIL; } diff --git a/src/gns/nss/nss_gns_query.c b/src/gns/nss/nss_gns_query.c index 094e25ed5..867ead624 100644 --- a/src/gns/nss/nss_gns_query.c +++ b/src/gns/nss/nss_gns_query.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -48,14 +48,16 @@ gns_resolve_name (int af, { if (-1 == asprintf (&cmd, "%s -t AAAA -u %s\n", - "gnunet-gns -r", name)) + "gnunet-gns -r", + name)) return -1; } else { if (-1 == asprintf (&cmd, "%s %s\n", - "gnunet-gns -r -u", name)) + "gnunet-gns -r -u", + name)) return -1; } if (NULL == (p = popen (cmd, "r"))) @@ -63,7 +65,9 @@ gns_resolve_name (int af, free (cmd); return -1; } - while (NULL != fgets (line, sizeof(line), p)) + while (NULL != fgets (line, + sizeof(line), + p)) { if (u->count >= MAX_ENTRIES) break; @@ -72,7 +76,9 @@ gns_resolve_name (int af, line[strlen(line)-1] = '\0'; if (AF_INET == af) { - if (inet_pton(af, line, &(u->data.ipv4[u->count]))) + if (inet_pton(af, + line, + &u->data.ipv4[u->count])) { u->count++; u->data_len += sizeof(ipv4_address_t); @@ -86,7 +92,9 @@ gns_resolve_name (int af, } else if (AF_INET6 == af) { - if (inet_pton(af, line, &(u->data.ipv6[u->count]))) + if (inet_pton(af, + line, + &u->data.ipv6[u->count])) { u->count++; u->data_len += sizeof(ipv6_address_t); @@ -105,7 +113,10 @@ gns_resolve_name (int af, if (4 == ret) return -2; /* not for GNS */ if (3 == ret) - return -3; /* timeout */ + return -3; /* timeout -> not found */ + if ( (2 == ret) || (1 == ret) ) + return -2; /* launch failure -> service unavailable */ return 0; } + /* end of nss_gns_query.c */ diff --git a/src/gns/nss/nss_gns_query.h b/src/gns/nss/nss_gns_query.h index bb04f9004..48cab4b22 100644 --- a/src/gns/nss/nss_gns_query.h +++ b/src/gns/nss/nss_gns_query.h @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -26,25 +26,30 @@ /* Maximum number of entries to return */ #define MAX_ENTRIES 16 -typedef struct { - uint32_t address; +typedef struct +{ + uint32_t address; } ipv4_address_t; -typedef struct { - uint8_t address[16]; + +typedef struct +{ + uint8_t address[16]; } ipv6_address_t; -struct userdata { +struct userdata +{ int count; int data_len; /* only valid when doing reverse lookup */ union { - ipv4_address_t ipv4[MAX_ENTRIES]; - ipv6_address_t ipv6[MAX_ENTRIES]; - char *name[MAX_ENTRIES]; + ipv4_address_t ipv4[MAX_ENTRIES]; + ipv6_address_t ipv6[MAX_ENTRIES]; + char *name[MAX_ENTRIES]; } data; }; + /** * Wrapper function that uses gnunet-gns cli tool to resolve * an IPv4/6 address. @@ -54,8 +59,9 @@ struct userdata { * @param u the userdata (result struct) * @return -1 on error else 0 */ -int gns_resolve_name(int af, - const char *name, - struct userdata *userdata); +int +gns_resolve_name(int af, + const char *name, + struct userdata *userdata); #endif diff --git a/src/identity/identity_api_lookup.c b/src/identity/identity_api_lookup.c index 593a5dbb0..25aec8ede 100644 --- a/src/identity/identity_api_lookup.c +++ b/src/identity/identity_api_lookup.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -131,6 +131,12 @@ GNUNET_IDENTITY_ego_lookup (const struct GNUNET_CONFIGURATION_Handle *cfg, el->identity = GNUNET_IDENTITY_connect (cfg, &identity_cb, el); + if (NULL == el->identity) + { + GNUNET_free (el->name); + GNUNET_free (el); + return NULL; + } return el; } diff --git a/src/util/Makefile.am b/src/util/Makefile.am index ec7bcb016..4ae073c2c 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -166,6 +166,7 @@ lib_LTLIBRARIES = libgnunetutil.la libexec_PROGRAMS = \ gnunet-service-resolver \ + gnunet-timeout \ $(W32CONSOLEHELPER) bin_SCRIPTS =\ @@ -192,6 +193,15 @@ endif endif +if !MINGW +gnunet_timeout_SOURCES = \ + gnunet-timeout.c +else +gnunet_timeout_SOURCES = \ + gnunet-timeout-w32.c +endif + + do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' gnunet-qr: gnunet-qr.py.in Makefile @@ -334,12 +344,12 @@ test_hexcoder_LDADD = \ test_tun_SOURCES = \ test_tun.c test_tun_LDADD = \ - libgnunetutil.la + libgnunetutil.la test_regex_SOURCES = \ test_regex.c test_regex_LDADD = \ - libgnunetutil.la + libgnunetutil.la test_os_start_process_SOURCES = \ test_os_start_process.c @@ -622,4 +632,4 @@ EXTRA_DIST = \ test_resolver_api_data.conf \ test_service_data.conf \ test_speedup_data.conf \ - gnunet-qr.py.in + gnunet-qr.py.in diff --git a/src/util/client.c b/src/util/client.c index 44e326eab..1f569255a 100644 --- a/src/util/client.c +++ b/src/util/client.c @@ -11,7 +11,7 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ @@ -721,6 +721,17 @@ test_service_configuration (const char *service_name, &unixpath)) && (0 < strlen (unixpath))) ret = GNUNET_OK; + else if ((GNUNET_OK == + GNUNET_CONFIGURATION_have_value (cfg, + service_name, + "UNIXPATH"))) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + service_name, + "UNIXPATH", + _("not a valid filename")); + return GNUNET_SYSERR; /* UNIXPATH specified but invalid! */ + } GNUNET_free_non_null (unixpath); #endif diff --git a/src/util/gnunet-timeout-w32.c b/src/util/gnunet-timeout-w32.c new file mode 100644 index 000000000..78b268fe2 --- /dev/null +++ b/src/util/gnunet-timeout-w32.c @@ -0,0 +1,191 @@ +/* + This file is part of GNUnet + Copyright (C) 2010 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file src/util/gnunet-timeout-w32.c + * @brief small tool starting a child process, waiting that it terminates or killing it after a given timeout period + * @author LRN + */ + +#include +#include +#include + +int +main (int argc, char *argv[]) +{ + int i; + DWORD wait_result; + wchar_t *commandline; + wchar_t **wargv; + wchar_t *arg; + unsigned int cmdlen; + STARTUPINFOW start; + PROCESS_INFORMATION proc; + + wchar_t wpath[MAX_PATH + 1]; + + wchar_t *pathbuf; + DWORD pathbuf_len, alloc_len; + wchar_t *ptr; + wchar_t *non_const_filename; + wchar_t *wcmd; + int wargc; + int timeout = 0; + ssize_t wrote; + + HANDLE job; + + if (argc < 3) + { + printf + ("arg 1: timeout in sec., arg 2: executable, arg arguments\n"); + exit (1); + } + + timeout = atoi (argv[1]); + + if (timeout == 0) + timeout = 600; + + commandline = GetCommandLineW (); + if (commandline == NULL) + { + printf ("Failed to get commandline: %lu\n", GetLastError ()); + exit (2); + } + + wargv = CommandLineToArgvW (commandline, &wargc); + if (wargv == NULL || wargc <= 1) + { + printf ("Failed to get parse commandline: %lu\n", GetLastError ()); + exit (3); + } + + job = CreateJobObject (NULL, NULL); + if (job == NULL) + { + printf ("Failed to create a job: %lu\n", GetLastError ()); + exit (4); + } + + pathbuf_len = GetEnvironmentVariableW (L"PATH", (wchar_t *) &pathbuf, 0); + + alloc_len = pathbuf_len + 1; + + pathbuf = malloc (alloc_len * sizeof (wchar_t)); + + ptr = pathbuf; + + alloc_len = GetEnvironmentVariableW (L"PATH", ptr, pathbuf_len); + + cmdlen = wcslen (wargv[2]); + if (cmdlen < 5 || wcscmp (&wargv[2][cmdlen - 4], L".exe") != 0) + { + non_const_filename = malloc (sizeof (wchar_t) * (cmdlen + 5)); + swprintf (non_const_filename, cmdlen + 5, L"%S.exe", wargv[2]); + } + else + { + non_const_filename = wcsdup (wargv[2]); + } + + /* Check that this is the full path. If it isn't, search. */ + if (non_const_filename[1] == L':') + swprintf (wpath, sizeof (wpath) / sizeof (wchar_t), L"%S", non_const_filename); + else if (!SearchPathW + (pathbuf, non_const_filename, NULL, sizeof (wpath) / sizeof (wchar_t), + wpath, NULL)) + { + printf ("Failed to get find executable: %lu\n", GetLastError ()); + exit (5); + } + free (pathbuf); + free (non_const_filename); + + cmdlen = wcslen (wpath) + 4; + i = 3; + while (NULL != (arg = wargv[i++])) + cmdlen += wcslen (arg) + 4; + + wcmd = malloc (sizeof (wchar_t) * (cmdlen + 1)); + wrote = 0; + i = 2; + while (NULL != (arg = wargv[i++])) + { + /* This is to escape trailing slash */ + wchar_t arg_lastchar = arg[wcslen (arg) - 1]; + if (wrote == 0) + { + wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\" ", wpath, + arg_lastchar == L'\\' ? L"\\" : L""); + } + else + { + if (wcschr (arg, L' ') != NULL) + wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\"%S", arg, + arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" "); + else + wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"%S%S%S", arg, + arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" "); + } + } + + LocalFree (wargv); + + memset (&start, 0, sizeof (start)); + start.cb = sizeof (start); + + if (!CreateProcessW (wpath, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED, + NULL, NULL, &start, &proc)) + { + wprintf (L"Failed to get spawn process `%S' with arguments `%S': %lu\n", wpath, wcmd, GetLastError ()); + exit (6); + } + + AssignProcessToJobObject (job, proc.hProcess); + + ResumeThread (proc.hThread); + CloseHandle (proc.hThread); + + free (wcmd); + + wait_result = WaitForSingleObject (proc.hProcess, timeout * 1000); + if (wait_result == WAIT_OBJECT_0) + { + DWORD status; + wait_result = GetExitCodeProcess (proc.hProcess, &status); + CloseHandle (proc.hProcess); + if (wait_result != 0) + { + printf ("Test process exited with result %lu\n", status); + TerminateJobObject (job, status); + exit (status); + } + printf ("Test process exited (failed to obtain exit status)\n"); + TerminateJobObject (job, 0); + exit (0); + } + printf ("Child processes were killed after timeout of %u seconds\n", + timeout); + TerminateJobObject (job, 1); + CloseHandle (proc.hProcess); + exit (1); +} + +/* end of timeout_watchdog_w32.c */ diff --git a/src/util/gnunet-timeout.c b/src/util/gnunet-timeout.c new file mode 100644 index 000000000..8dfb6ad17 --- /dev/null +++ b/src/util/gnunet-timeout.c @@ -0,0 +1,128 @@ +/* + This file is part of GNUnet + Copyright (C) 2010 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file src/util/gnunet-timeout.c + * @brief small tool starting a child process, waiting that it terminates or killing it after a given timeout period + * @author Matthias Wachs + */ + +#include +#include +#include +#include +#include +#include + +static pid_t child; + + +static void +sigchld_handler (int val) +{ + int status = 0; + int ret = 0; + + (void) val; + waitpid (child, + &status, + 0); + if (WIFEXITED (status) != 0) + { + ret = WEXITSTATUS (status); + fprintf (stderr, + "Process exited with result %u\n", + ret); + exit (ret); /* return same status code */ + } + if (WIFSIGNALED (status) != 0) + { + ret = WTERMSIG (status); + fprintf (stderr, + "Process received signal %u\n", + ret); + kill (getpid (), + ret); /* kill self with the same signal */ + } + exit (-1); +} + + +static void +sigint_handler (int val) +{ + kill (0, + val); + exit (val); +} + + +int +main (int argc, + char *argv[]) +{ + int timeout = 0; + pid_t gpid = 0; + + if (argc < 3) + { + fprintf (stderr, + "arg 1: timeout in sec., arg 2: executable, arg arguments\n"); + exit (-1); + } + + timeout = atoi (argv[1]); + + if (timeout == 0) + timeout = 600; + + /* with getpgid() it does not compile, but getpgrp is the BSD version and working */ + gpid = getpgrp (); + + signal (SIGCHLD, sigchld_handler); + signal (SIGABRT, sigint_handler); + signal (SIGFPE, sigint_handler); + signal (SIGILL, sigint_handler); + signal (SIGINT, sigint_handler); + signal (SIGSEGV, sigint_handler); + signal (SIGTERM, sigint_handler); + + child = fork (); + if (child == 0) + { + /* int setpgrp(pid_t pid, pid_t pgid); is not working on this machine */ + //setpgrp (0, pid_t gpid); + if (-1 != gpid) + setpgid (0, gpid); + execvp (argv[2], + &argv[2]); + exit (-1); + } + if (child > 0) + { + sleep (timeout); + printf ("Child processes were killed after timeout of %u seconds\n", + timeout); + kill (0, + SIGTERM); + exit (3); + } + exit (-1); +} + +/* end of timeout_watchdog.c */ -- cgit v1.2.3