back to topotato report
topotato coverage report
Current view: top level - lib - defaults.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 80 106 75.5 %
Date: 2023-11-16 17:19:14 Functions: 6 22 27.3 %

          Line data    Source code
       1             : // SPDX-License-Identifier: ISC
       2             : /*
       3             :  * FRR switchable defaults.
       4             :  * Copyright (c) 2017-2019  David Lamparter, for NetDEF, Inc.
       5             :  */
       6             : 
       7             : #include <zebra.h>
       8             : 
       9             : #include "defaults.h"
      10             : #include "lib/version.h"
      11             : 
      12             : static char df_version[128] = FRR_VER_SHORT, df_profile[128] = DFLT_NAME;
      13             : static struct frr_default *dflt_first = NULL, **dflt_next = &dflt_first;
      14             : 
      15             : /* these are global for all FRR daemons.  they have to be, since we write an
      16             :  * integrated config with the same value for all daemons.
      17             :  */
      18             : const char *frr_defaults_profiles[] = {
      19             :         "traditional",
      20             :         "datacenter",
      21             :         NULL,
      22             : };
      23             : 
      24          16 : static int version_value(int ch)
      25             : {
      26             :         /* non-ASCII shouldn't happen */
      27          16 :         if (ch < 0 || ch >= 128)
      28             :                 return 2;
      29             : 
      30             :         /* ~foo sorts older than nothing */
      31          16 :         if (ch == '~')
      32             :                 return 0;
      33          16 :         if (ch == '\0')
      34             :                 return 1;
      35          16 :         if (isalpha(ch))
      36           0 :                 return 0x100 + tolower(ch);
      37             : 
      38             :         /* punctuation and digits (and everything else) */
      39          16 :         return 0x200 + ch;
      40             : }
      41             : 
      42          48 : int frr_version_cmp(const char *aa, const char *bb)
      43             : {
      44          48 :         const char *apos = aa, *bpos = bb;
      45             : 
      46             :         /* || is correct, we won't scan past the end of a string since that
      47             :          * doesn't compare equal to anything else */
      48          64 :         while (apos[0] || bpos[0]) {
      49          64 :                 if (isdigit((unsigned char)apos[0]) &&
      50          56 :                     isdigit((unsigned char)bpos[0])) {
      51          56 :                         unsigned long av, bv;
      52          56 :                         char *aend = NULL, *bend = NULL;
      53             : 
      54          56 :                         av = strtoul(apos, &aend, 10);
      55          56 :                         bv = strtoul(bpos, &bend, 10);
      56          56 :                         if (av < bv)
      57          48 :                                 return -1;
      58          56 :                         if (av > bv)
      59             :                                 return 1;
      60             : 
      61           8 :                         apos = aend;
      62           8 :                         bpos = bend;
      63           8 :                         continue;
      64             :                 }
      65             : 
      66           8 :                 int a = version_value(*apos++);
      67           8 :                 int b = version_value(*bpos++);
      68             : 
      69           8 :                 if (a < b)
      70             :                         return -1;
      71           8 :                 if (a > b)
      72             :                         return 1;
      73             :         }
      74             :         return 0;
      75             : }
      76             : 
      77             : static void frr_default_apply_one(struct frr_default *dflt, bool check);
      78             : 
      79         148 : void frr_default_add(struct frr_default *dflt)
      80             : {
      81         148 :         dflt->next = NULL;
      82         148 :         *dflt_next = dflt;
      83         148 :         dflt_next = &dflt->next;
      84             : 
      85         148 :         frr_default_apply_one(dflt, true);
      86         148 : }
      87             : 
      88         528 : static bool frr_match_version(const char *name, const char *vspec,
      89             :                               const char *version, bool check)
      90             : {
      91         528 :         int cmp;
      92         528 :         static const struct spec {
      93             :                 const char *str;
      94             :                 int dir, eq;
      95             :         } specs[] = {
      96             :                 {"<=", -1, 1},
      97             :                 {">=", 1, 1},
      98             :                 {"==", 0, 1},
      99             :                 {"<", -1, 0},
     100             :                 {">", 1, 0},
     101             :                 {"=", 0, 1},
     102             :                 {NULL, 0, 0},
     103             :         };
     104         528 :         const struct spec *s;
     105             : 
     106         528 :         if (!vspec)
     107             :                 /* NULL = all versions */
     108             :                 return true;
     109             : 
     110         192 :         for (s = specs; s->str; s++)
     111         192 :                 if (!strncmp(s->str, vspec, strlen(s->str)))
     112             :                         break;
     113          48 :         if (!s->str) {
     114           0 :                 if (check)
     115           0 :                         fprintf(stderr, "invalid version specifier for %s: %s",
     116             :                                 name, vspec);
     117             :                 /* invalid version spec, never matches */
     118           0 :                 return false;
     119             :         }
     120             : 
     121          48 :         vspec += strlen(s->str);
     122          96 :         while (isspace((unsigned char)*vspec))
     123          48 :                 vspec++;
     124             : 
     125          48 :         cmp = frr_version_cmp(version, vspec);
     126          48 :         if (cmp == s->dir || (s->eq && cmp == 0))
     127             :                 return true;
     128             : 
     129             :         return false;
     130             : }
     131             : 
     132         296 : static void frr_default_apply_one(struct frr_default *dflt, bool check)
     133             : {
     134         296 :         struct frr_default_entry *entry = dflt->entries;
     135         296 :         struct frr_default_entry *dfltentry = NULL, *saveentry = NULL;
     136             : 
     137         476 :         for (; entry->match_version || entry->match_profile; entry++) {
     138         300 :                 if (entry->match_profile
     139         280 :                         && strcmp(entry->match_profile, df_profile))
     140          36 :                         continue;
     141             : 
     142         264 :                 if (!dfltentry && frr_match_version(dflt->name,
     143             :                                 entry->match_version, df_version, check))
     144         240 :                         dfltentry = entry;
     145         264 :                 if (!saveentry && frr_match_version(dflt->name,
     146             :                                 entry->match_version, FRR_VER_SHORT, check))
     147         240 :                         saveentry = entry;
     148             : 
     149         264 :                 if (dfltentry && saveentry && !check)
     150             :                         break;
     151             :         }
     152             :         /* found default or arrived at last entry that has NULL,NULL spec */
     153             : 
     154         296 :         if (!dfltentry)
     155          56 :                 dfltentry = entry;
     156         296 :         if (!saveentry)
     157          56 :                 saveentry = entry;
     158             : 
     159         296 :         if (dflt->dflt_bool)
     160         284 :                 *dflt->dflt_bool = dfltentry->val_bool;
     161         296 :         if (dflt->dflt_str)
     162           0 :                 *dflt->dflt_str = dfltentry->val_str;
     163         296 :         if (dflt->dflt_long)
     164           0 :                 *dflt->dflt_long = dfltentry->val_long;
     165         296 :         if (dflt->dflt_ulong)
     166          12 :                 *dflt->dflt_ulong = dfltentry->val_ulong;
     167         296 :         if (dflt->dflt_float)
     168           0 :                 *dflt->dflt_float = dfltentry->val_float;
     169         296 :         if (dflt->save_bool)
     170         284 :                 *dflt->save_bool = saveentry->val_bool;
     171         296 :         if (dflt->save_str)
     172           0 :                 *dflt->save_str = saveentry->val_str;
     173         296 :         if (dflt->save_long)
     174           0 :                 *dflt->save_long = saveentry->val_long;
     175         296 :         if (dflt->save_ulong)
     176          12 :                 *dflt->save_ulong = saveentry->val_ulong;
     177         296 :         if (dflt->save_float)
     178           0 :                 *dflt->save_float = saveentry->val_float;
     179         296 : }
     180             : 
     181           4 : void frr_defaults_apply(void)
     182             : {
     183           4 :         struct frr_default *dflt;
     184             : 
     185         152 :         for (dflt = dflt_first; dflt; dflt = dflt->next)
     186         148 :                 frr_default_apply_one(dflt, false);
     187           4 : }
     188             : 
     189           0 : bool frr_defaults_profile_valid(const char *profile)
     190             : {
     191           0 :         const char **p;
     192             : 
     193           0 :         for (p = frr_defaults_profiles; *p; p++)
     194           0 :                 if (!strcmp(profile, *p))
     195             :                         return true;
     196             :         return false;
     197             : }
     198             : 
     199           0 : const char *frr_defaults_version(void)
     200             : {
     201           0 :         return df_version;
     202             : }
     203             : 
     204           0 : const char *frr_defaults_profile(void)
     205             : {
     206           0 :         return df_profile;
     207             : }
     208             : 
     209           0 : void frr_defaults_version_set(const char *version)
     210             : {
     211           0 :         strlcpy(df_version, version, sizeof(df_version));
     212           0 :         frr_defaults_apply();
     213           0 : }
     214             : 
     215           0 : void frr_defaults_profile_set(const char *profile)
     216             : {
     217           0 :         strlcpy(df_profile, profile, sizeof(df_profile));
     218           0 :         frr_defaults_apply();
     219           0 : }

Generated by: LCOV version v1.16-topotato