]> git.proxmox.com Git - mirror_frr.git/blame - lib/module.c
Merge pull request #2099 from qlyoung/fix-cpu-thread-hist-race
[mirror_frr.git] / lib / module.c
CommitLineData
30771d65
DL
1/*
2 * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include "config.h"
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28#include <unistd.h>
29#include <limits.h>
30#include <dlfcn.h>
31
32#include "module.h"
33#include "memory.h"
34#include "version.h"
35
36DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name")
37DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments")
38
39static struct frrmod_info frrmod_default_info = {
40 .name = "libfrr",
41 .version = FRR_VERSION,
42 .description = "libfrr core module",
43};
44union _frrmod_runtime_u frrmod_default = {
996c9314
LB
45 .r =
46 {
47 .info = &frrmod_default_info,
48 .finished_loading = 1,
49 },
30771d65
DL
50};
51
52// if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE)
53// union _frrmod_runtime_u _frrmod_this_module
54// __attribute__((weak, alias("frrmod_default")));
55// elif defined(HAVE_SYS_WEAK_ALIAS_PRAGMA)
56#pragma weak _frrmod_this_module = frrmod_default
57// else
58// error need weak symbol support
59// endif
60
61struct frrmod_runtime *frrmod_list = &frrmod_default.r;
62static struct frrmod_runtime **frrmod_last = &frrmod_default.r.next;
63static const char *execname = NULL;
64
65void frrmod_init(struct frrmod_runtime *modinfo)
66{
67 modinfo->finished_loading = 1;
68 *frrmod_last = modinfo;
69 frrmod_last = &modinfo->next;
70
71 execname = modinfo->info->name;
72}
73
d62a17ae 74struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err,
75 size_t err_len)
30771d65
DL
76{
77 void *handle = NULL;
78 char name[PATH_MAX], fullpath[PATH_MAX], *args;
79 struct frrmod_runtime *rtinfo, **rtinfop;
80 const struct frrmod_info *info;
81
82 snprintf(name, sizeof(name), "%s", spec);
83 args = strchr(name, ':');
84 if (args)
85 *args++ = '\0';
86
87 if (!strchr(name, '/')) {
88 if (!handle && execname) {
d62a17ae 89 snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", dir,
90 execname, name);
30771d65
DL
91 handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
92 }
93 if (!handle) {
d62a17ae 94 snprintf(fullpath, sizeof(fullpath), "%s/%s.so", dir,
95 name);
30771d65
DL
96 handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
97 }
98 }
99 if (!handle) {
100 snprintf(fullpath, sizeof(fullpath), "%s", name);
101 handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
102 }
103 if (!handle) {
104 if (err)
105 snprintf(err, err_len,
d62a17ae 106 "loading module \"%s\" failed: %s", name,
107 dlerror());
30771d65
DL
108 return NULL;
109 }
110
111 rtinfop = dlsym(handle, "frr_module");
112 if (!rtinfop) {
113 dlclose(handle);
114 if (err)
115 snprintf(err, err_len,
d62a17ae 116 "\"%s\" is not an FRR module: %s", name,
117 dlerror());
30771d65
DL
118 return NULL;
119 }
120 rtinfo = *rtinfop;
121 rtinfo->load_name = XSTRDUP(MTYPE_MODULE_LOADNAME, name);
122 rtinfo->dl_handle = handle;
123 if (args)
124 rtinfo->load_args = XSTRDUP(MTYPE_MODULE_LOADARGS, args);
125 info = rtinfo->info;
126
127 if (rtinfo->finished_loading) {
128 dlclose(handle);
129 if (err)
d62a17ae 130 snprintf(err, err_len, "module \"%s\" already loaded",
131 name);
30771d65
DL
132 goto out_fail;
133 }
134
135 if (info->init && info->init()) {
136 dlclose(handle);
137 if (err)
138 snprintf(err, err_len,
d62a17ae 139 "module \"%s\" initialisation failed", name);
30771d65
DL
140 goto out_fail;
141 }
142
143 rtinfo->finished_loading = 1;
144
145 *frrmod_last = rtinfo;
146 frrmod_last = &rtinfo->next;
147 return rtinfo;
148
149out_fail:
150 if (rtinfo->load_args)
151 XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args);
152 XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name);
153 return NULL;
154}
155
156#if 0
157void frrmod_unload(struct frrmod_runtime *module)
158{
159}
160#endif