OpenVAS Scanner  22.7.9
ipc.c
Go to the documentation of this file.
1 /* SPDX-FileCopyrightText: 2023 Greenbone AG
2  *
3  * SPDX-License-Identifier: GPL-2.0-or-later
4  */
5 
6 #include "ipc.h"
7 
8 #include "ipc_pipe.h"
9 
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <glib.h>
13 #include <gvm/base/logging.h>
14 #include <json-glib/json-glib.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 
22 #undef G_LOG_DOMAIN
23 
26 #define G_LOG_DOMAIN "lib misc"
27 
28 // default preallocation length for ipc_contexts
29 #define IPC_CONTEXTS_CAP_STEP 10
30 
45 int
46 ipc_send (struct ipc_context *context, enum ipc_relation to, const char *msg,
47  size_t len)
48 {
49  (void) to;
50  if (context == NULL || msg == NULL)
51  return -2;
52  switch (context->type)
53  {
54  case IPC_PIPE:
55  return ipc_pipe_send (context->context, msg, len);
56  };
57  return -2;
58 }
59 
67 int
68 ipc_destroy (struct ipc_context *context)
69 {
70  int rc = 0;
71  if (context == NULL)
72  return -1;
73  switch (context->type)
74  {
75  case IPC_PIPE:
76  rc = ipc_pipe_destroy (context->context);
77  break;
78  }
79  g_free (context);
80  return rc;
81 }
82 
94 char *
95 ipc_retrieve (struct ipc_context *context, enum ipc_relation from)
96 {
97  (void) from;
98  if (context == NULL)
99  return NULL;
100  switch (context->type)
101  {
102  case IPC_PIPE:
103  return ipc_pipe_retrieve (context->context);
104  };
105  return NULL;
106 }
107 
115 int
116 ipc_close (struct ipc_context *context)
117 {
118  int rc = -1;
119  if (context == NULL || context->closed == 1)
120  return rc;
121  switch (context->type)
122  {
123  case IPC_PIPE:
124  rc = ipc_pipe_close (context->context);
125  context->closed = 1;
126  }
127  return rc;
128 }
129 
139 struct ipc_context *
141 {
142  struct ipc_context *ctx = NULL;
143  void *context = NULL;
144  (void) relation;
145  if ((ctx = calloc (1, sizeof (*ctx))) == NULL)
146  goto exit;
147  ctx->type = type;
148  switch (type)
149  {
150  case IPC_PIPE:
151  context = ipc_init_pipe ();
152  break;
153  }
154  if (!context)
155  goto free_exit;
156  ctx->context = context;
157  return ctx;
158 
159 free_exit:
160  if (ctx != NULL)
161  free (ctx);
162 exit:
163  return NULL;
164 }
165 
174 struct ipc_context *
176 {
177  struct ipc_context *pctx = NULL, *cctx = NULL;
178  pid_t pid;
179  if (exec_ctx.func == NULL)
180  return NULL;
181  switch (type)
182  {
183  case IPC_PIPE:
184  if ((pctx = ipc_init (type, IPC_MAIN)) == NULL)
185  {
186  return NULL;
187  }
188  }
189 
190  gvm_log_lock ();
191  pid = fork ();
192  gvm_log_unlock ();
193  /* fork error */
194  if (pid < 0)
195  {
196  ipc_destroy (pctx);
197  return NULL;
198  }
199  // we are the child process and execute given function
200  if (pid == 0)
201  {
202  if (pctx != NULL)
203  cctx = pctx;
204  else if ((cctx = ipc_init (type, IPC_CHILD)) == NULL)
205  {
206  exit (1);
207  }
208 
209  if (exec_ctx.pre_func != NULL)
210  (*exec_ctx.pre_func) (cctx, exec_ctx.pre_arg);
211  (*exec_ctx.func) (cctx, exec_ctx.func_arg);
212  if (exec_ctx.post_func != NULL)
213  (*exec_ctx.post_func) (cctx, exec_ctx.pre_arg);
214  switch (type)
215  {
216  case IPC_PIPE:
217  ipc_destroy (pctx);
218  break;
219  }
220  exit (0);
221  }
222 
223  if (pctx == NULL)
224  {
225  if ((pctx = malloc (sizeof (*pctx))) == NULL)
226  {
227  return NULL;
228  }
229  pctx->relation = IPC_MAIN;
230  pctx->type = type;
231  pctx->context = exec_ctx.shared_context;
232  }
233  // we are the parent process and return the id of the child process for
234  // observation
235  pctx->pid = pid;
236  return pctx;
237 }
238 
247 struct ipc_contexts *
249 {
250  struct ipc_contexts *ctxs = NULL;
251  if ((ctxs = malloc (sizeof (*ctxs))) == NULL)
252  goto exit;
253  ctxs->len = 0;
254  ctxs->cap = cap > 0 ? cap : IPC_CONTEXTS_CAP_STEP;
255  if ((ctxs->ctxs = malloc (ctxs->cap * sizeof (*ctxs->ctxs))) == NULL)
256  goto free_and_exit;
257 exit:
258  return ctxs;
259 free_and_exit:
260  if (ctxs != NULL)
261  free (ctxs);
262  return NULL;
263 }
264 
273 struct ipc_contexts *
275 {
276  if (ctxs == NULL)
277  goto exit_error;
278  if (ctx == NULL)
279  goto exit_error;
280  if (ctxs->len == ctxs->cap)
281  {
282  ctxs->cap = ctxs->cap + IPC_CONTEXTS_CAP_STEP;
283  ctxs->ctxs = realloc (ctxs->ctxs, ctxs->cap * sizeof (*ctxs->ctxs));
284  if (ctxs->ctxs == NULL)
285  {
286  // NOTE: the caller must free ctxs->ctxs in this case.
287  goto exit_error;
288  }
289  }
290  ctxs->ctxs[ctxs->len] = *ctx;
291  ctxs->len += 1;
292  return ctxs;
293 exit_error:
294  return NULL;
295 }
296 
304 int
306 {
307  int i, rc = 0;
308  if (ctxs == NULL)
309  return rc;
310  for (i = 0; i < ctxs->len; i++)
311  {
312  if (ipc_close (&ctxs->ctxs[i]) < 0)
313  rc = -1;
314  }
315  free (ctxs->ctxs);
316  free (ctxs);
317  return rc;
318 }
ipc_exec_context::pre_arg
void * pre_arg
Definition: ipc.h:57
ipc_add_context
struct ipc_contexts * ipc_add_context(struct ipc_contexts *ctxs, struct ipc_context *ctx)
adds a given context to contexts
Definition: ipc.c:274
IPC_PIPE
@ IPC_PIPE
Definition: ipc.h:13
malloc
void * malloc(YYSIZE_T)
ipc_context::pid
pid_t pid
Definition: ipc.h:36
ipc_pipe_retrieve
char * ipc_pipe_retrieve(struct ipc_pipe_context *context)
retrieves message from the given context. Do not use this method directly, use ipc_retrieve of ipc....
Definition: ipc_pipe.c:50
ipc_retrieve
char * ipc_retrieve(struct ipc_context *context, enum ipc_relation from)
retrieves data for the relation based on the context
Definition: ipc.c:95
ipc_pipe_close
int ipc_pipe_close(struct ipc_pipe_context *context)
closes given context. Do not use this method directly, use ipc_close of ipc.h instead.
Definition: ipc_pipe.c:85
ipc_pipe.h
ipc_relation
ipc_relation
Definition: ipc.h:17
ipc_contexts_init
struct ipc_contexts * ipc_contexts_init(int cap)
initializes ipc_contexts with a given preallocated capacity.
Definition: ipc.c:248
ipc_context::closed
unsigned int closed
Definition: ipc.h:35
ipc_send
int ipc_send(struct ipc_context *context, enum ipc_relation to, const char *msg, size_t len)
sends given msg to the target based on the given context
Definition: ipc.c:46
ipc_context::type
enum ipc_protocol type
Definition: ipc.h:33
pid
static pid_t pid
Definition: nasl_cmd_exec.c:39
len
uint8_t len
Definition: nasl_packet_forgery.c:1
ipc_exec_context
Definition: ipc.h:50
ipc_exec_context::post_func
ipc_process_func post_func
Definition: ipc.h:56
ipc_destroy_contexts
int ipc_destroy_contexts(struct ipc_contexts *ctxs)
destroys given contexts
Definition: ipc.c:305
IPC_MAIN
@ IPC_MAIN
Definition: ipc.h:18
ipc_context::relation
enum ipc_relation relation
Definition: ipc.h:34
ipc.h
ipc_pipe_send
int ipc_pipe_send(struct ipc_pipe_context *context, const char *msg, int len)
sends given msg via the given context. Do not use this method directly, use ipc_send of ipc....
Definition: ipc_pipe.c:32
IPC_CHILD
@ IPC_CHILD
Definition: ipc.h:19
ipc_contexts
Definition: ipc.h:41
ipc_context
Definition: ipc.h:32
ipc_contexts::cap
int cap
Definition: ipc.h:43
ipc_pipe_destroy
int ipc_pipe_destroy(struct ipc_pipe_context *context)
destroys given context. Do not use this method directly, use ipc_destroy of ipc.h instead.
Definition: ipc_pipe.c:110
ipc_exec_context::shared_context
void * shared_context
Definition: ipc.h:60
ipc_close
int ipc_close(struct ipc_context *context)
closes given context
Definition: ipc.c:116
ipc_exec_context::func
ipc_process_func func
Definition: ipc.h:54
ipc_exec_context::func_arg
void * func_arg
Definition: ipc.h:58
ipc_init
struct ipc_context * ipc_init(enum ipc_protocol type, enum ipc_relation relation)
initializes a new context.
Definition: ipc.c:140
ipc_contexts::ctxs
struct ipc_context * ctxs
Definition: ipc.h:44
IPC_CONTEXTS_CAP_STEP
#define IPC_CONTEXTS_CAP_STEP
Definition: ipc.c:29
ipc_destroy
int ipc_destroy(struct ipc_context *context)
destroys given context
Definition: ipc.c:68
free
void free(void *)
ipc_exec_as_process
struct ipc_context * ipc_exec_as_process(enum ipc_protocol type, struct ipc_exec_context exec_ctx)
runs given functions with the given protocol type.
Definition: ipc.c:175
ipc_protocol
ipc_protocol
Definition: ipc.h:12
ipc_init_pipe
struct ipc_pipe_context * ipc_init_pipe(void)
initializes a new context. Do not use this method directly, use ipc_init of ipc.h instead.
Definition: ipc_pipe.c:132
ipc_exec_context::pre_func
ipc_process_func pre_func
Definition: ipc.h:52
ipc_context::context
void * context
Definition: ipc.h:37