gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

testing_api_cmd_netjail_start.c (5843B)


      1 /*
      2       This file is part of GNUnet
      3       Copyright (C) 2021 GNUnet e.V.
      4 
      5       GNUnet is free software: you can redistribute it and/or modify it
      6       under the terms of the GNU Affero General Public License as published
      7       by the Free Software Foundation, either version 3 of the License,
      8       or (at your option) any later version.
      9 
     10       GNUnet is distributed in the hope that it will be useful, but
     11       WITHOUT ANY WARRANTY; without even the implied warranty of
     12       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13       Affero General Public License for more details.
     14 
     15       You should have received a copy of the GNU Affero General Public License
     16       along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18      SPDX-License-Identifier: AGPL3.0-or-later
     19  */
     20 
     21 /**
     22  * @file testing/testing_api_cmd_netjail_start.c
     23  * @brief Command to start the netjail script.
     24  * @author t3sserakt
     25  */
     26 #include "platform.h"
     27 #include "gnunet_util_lib.h"
     28 #include "gnunet_testing_lib.h"
     29 #include "testing_api_topology.h"
     30 
     31 #define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
     32 
     33 /**
     34  * Struct to hold information for callbacks.
     35  *
     36  */
     37 struct NetJailState
     38 {
     39   /**
     40    * Context for our asynchronous completion.
     41    */
     42   struct GNUNET_TESTING_AsyncContext ac;
     43 
     44   struct GNUNET_ChildWaitHandle *cwh;
     45 
     46   /**
     47    * The process id of the start script.
     48    */
     49   struct GNUNET_Process *start_proc;
     50 
     51   /**
     52    * Configuration file for the test topology.
     53    */
     54   const char *topology_cmd_label;
     55 
     56   /**
     57    * Start or stop?
     58    */
     59   const char *script;
     60 
     61 };
     62 
     63 
     64 /**
     65  * The cleanup function of this cmd frees resources the cmd allocated.
     66  *
     67  */
     68 static void
     69 netjail_start_cleanup (void *cls)
     70 {
     71   struct NetJailState *ns = cls;
     72 
     73   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     74               "netjail_start_cleanup!\n");
     75   if (NULL != ns->cwh)
     76   {
     77     GNUNET_wait_child_cancel (ns->cwh);
     78     ns->cwh = NULL;
     79   }
     80   if (NULL != ns->start_proc)
     81   {
     82     GNUNET_assert (GNUNET_OK ==
     83                    GNUNET_process_kill (ns->start_proc,
     84                                         SIGKILL));
     85     GNUNET_assert (GNUNET_OK ==
     86                    GNUNET_process_wait (ns->start_proc,
     87                                         true,
     88                                         NULL,
     89                                         NULL));
     90     GNUNET_process_destroy (ns->start_proc);
     91     ns->start_proc = NULL;
     92   }
     93   GNUNET_free (ns);
     94 }
     95 
     96 
     97 /**
     98  * Callback which will be called if the setup script finished.
     99  */
    100 static void
    101 child_completed_callback (void *cls,
    102                           enum GNUNET_OS_ProcessStatusType type,
    103                           unsigned long int exit_code)
    104 {
    105   struct NetJailState *ns = cls;
    106 
    107   GNUNET_process_destroy (ns->start_proc);
    108   ns->start_proc = NULL;
    109   ns->cwh = NULL;
    110   if ( (GNUNET_OS_PROCESS_EXITED != type) ||
    111        (0 != exit_code) )
    112   {
    113     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    114                 "Child failed with error %lu!\n",
    115                 exit_code);
    116     GNUNET_TESTING_async_fail (&ns->ac);
    117     return;
    118   }
    119   GNUNET_TESTING_async_finish (&ns->ac);
    120 }
    121 
    122 
    123 /**
    124 * The run method starts the script which setup the network namespaces.
    125 *
    126 * @param cls closure.
    127 * @param is interpreter state.
    128 */
    129 static void
    130 netjail_start_run (void *cls,
    131                    struct GNUNET_TESTING_Interpreter *is)
    132 {
    133   struct NetJailState *ns = cls;
    134   const struct GNUNET_TESTING_Command *topo_cmd;
    135   char pid[15];
    136   enum GNUNET_GenericReturnValue helper_check;
    137   char *data_dir;
    138   char *script_name;
    139   const char *topology_data;
    140 
    141   topo_cmd = GNUNET_TESTING_interpreter_lookup_command (
    142     is,
    143     ns->topology_cmd_label);
    144   if (NULL == topo_cmd)
    145     GNUNET_TESTING_FAIL (is);
    146   if (GNUNET_OK !=
    147       GNUNET_TESTING_get_trait_topology_string (topo_cmd,
    148                                                 &topology_data))
    149     GNUNET_TESTING_FAIL (is);
    150   data_dir = GNUNET_OS_installation_get_path (
    151     GNUNET_OS_project_data_gnunet (),
    152     GNUNET_OS_IPK_DATADIR);
    153   GNUNET_asprintf (&script_name,
    154                    "%s%s",
    155                    data_dir,
    156                    ns->script);
    157   helper_check = GNUNET_OS_check_helper_binary (
    158     script_name,
    159     true,
    160     NULL);
    161   if (GNUNET_NO == helper_check)
    162   {
    163     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    164                 "No SUID for %s!\n",
    165                 script_name);
    166     GNUNET_TESTING_interpreter_skip (is);
    167     return;
    168   }
    169   if (GNUNET_SYSERR == helper_check)
    170   {
    171     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    172                 "%s not found!\n",
    173                 script_name);
    174     GNUNET_TESTING_interpreter_skip (is);
    175     return;
    176   }
    177 
    178   GNUNET_snprintf (pid,
    179                    sizeof (pid),
    180                    "%u",
    181                    getpid ());
    182   ns->start_proc = GNUNET_process_create (GNUNET_OS_INHERIT_STD_ERR);
    183   if (GNUNET_OK !=
    184       GNUNET_process_run_command_va (ns->start_proc,
    185                                      script_name,
    186                                      script_name,
    187                                      (char *) topology_data,
    188                                      pid,
    189                                      (char*) "0",
    190                                      NULL))
    191   {
    192     GNUNET_break (0);
    193     GNUNET_TESTING_FAIL (is);
    194     return;
    195   }
    196   ns->cwh = GNUNET_wait_child (ns->start_proc,
    197                                &child_completed_callback,
    198                                ns);
    199   GNUNET_break (NULL != ns->cwh);
    200   GNUNET_free (script_name);
    201   GNUNET_free (data_dir);
    202 }
    203 
    204 
    205 struct GNUNET_TESTING_Command
    206 GNUNET_TESTING_cmd_netjail_setup (
    207   const char *label,
    208   const char *script,
    209   const char *topology_cmd_label)
    210 {
    211   struct NetJailState *ns;
    212 
    213   ns = GNUNET_new (struct NetJailState);
    214   ns->script = script;
    215   ns->topology_cmd_label = topology_cmd_label;
    216   return GNUNET_TESTING_command_new_ac (
    217     ns,
    218     label,
    219     &netjail_start_run,
    220     &netjail_start_cleanup,
    221     NULL,
    222     &ns->ac);
    223 }