OpenVAS Scanner 23.40.3
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
26#define G_LOG_DOMAIN "lib misc"
27
28// default preallocation length for ipc_contexts
29#define IPC_CONTEXTS_CAP_STEP 10
30
45int
46ipc_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
67int
68ipc_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
94char *
95ipc_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
115int
116ipc_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
139struct 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:
152 break;
153 }
154 if (!context)
155 goto free_exit;
156 ctx->context = context;
157 return ctx;
158
159free_exit:
160 if (ctx != NULL)
161 free (ctx);
162exit:
163 return NULL;
164}
165
174struct 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
247struct 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;
257exit:
258 return ctxs;
259free_and_exit:
260 if (ctxs != NULL)
261 free (ctxs);
262 return NULL;
263}
264
273struct 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;
293exit_error:
294 return NULL;
295}
296
304int
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}
int ipc_close(struct ipc_context *context)
closes given context
Definition ipc.c:116
struct ipc_context * ipc_init(enum ipc_protocol type, enum ipc_relation relation)
initializes a new context.
Definition ipc.c:140
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
int ipc_destroy(struct ipc_context *context)
destroys given context
Definition ipc.c:68
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
struct ipc_contexts * ipc_contexts_init(int cap)
initializes ipc_contexts with a given preallocated capacity.
Definition ipc.c:248
struct ipc_contexts * ipc_add_context(struct ipc_contexts *ctxs, struct ipc_context *ctx)
adds a given context to contexts
Definition ipc.c:274
char * ipc_retrieve(struct ipc_context *context, enum ipc_relation from)
retrieves data for the relation based on the context
Definition ipc.c:95
int ipc_destroy_contexts(struct ipc_contexts *ctxs)
destroys given contexts
Definition ipc.c:305
#define IPC_CONTEXTS_CAP_STEP
Definition ipc.c:29
ipc_protocol
Definition ipc.h:12
@ IPC_PIPE
Definition ipc.h:13
ipc_relation
Definition ipc.h:17
@ IPC_CHILD
Definition ipc.h:19
@ IPC_MAIN
Definition ipc.h:18
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
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
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
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
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
static pid_t pid
void * malloc(YYSIZE_T)
void free(void *)
uint8_t len
void * context
Definition ipc.h:37
enum ipc_protocol type
Definition ipc.h:33
unsigned int closed
Definition ipc.h:35
enum ipc_relation relation
Definition ipc.h:34
pid_t pid
Definition ipc.h:36
struct ipc_context * ctxs
Definition ipc.h:44
int cap
Definition ipc.h:43
ipc_process_func pre_func
Definition ipc.h:52
void * pre_arg
Definition ipc.h:57
void * func_arg
Definition ipc.h:58
void * shared_context
Definition ipc.h:60
ipc_process_func post_func
Definition ipc.h:56
ipc_process_func func
Definition ipc.h:54