-
Notifications
You must be signed in to change notification settings - Fork 16
/
output.c
101 lines (83 loc) · 2.23 KB
/
output.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <dlfcn.h>
#include <netinet/in.h>
#include <ncrx.h>
#include "include/common.h"
#include "include/msgbuf-struct.h"
#include "include/output.h"
static void *output_dlhandles[MAXOUTS];
static void (*outputs[MAXOUTS])(int, struct in6_addr *, struct msg_buf *,
struct ncrx_msg *);
static int nr_outputs;
int register_output_module(char *path, int nr_workers)
{
void *dl, *dlsym_addr;
int (*mod_init)(int);
int ret;
if (nr_outputs == MAXOUTS) {
warn("Too many output modules!\n");
return -1;
}
log("Loading module '%s'\n", path);
dl = dlopen(path, RTLD_NOW|RTLD_LOCAL);
if (!dl) {
warn("Can't open '%s': %s", path, dlerror());
return -1;
}
dlsym_addr = dlsym(dl, "netconsd_output_handler");
if (!dlsym_addr) {
warn("Can't find handler sym in '%s': %s", path, dlerror());
goto err_close;
}
mod_init = dlsym(dl, "netconsd_output_init");
if (mod_init) {
log("Calling mod_init() for '%s'\n", path);
ret = mod_init(nr_workers);
if (ret) {
warn("mod_init() for '%s' failed: %d\n", path, ret);
goto err_close;
}
}
log("Module '%s' registered (#%d@%p)\n", path, nr_outputs, dlsym_addr);
output_dlhandles[nr_outputs] = dl;
outputs[nr_outputs] = dlsym_addr;
nr_outputs++;
return 0;
err_close:
dlclose(dl);
return -1;
}
void destroy_output_modules(void)
{
int i, ret;
void (*mod_exit)(void);
char path[PATH_MAX] = {0};
for (i = 0; i < nr_outputs; i++) {
if (dlinfo(output_dlhandles[i], RTLD_DI_ORIGIN, path))
strncpy(path, dlerror(), PATH_MAX - 1);
mod_exit = dlsym(output_dlhandles[i], "netconsd_output_exit");
if (mod_exit) {
log("Calling mod_exit() for '%s'\n", path);
mod_exit();
}
log("Unloading module '%s' (#%d@%p)\n", path, i, outputs[i]);
ret = dlclose(output_dlhandles[i]);
if (ret)
warn("dlclose() failed: %s\n", dlerror());
}
}
void execute_output_pipeline(int thread_nr, struct in6_addr *src,
struct msg_buf *buf, struct ncrx_msg *msg)
{
int i;
for (i = 0; i < nr_outputs; i++)
outputs[i](thread_nr, src, buf, msg);
}