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