back to topotato report
topotato coverage report
Current view: top level - lib - defaults.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 65 106 61.3 %
Date: 2023-02-24 19:38:44 Functions: 5 11 45.5 %

          Line data    Source code
       1             : /*
       2             :  * FRR switchable defaults.
       3             :  * Copyright (c) 2017-2019  David Lamparter, for NetDEF, Inc.
       4             :  *
       5             :  * Permission to use, copy, modify, and distribute this software for any
       6             :  * purpose with or without fee is hereby granted, provided that the above
       7             :  * copyright notice and this permission notice appear in all copies.
       8             :  *
       9             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      10             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      11             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      12             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      13             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      14             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      15             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      16             :  */
      17             : 
      18             : #include <zebra.h>
      19             : 
      20             : #include "defaults.h"
      21             : #include "lib/version.h"
      22             : 
      23             : static char df_version[128] = FRR_VER_SHORT, df_profile[128] = DFLT_NAME;
      24             : static struct frr_default *dflt_first = NULL, **dflt_next = &dflt_first;
      25             : 
      26             : /* these are global for all FRR daemons.  they have to be, since we write an
      27             :  * integrated config with the same value for all daemons.
      28             :  */
      29             : const char *frr_defaults_profiles[] = {
      30             :         "traditional",
      31             :         "datacenter",
      32             :         NULL,
      33             : };
      34             : 
      35           0 : static int version_value(int ch)
      36             : {
      37             :         /* non-ASCII shouldn't happen */
      38           0 :         if (ch < 0 || ch >= 128)
      39             :                 return 2;
      40             : 
      41             :         /* ~foo sorts older than nothing */
      42           0 :         if (ch == '~')
      43             :                 return 0;
      44           0 :         if (ch == '\0')
      45             :                 return 1;
      46           0 :         if (isalpha(ch))
      47           0 :                 return 0x100 + tolower(ch);
      48             : 
      49             :         /* punctuation and digits (and everything else) */
      50           0 :         return 0x200 + ch;
      51             : }
      52             : 
      53         960 : int frr_version_cmp(const char *aa, const char *bb)
      54             : {
      55         960 :         const char *apos = aa, *bpos = bb;
      56             : 
      57             :         /* || is correct, we won't scan past the end of a string since that
      58             :          * doesn't compare equal to anything else */
      59         960 :         while (apos[0] || bpos[0]) {
      60         960 :                 if (isdigit((unsigned char)apos[0]) &&
      61         960 :                     isdigit((unsigned char)bpos[0])) {
      62         960 :                         unsigned long av, bv;
      63         960 :                         char *aend = NULL, *bend = NULL;
      64             : 
      65         960 :                         av = strtoul(apos, &aend, 10);
      66         960 :                         bv = strtoul(bpos, &bend, 10);
      67         960 :                         if (av < bv)
      68         960 :                                 return -1;
      69         960 :                         if (av > bv)
      70             :                                 return 1;
      71             : 
      72           0 :                         apos = aend;
      73           0 :                         bpos = bend;
      74           0 :                         continue;
      75             :                 }
      76             : 
      77           0 :                 int a = version_value(*apos++);
      78           0 :                 int b = version_value(*bpos++);
      79             : 
      80           0 :                 if (a < b)
      81             :                         return -1;
      82           0 :                 if (a > b)
      83             :                         return 1;
      84             :         }
      85             :         return 0;
      86             : }
      87             : 
      88             : static void frr_default_apply_one(struct frr_default *dflt, bool check);
      89             : 
      90         596 : void frr_default_add(struct frr_default *dflt)
      91             : {
      92         596 :         dflt->next = NULL;
      93         596 :         *dflt_next = dflt;
      94         596 :         dflt_next = &dflt->next;
      95             : 
      96         596 :         frr_default_apply_one(dflt, true);
      97         596 : }
      98             : 
      99         960 : static bool frr_match_version(const char *name, const char *vspec,
     100             :                               const char *version, bool check)
     101             : {
     102         960 :         int cmp;
     103         960 :         static const struct spec {
     104             :                 const char *str;
     105             :                 int dir, eq;
     106             :         } specs[] = {
     107             :                 {"<=", -1, 1},
     108             :                 {">=", 1, 1},
     109             :                 {"==", 0, 1},
     110             :                 {"<", -1, 0},
     111             :                 {">", 1, 0},
     112             :                 {"=", 0, 1},
     113             :                 {NULL, 0, 0},
     114             :         };
     115         960 :         const struct spec *s;
     116             : 
     117         960 :         if (!vspec)
     118             :                 /* NULL = all versions */
     119             :                 return true;
     120             : 
     121        3840 :         for (s = specs; s->str; s++)
     122        3840 :                 if (!strncmp(s->str, vspec, strlen(s->str)))
     123             :                         break;
     124         960 :         if (!s->str) {
     125           0 :                 if (check)
     126           0 :                         fprintf(stderr, "invalid version specifier for %s: %s",
     127             :                                 name, vspec);
     128             :                 /* invalid version spec, never matches */
     129           0 :                 return false;
     130             :         }
     131             : 
     132         960 :         vspec += strlen(s->str);
     133        1920 :         while (isspace((unsigned char)*vspec))
     134         960 :                 vspec++;
     135             : 
     136         960 :         cmp = frr_version_cmp(version, vspec);
     137         960 :         if (cmp == s->dir || (s->eq && cmp == 0))
     138             :                 return true;
     139             : 
     140             :         return false;
     141             : }
     142             : 
     143        1192 : static void frr_default_apply_one(struct frr_default *dflt, bool check)
     144             : {
     145        1192 :         struct frr_default_entry *entry = dflt->entries;
     146        1192 :         struct frr_default_entry *dfltentry = NULL, *saveentry = NULL;
     147             : 
     148        2480 :         for (; entry->match_version || entry->match_profile; entry++) {
     149        1288 :                 if (entry->match_profile
     150         904 :                         && strcmp(entry->match_profile, df_profile))
     151         808 :                         continue;
     152             : 
     153         480 :                 if (!dfltentry && frr_match_version(dflt->name,
     154             :                                 entry->match_version, df_version, check))
     155           0 :                         dfltentry = entry;
     156         480 :                 if (!saveentry && frr_match_version(dflt->name,
     157             :                                 entry->match_version, FRR_VER_SHORT, check))
     158           0 :                         saveentry = entry;
     159             : 
     160         480 :                 if (dfltentry && saveentry && !check)
     161             :                         break;
     162             :         }
     163             :         /* found default or arrived at last entry that has NULL,NULL spec */
     164             : 
     165        1192 :         if (!dfltentry)
     166        1192 :                 dfltentry = entry;
     167        1192 :         if (!saveentry)
     168        1192 :                 saveentry = entry;
     169             : 
     170        1192 :         if (dflt->dflt_bool)
     171         904 :                 *dflt->dflt_bool = dfltentry->val_bool;
     172        1192 :         if (dflt->dflt_str)
     173           0 :                 *dflt->dflt_str = dfltentry->val_str;
     174        1192 :         if (dflt->dflt_long)
     175           0 :                 *dflt->dflt_long = dfltentry->val_long;
     176        1192 :         if (dflt->dflt_ulong)
     177         288 :                 *dflt->dflt_ulong = dfltentry->val_ulong;
     178        1192 :         if (dflt->dflt_float)
     179           0 :                 *dflt->dflt_float = dfltentry->val_float;
     180        1192 :         if (dflt->save_bool)
     181         904 :                 *dflt->save_bool = saveentry->val_bool;
     182        1192 :         if (dflt->save_str)
     183           0 :                 *dflt->save_str = saveentry->val_str;
     184        1192 :         if (dflt->save_long)
     185           0 :                 *dflt->save_long = saveentry->val_long;
     186        1192 :         if (dflt->save_ulong)
     187         288 :                 *dflt->save_ulong = saveentry->val_ulong;
     188        1192 :         if (dflt->save_float)
     189           0 :                 *dflt->save_float = saveentry->val_float;
     190        1192 : }
     191             : 
     192         218 : void frr_defaults_apply(void)
     193             : {
     194         218 :         struct frr_default *dflt;
     195             : 
     196         814 :         for (dflt = dflt_first; dflt; dflt = dflt->next)
     197         596 :                 frr_default_apply_one(dflt, false);
     198         218 : }
     199             : 
     200           0 : bool frr_defaults_profile_valid(const char *profile)
     201             : {
     202           0 :         const char **p;
     203             : 
     204           0 :         for (p = frr_defaults_profiles; *p; p++)
     205           0 :                 if (!strcmp(profile, *p))
     206             :                         return true;
     207             :         return false;
     208             : }
     209             : 
     210           0 : const char *frr_defaults_version(void)
     211             : {
     212           0 :         return df_version;
     213             : }
     214             : 
     215           0 : const char *frr_defaults_profile(void)
     216             : {
     217           0 :         return df_profile;
     218             : }
     219             : 
     220           0 : void frr_defaults_version_set(const char *version)
     221             : {
     222           0 :         strlcpy(df_version, version, sizeof(df_version));
     223           0 :         frr_defaults_apply();
     224           0 : }
     225             : 
     226           0 : void frr_defaults_profile_set(const char *profile)
     227             : {
     228           0 :         strlcpy(df_profile, profile, sizeof(df_profile));
     229           0 :         frr_defaults_apply();
     230           0 : }

Generated by: LCOV version v1.16-topotato