OpenVAS Scanner  7.0.1~git
pluginload.c
Go to the documentation of this file.
1 /* Portions Copyright (C) 2009-2019 Greenbone Networks GmbH
2  * Portions Copyright (C) 2006 Software in the Public Interest, Inc.
3  * Based on work Copyright (C) 1998 - 2006 Tenable Network Security, Inc.
4  *
5  * SPDX-License-Identifier: GPL-2.0-only
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
26 #include "pluginload.h"
27 
28 #include "../nasl/nasl.h"
29 #include "processes.h"
30 #include "sighand.h"
31 #include "utils.h"
32 
33 #include <errno.h>
34 #include <glib.h>
35 #include <gvm/base/prefs.h> /* for prefs_get() */
36 #include <gvm/base/proctitle.h>
37 #include <gvm/util/nvticache.h> /* for nvticache_new */
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/shm.h> /* for shmget */
42 #include <sys/time.h>
43 #include <sys/wait.h>
44 
45 #undef G_LOG_DOMAIN
46 
49 #define G_LOG_DOMAIN "sd main"
50 
67 GSList *
68 collect_nvts (const char *folder, const char *subdir, GSList *files)
69 {
70  GDir *dir;
71  const gchar *fname;
72 
73  if (folder == NULL)
74  return files;
75 
76  dir = g_dir_open (folder, 0, NULL);
77  if (dir == NULL)
78  return files;
79 
80  fname = g_dir_read_name (dir);
81  while (fname)
82  {
83  char *path;
84 
85  path = g_build_filename (folder, fname, NULL);
86  if (g_file_test (path, G_FILE_TEST_IS_DIR))
87  {
88  char *new_folder, *new_subdir;
89 
90  new_folder = g_build_filename (folder, fname, NULL);
91  new_subdir = g_build_filename (subdir, fname, NULL);
92 
93  files = collect_nvts (new_folder, new_subdir, files);
94 
95  if (new_folder)
96  g_free (new_folder);
97  if (new_subdir)
98  g_free (new_subdir);
99  }
100  else if (g_str_has_suffix (fname, ".nasl"))
101  files = g_slist_prepend (files, g_build_filename (subdir, fname, NULL));
102  g_free (path);
103  fname = g_dir_read_name (dir);
104  }
105 
106  g_dir_close (dir);
107  return files;
108 }
109 
110 int
111 calculate_eta (struct timeval start_time, int loaded, int total)
112 {
113  struct timeval current_time;
114  int elapsed, remaining;
115 
116  if (start_time.tv_sec == 0)
117  return 0;
118 
119  gettimeofday (&current_time, NULL);
120  elapsed = current_time.tv_sec - start_time.tv_sec;
121  remaining = total - loaded;
122  return (remaining * elapsed) / loaded;
123 }
124 
125 static int *loading_shm = NULL;
126 static int loading_shmid = 0;
127 
128 /*
129  * @brief Initializes the shared memory data used to report plugins loading
130  * progress to other processes.
131  */
132 void
134 {
135  int shm_key;
136 
137  if (loading_shm)
138  return;
139 
140  shm_key = rand () + 1;
141  /*
142  * Create shared memory segment if it doesn't exist.
143  * This will be used to communicate current plugins loading progress to other
144  * processes.
145  * loading_shm[0]: Number of loaded plugins.
146  * loading_shm[1]: Total number of plugins.
147  */
148  loading_shmid = shmget (shm_key, sizeof (int) * 2, IPC_CREAT | 0600);
149  if (loading_shmid < 0)
150  perror ("shmget");
151  loading_shm = shmat (loading_shmid, NULL, 0);
152  if (loading_shm == (void *) -1)
153  {
154  perror ("shmat");
155  loading_shm = NULL;
156  }
157  else
158  bzero (loading_shm, sizeof (int) * 2);
159 }
160 
161 /*
162  * @brief Destroys the shared memory data used to report plugins loading
163  * progress to other processes.
164  */
165 void
167 {
168  if (loading_shm)
169  {
170  shmdt (loading_shm);
171  if (shmctl (loading_shmid, IPC_RMID, NULL))
172  perror ("shmctl");
173  loading_shm = NULL;
174  loading_shmid = 0;
175  }
176 }
177 
178 /*
179  * @brief Gives current number of loaded plugins.
180  *
181  * @return Number of loaded plugins, 0 if initialization wasn't successful.
182  */
183 int
185 {
186  return loading_shm ? loading_shm[0] : 0;
187 }
188 
189 /*
190  * @brief Gives the total number of plugins to be loaded.
191  *
192  * @return Total of loaded plugins, 0 if initialization wasn't successful.
193  */
194 int
196 {
197  return loading_shm ? loading_shm[1] : 0;
198 }
199 
200 /*
201  * @brief Sets number of loaded plugins.
202  *
203  * @param[in] current Number of loaded plugins.
204  */
205 void
207 {
208  if (loading_shm)
209  loading_shm[0] = current;
210 }
211 
212 /*
213  * @brief Sets total number of plugins to be loaded.
214  *
215  * @param[in] total Total number of plugins
216  */
217 void
219 {
220  if (loading_shm)
221  loading_shm[1] = total;
222 }
223 
224 /*
225  * @brief Clean leftover NVTs.
226  *
227  * @param[in] num_files Number of NVT files found in the folder.
228  */
229 static void
230 cleanup_leftovers (int num_files)
231 {
232  size_t count;
233  GSList *oids, *element;
234 
235  proctitle_set ("openvas: Cleaning leftover NVTs.");
236 
237  count = nvticache_count ();
238  if ((int) count <= num_files)
239  return;
240 
241  oids = element = nvticache_get_oids ();
242  while (element)
243  {
244  char *path = nvticache_get_src (element->data);
245 
246  if (!g_file_test (path, G_FILE_TEST_EXISTS))
247  nvticache_delete (element->data);
248  g_free (path);
249  element = element->next;
250  }
251  g_slist_free_full (oids, g_free);
252 }
253 
254 static void
256 {
257  GSList *files = NULL, *f;
258  int loaded_files = 0, num_files = 0;
259  struct timeval start_time;
260 
261  openvas_signal (SIGTERM, SIG_DFL);
262  if (folder == NULL)
263  {
264  g_debug ("%s:%d : folder == NULL", __FILE__, __LINE__);
265  g_debug ("Could not determine the value of <plugins_folder>. "
266  " Check %s\n",
267  (char *) prefs_get ("config_file"));
268  exit (1);
269  }
270 
271  files = collect_nvts (folder, "", files);
272  num_files = g_slist_length (files);
273 
274  /*
275  * Add the plugins
276  */
277 
278  if (gettimeofday (&start_time, NULL))
279  {
280  bzero (&start_time, sizeof (start_time));
281  g_debug ("gettimeofday: %s", strerror (errno));
282  }
283  f = files;
284  set_total_loading_plugins (num_files);
285  while (f != NULL)
286  {
287  static int err_count = 0;
288  char *name = f->data;
289 
290  loaded_files++;
291  if (loaded_files % 50 == 0)
292  {
293  int percentile, eta;
294 
295  set_current_loading_plugins (loaded_files);
296  percentile = (loaded_files * 100) / num_files;
297  eta = calculate_eta (start_time, loaded_files, num_files);
298  proctitle_set ("openvas: Reloaded %d of %d NVTs"
299  " (%d%% / ETA: %02d:%02d)",
300  loaded_files, num_files, percentile, eta / 60,
301  eta % 60);
302  }
303  if (prefs_get_bool ("log_plugins_name_at_load"))
304  g_message ("Loading %s", name);
305  if (g_str_has_suffix (name, ".nasl"))
306  {
307  if (nasl_plugin_add (folder, name))
308  err_count++;
309  }
310 
311  if (err_count == 20)
312  {
313  g_debug ("Stopped loading plugins: High number of errors.");
314  proctitle_set ("openvas: Error loading NVTs.");
315  g_slist_free_full (files, g_free);
316  exit (1);
317  }
318  f = g_slist_next (f);
319  }
320 
321  cleanup_leftovers (num_files);
322  g_slist_free_full (files, g_free);
323  nasl_clean_inc ();
324 
325  proctitle_set ("openvas: Reloaded all the NVTs.");
326 
327  exit (0);
328 }
329 
330 static void
332 {
333  const gchar *pref_include_folders;
334 
335  add_nasl_inc_dir (""); // for absolute and relative paths
336  pref_include_folders = prefs_get ("include_folders");
337  if (pref_include_folders != NULL)
338  {
339  gchar **include_folders = g_strsplit (pref_include_folders, ":", 0);
340  unsigned int i = 0;
341 
342  for (i = 0; i < g_strv_length (include_folders); i++)
343  {
344  int result = add_nasl_inc_dir (include_folders[i]);
345  if (result < 0)
346  g_debug ("Could not add %s to the list of include folders.\n"
347  "Make sure %s exists and is a directory.\n",
348  include_folders[i], include_folders[i]);
349  }
350 
351  g_strfreev (include_folders);
352  }
353 }
358 int
360 {
361  const char *plugins_folder = prefs_get ("plugins_folder");
362 
363  if (nvticache_init (plugins_folder, prefs_get ("db_address")))
364  {
365  g_debug ("Failed to initialize nvti cache.");
366  return -1;
367  }
368  include_dirs ();
369  return 0;
370 }
371 
372 /*
373  * main function for loading all the plugins
374  */
375 int
377 {
378  int ret = 0;
379  pid_t child_pid;
380  const char *plugins_folder = prefs_get ("plugins_folder");
381 
382  ret = plugins_cache_init ();
383  if (ret)
384  return ret;
385 
386  child_pid = create_process (plugins_reload_from_dir, (void *) plugins_folder);
387  waitpid (child_pid, &ret, 0);
388  nvticache_save ();
389  return ret;
390 }
processes.h
processes.c header.
total_loading_plugins
int total_loading_plugins(void)
Definition: pluginload.c:195
destroy_loading_shm
void destroy_loading_shm(void)
Definition: pluginload.c:166
init_loading_shm
void init_loading_shm(void)
Definition: pluginload.c:133
add_nasl_inc_dir
int add_nasl_inc_dir(const char *)
Adds the given string as directory for searching for includes.
Definition: nasl_grammar.tab.c:2738
sighand.h
headerfile for sighand.c.
timeval
struct timeval timeval(unsigned long val)
Definition: nasl_builtin_synscan.c:105
set_current_loading_plugins
void set_current_loading_plugins(int current)
Definition: pluginload.c:206
current_loading_plugins
int current_loading_plugins(void)
Definition: pluginload.c:184
include_dirs
static void include_dirs(void)
Definition: pluginload.c:331
loading_shmid
static int loading_shmid
Definition: pluginload.c:126
name
const char * name
Definition: nasl_init.c:377
openvas_signal
void(*)(int) openvas_signal(int signum, void(*handler)(int))
Definition: sighand.c:87
pluginload.h
pluginload.c header.
nasl_plugin_add
int nasl_plugin_add(char *folder, char *filename)
Add one .nasl plugin to the plugin list.
Definition: nasl_plugins.c:99
loading_shm
static int * loading_shm
Definition: pluginload.c:125
utils.h
utils.c headerfile.
plugins_init
int plugins_init(void)
Definition: pluginload.c:376
calculate_eta
int calculate_eta(struct timeval start_time, int loaded, int total)
Definition: pluginload.c:111
create_process
pid_t create_process(process_func_t function, void *argument)
Create a new process (fork).
Definition: processes.c:97
collect_nvts
GSList * collect_nvts(const char *folder, const char *subdir, GSList *files)
Collects all NVT files in a directory and recurses into subdirs.
Definition: pluginload.c:68
plugins_reload_from_dir
static void plugins_reload_from_dir(void *folder)
Definition: pluginload.c:255
cleanup_leftovers
static void cleanup_leftovers(int num_files)
Definition: pluginload.c:230
set_total_loading_plugins
void set_total_loading_plugins(int total)
Definition: pluginload.c:218
plugins_cache_init
int plugins_cache_init(void)
Main function for nvticache initialization without loading the plugins.
Definition: pluginload.c:359
nasl_clean_inc
void nasl_clean_inc(void)
Definition: nasl_grammar.tab.c:3003