back to topotato report
topotato coverage report
Current view: top level - lib - module.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 10 70 14.3 %
Date: 2023-11-16 17:19:14 Functions: 8 15 53.3 %

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

Generated by: LCOV version v1.16-topotato