back to topotato report
topotato coverage report
Current view: top level - lib - module.c (source / functions) Hit Total Coverage
Test: test_bgp_minimum_holdtime.py::TestBGPMinimumHoldtime Lines: 10 69 14.5 %
Date: 2023-02-24 18:37:25 Functions: 8 9 88.9 %

          Line data    Source code
       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 "lib/version.h"
      29             : #include "printfrr.h"
      30             : 
      31          12 : DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name");
      32          12 : DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments");
      33          12 : DEFINE_MTYPE_STATIC(LIB, MODULE_LOAD_ERR, "Module loading error");
      34             : 
      35             : static struct frrmod_info frrmod_default_info = {
      36             :         .name = "libfrr",
      37             :         .version = FRR_VERSION,
      38             :         .description = "libfrr core module",
      39             : };
      40             : union _frrmod_runtime_u frrmod_default = {
      41             :         .r =
      42             :                 {
      43             :                         .info = &frrmod_default_info,
      44             :                         .finished_loading = 1,
      45             :                 },
      46             : };
      47             : 
      48           4 : XREF_SETUP();
      49             : 
      50             : // if defined(HAVE_SYS_WEAK_ALIAS_ATTRIBUTE)
      51             : // union _frrmod_runtime_u _frrmod_this_module
      52             : //      __attribute__((weak, alias("frrmod_default")));
      53             : // elif defined(HAVE_SYS_WEAK_ALIAS_PRAGMA)
      54             : #pragma weak _frrmod_this_module = frrmod_default
      55             : // else
      56             : // error need weak symbol support
      57             : // endif
      58             : 
      59             : struct frrmod_runtime *frrmod_list = &frrmod_default.r;
      60             : static struct frrmod_runtime **frrmod_last = &frrmod_default.r.next;
      61             : static const char *execname = NULL;
      62             : 
      63           4 : void frrmod_init(struct frrmod_runtime *modinfo)
      64             : {
      65           4 :         modinfo->finished_loading = true;
      66           4 :         *frrmod_last = modinfo;
      67           4 :         frrmod_last = &modinfo->next;
      68             : 
      69           4 :         execname = modinfo->info->name;
      70           4 : }
      71             : 
      72             : /*
      73             :  * If caller wants error strings, it should define non-NULL pFerrlog
      74             :  * which will be called with 0-terminated error messages. These
      75             :  * messages will NOT contain newlines, and the (*pFerrlog)() function
      76             :  * could be called multiple times for a single call to frrmod_load().
      77             :  *
      78             :  * The (*pFerrlog)() function may copy these strings if needed, but
      79             :  * should expect them to be freed by frrmod_load() before frrmod_load()
      80             :  * returns.
      81             :  *
      82             :  * frrmod_load() is coded such that (*pFerrlog)() will be called only
      83             :  * in the case where frrmod_load() returns an error.
      84             :  */
      85           0 : struct frrmod_runtime *frrmod_load(const char *spec, const char *dir,
      86             :                                    void (*pFerrlog)(const void *, const char *),
      87             :                                    const void *pErrlogCookie)
      88             : {
      89           0 :         void *handle = NULL;
      90           0 :         char name[PATH_MAX], fullpath[PATH_MAX * 2], *args;
      91           0 :         struct frrmod_runtime *rtinfo, **rtinfop;
      92           0 :         const struct frrmod_info *info;
      93             : 
      94             : #define FRRMOD_LOAD_N_ERRSTR 10
      95           0 :         char *aErr[FRRMOD_LOAD_N_ERRSTR];
      96           0 :         unsigned int iErr = 0;
      97             : 
      98           0 :         memset(aErr, 0, sizeof(aErr));
      99             : 
     100             : #define ERR_RECORD(...)                                                        \
     101             :         do {                                                                   \
     102             :                 if (pFerrlog && (iErr < FRRMOD_LOAD_N_ERRSTR)) {               \
     103             :                         aErr[iErr++] = asprintfrr(MTYPE_MODULE_LOAD_ERR,       \
     104             :                                                   __VA_ARGS__);                \
     105             :                 }                                                              \
     106             :         } while (0)
     107             : 
     108             : #define ERR_REPORT                                                             \
     109             :         do {                                                                   \
     110             :                 if (pFerrlog) {                                                \
     111             :                         unsigned int i;                                        \
     112             :                                                                                \
     113             :                         for (i = 0; i < iErr; ++i) {                           \
     114             :                                 (*pFerrlog)(pErrlogCookie, aErr[i]);           \
     115             :                         }                                                      \
     116             :                 }                                                              \
     117             :         } while (0)
     118             : 
     119             : #define ERR_FREE                                                               \
     120             :         do {                                                                   \
     121             :                 unsigned int i;                                                \
     122             :                                                                                \
     123             :                 for (i = 0; i < iErr; ++i) {                                   \
     124             :                         XFREE(MTYPE_MODULE_LOAD_ERR, aErr[i]);                 \
     125             :                         aErr[i] = 0;                                           \
     126             :                 }                                                              \
     127             :                 iErr = 0;                                                      \
     128             :         } while (0)
     129             : 
     130           0 :         snprintf(name, sizeof(name), "%s", spec);
     131           0 :         args = strchr(name, ':');
     132           0 :         if (args)
     133           0 :                 *args++ = '\0';
     134             : 
     135           0 :         if (!strchr(name, '/')) {
     136           0 :                 if (execname) {
     137           0 :                         snprintf(fullpath, sizeof(fullpath), "%s/%s_%s.so", dir,
     138             :                                  execname, name);
     139           0 :                         handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
     140           0 :                         if (!handle)
     141           0 :                                 ERR_RECORD("loader error: dlopen(%s): %s",
     142             :                                            fullpath, dlerror());
     143             :                 }
     144             :                 if (!handle) {
     145           0 :                         snprintf(fullpath, sizeof(fullpath), "%s/%s.so", dir,
     146             :                                  name);
     147           0 :                         handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
     148           0 :                         if (!handle)
     149           0 :                                 ERR_RECORD("loader error: dlopen(%s): %s",
     150             :                                            fullpath, dlerror());
     151             :                 }
     152             :         }
     153             :         if (!handle) {
     154           0 :                 snprintf(fullpath, sizeof(fullpath), "%s", name);
     155           0 :                 handle = dlopen(fullpath, RTLD_NOW | RTLD_GLOBAL);
     156           0 :                 if (!handle)
     157           0 :                         ERR_RECORD("loader error: dlopen(%s): %s", fullpath,
     158             :                                    dlerror());
     159             :         }
     160           0 :         if (!handle) {
     161           0 :                 ERR_REPORT;
     162           0 :                 ERR_FREE;
     163             :                 return NULL;
     164             :         }
     165             : 
     166             :         /* previous dlopen() errors are no longer relevant */
     167           0 :         ERR_FREE;
     168             : 
     169           0 :         rtinfop = dlsym(handle, "frr_module");
     170           0 :         if (!rtinfop) {
     171           0 :                 dlclose(handle);
     172           0 :                 ERR_RECORD("\"%s\" is not an FRR module: %s", name, dlerror());
     173           0 :                 ERR_REPORT;
     174           0 :                 ERR_FREE;
     175             :                 return NULL;
     176             :         }
     177           0 :         rtinfo = *rtinfop;
     178           0 :         rtinfo->load_name = XSTRDUP(MTYPE_MODULE_LOADNAME, name);
     179           0 :         rtinfo->dl_handle = handle;
     180           0 :         if (args)
     181           0 :                 rtinfo->load_args = XSTRDUP(MTYPE_MODULE_LOADARGS, args);
     182           0 :         info = rtinfo->info;
     183             : 
     184           0 :         if (rtinfo->finished_loading) {
     185           0 :                 dlclose(handle);
     186           0 :                 ERR_RECORD("module \"%s\" already loaded", name);
     187           0 :                 goto out_fail;
     188             :         }
     189             : 
     190           0 :         if (info->init && info->init()) {
     191           0 :                 dlclose(handle);
     192           0 :                 ERR_RECORD("module \"%s\" initialisation failed", name);
     193           0 :                 goto out_fail;
     194             :         }
     195             : 
     196           0 :         rtinfo->finished_loading = true;
     197             : 
     198           0 :         *frrmod_last = rtinfo;
     199           0 :         frrmod_last = &rtinfo->next;
     200           0 :         ERR_FREE;
     201             :         return rtinfo;
     202             : 
     203           0 : out_fail:
     204           0 :         XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args);
     205           0 :         XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name);
     206           0 :         ERR_REPORT;
     207           0 :         ERR_FREE;
     208             :         return NULL;
     209             : }
     210             : 
     211             : #if 0
     212             : void frrmod_unload(struct frrmod_runtime *module)
     213             : {
     214             : }
     215             : #endif

Generated by: LCOV version v1.16-topotato