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 }