]> git.proxmox.com Git - mirror_frr.git/blob - lib/module.c
*: fix compiler warnings
[mirror_frr.git] / lib / module.c
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
36 DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name")
37 DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments")
38
39 static struct frrmod_info frrmod_default_info = {
40 .name = "libfrr",
41 .version = FRR_VERSION,
42 .description = "libfrr core module",
43 };
44 union _frrmod_runtime_u frrmod_default = {
45 .r = {
46 .info = &frrmod_default_info,
47 .finished_loading = 1,
48 },
49 };
50
51 // if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE)
52 // union _frrmod_runtime_u _frrmod_this_module
53 // __attribute__((weak, alias("frrmod_default")));
54 // elif defined(HAVE_SYS_WEAK_ALIAS_PRAGMA)
55 #pragma weak _frrmod_this_module = frrmod_default
56 // else
57 // error need weak symbol support
58 // endif
59
60 struct frrmod_runtime *frrmod_list = &frrmod_default.r;
61 static struct frrmod_runtime **frrmod_last = &frrmod_default.r.next;
62 static const char *execname = NULL;
63
64 void frrmod_init(struct frrmod_runtime *modinfo)
65 {
66 modinfo->finished_loading = 1;
67 *frrmod_last = modinfo;
68 frrmod_last = &modinfo->next;
69
70 execname = modinfo->info->name;
71 }
72
73 struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err,
74 size_t err_len)
75 {
76 void *handle = NULL;
77 char name[PATH_MAX], fullpath[PATH_MAX], *args;
78 struct frrmod_runtime *rtinfo, **rtinfop;
79 const struct frrmod_info *info;
80
81 snprintf(name, sizeof(name), "%s", spec);
82 args = strchr(name, ':');
83 if (args)
84 *args++ = '\0';
85
86 if (!strchr(name, '/')) {
87 if (!handle && execname) {
88 snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", dir,
89 execname, name);
90 handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
91 }
92 if (!handle) {
93 snprintf(fullpath, sizeof(fullpath), "%s/%s.so", dir,
94 name);
95 handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
96 }
97 }
98 if (!handle) {
99 snprintf(fullpath, sizeof(fullpath), "%s", name);
100 handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
101 }
102 if (!handle) {
103 if (err)
104 snprintf(err, err_len,
105 "loading module \"%s\" failed: %s", name,
106 dlerror());
107 return NULL;
108 }
109
110 rtinfop = dlsym(handle, "frr_module");
111 if (!rtinfop) {
112 dlclose(handle);
113 if (err)
114 snprintf(err, err_len,
115 "\"%s\" is not an FRR module: %s", name,
116 dlerror());
117 return NULL;
118 }
119 rtinfo = *rtinfop;
120 rtinfo->load_name = XSTRDUP(MTYPE_MODULE_LOADNAME, name);
121 rtinfo->dl_handle = handle;
122 if (args)
123 rtinfo->load_args = XSTRDUP(MTYPE_MODULE_LOADARGS, args);
124 info = rtinfo->info;
125
126 if (rtinfo->finished_loading) {
127 dlclose(handle);
128 if (err)
129 snprintf(err, err_len, "module \"%s\" already loaded",
130 name);
131 goto out_fail;
132 }
133
134 if (info->init && info->init()) {
135 dlclose(handle);
136 if (err)
137 snprintf(err, err_len,
138 "module \"%s\" initialisation failed", name);
139 goto out_fail;
140 }
141
142 rtinfo->finished_loading = 1;
143
144 *frrmod_last = rtinfo;
145 frrmod_last = &rtinfo->next;
146 return rtinfo;
147
148 out_fail:
149 if (rtinfo->load_args)
150 XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args);
151 XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name);
152 return NULL;
153 }
154
155 #if 0
156 void frrmod_unload(struct frrmod_runtime *module)
157 {
158 }
159 #endif