]> git.proxmox.com Git - mirror_frr.git/blob - lib/module.c
Merge pull request #8301 from donaldsharp/isis_spacing
[mirror_frr.git] / lib / module.c
1 /*
2 * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include "config.h"
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <limits.h>
24 #include <dlfcn.h>
25
26 #include "module.h"
27 #include "memory.h"
28 #include "version.h"
29
30 DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name");
31 DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments");
32
33 static struct frrmod_info frrmod_default_info = {
34 .name = "libfrr",
35 .version = FRR_VERSION,
36 .description = "libfrr core module",
37 };
38 union _frrmod_runtime_u frrmod_default = {
39 .r =
40 {
41 .info = &frrmod_default_info,
42 .finished_loading = 1,
43 },
44 };
45
46 XREF_SETUP();
47
48 // if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE)
49 // union _frrmod_runtime_u _frrmod_this_module
50 // __attribute__((weak, alias("frrmod_default")));
51 // elif defined(HAVE_SYS_WEAK_ALIAS_PRAGMA)
52 #pragma weak _frrmod_this_module = frrmod_default
53 // else
54 // error need weak symbol support
55 // endif
56
57 struct frrmod_runtime *frrmod_list = &frrmod_default.r;
58 static struct frrmod_runtime **frrmod_last = &frrmod_default.r.next;
59 static const char *execname = NULL;
60
61 void frrmod_init(struct frrmod_runtime *modinfo)
62 {
63 modinfo->finished_loading = true;
64 *frrmod_last = modinfo;
65 frrmod_last = &modinfo->next;
66
67 execname = modinfo->info->name;
68 }
69
70 struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err,
71 size_t err_len)
72 {
73 void *handle = NULL;
74 char name[PATH_MAX], fullpath[PATH_MAX * 2], *args;
75 struct frrmod_runtime *rtinfo, **rtinfop;
76 const struct frrmod_info *info;
77
78 snprintf(name, sizeof(name), "%s", spec);
79 args = strchr(name, ':');
80 if (args)
81 *args++ = '\0';
82
83 if (!strchr(name, '/')) {
84 if (execname) {
85 snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", dir,
86 execname, name);
87 handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
88 }
89 if (!handle) {
90 snprintf(fullpath, sizeof(fullpath), "%s/%s.so", dir,
91 name);
92 handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
93 }
94 }
95 if (!handle) {
96 snprintf(fullpath, sizeof(fullpath), "%s", name);
97 handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
98 }
99 if (!handle) {
100 if (err)
101 snprintf(err, err_len,
102 "loading module \"%s\" failed: %s", name,
103 dlerror());
104 return NULL;
105 }
106
107 rtinfop = dlsym(handle, "frr_module");
108 if (!rtinfop) {
109 dlclose(handle);
110 if (err)
111 snprintf(err, err_len,
112 "\"%s\" is not an FRR module: %s", name,
113 dlerror());
114 return NULL;
115 }
116 rtinfo = *rtinfop;
117 rtinfo->load_name = XSTRDUP(MTYPE_MODULE_LOADNAME, name);
118 rtinfo->dl_handle = handle;
119 if (args)
120 rtinfo->load_args = XSTRDUP(MTYPE_MODULE_LOADARGS, args);
121 info = rtinfo->info;
122
123 if (rtinfo->finished_loading) {
124 dlclose(handle);
125 if (err)
126 snprintf(err, err_len, "module \"%s\" already loaded",
127 name);
128 goto out_fail;
129 }
130
131 if (info->init && info->init()) {
132 dlclose(handle);
133 if (err)
134 snprintf(err, err_len,
135 "module \"%s\" initialisation failed", name);
136 goto out_fail;
137 }
138
139 rtinfo->finished_loading = true;
140
141 *frrmod_last = rtinfo;
142 frrmod_last = &rtinfo->next;
143 return rtinfo;
144
145 out_fail:
146 XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args);
147 XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name);
148 return NULL;
149 }
150
151 #if 0
152 void frrmod_unload(struct frrmod_runtime *module)
153 {
154 }
155 #endif