back to topotato report
topotato coverage report
Current view: top level - lib - asn.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 60 135 44.4 %
Date: 2023-11-16 17:19:14 Functions: 11 38 28.9 %

          Line data    Source code
       1             : /*
       2             :  * ASN functions
       3             :  *
       4             :  * Copyright 2022 6WIND
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the Free
       8             :  * Software Foundation; either version 2 of the License, or (at your option)
       9             :  * any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      12             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      14             :  * more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : #include <zebra.h>
      21             : #include "log.h"
      22             : #include "asn.h"
      23             : 
      24             : static bool relax_as_zero;
      25             : 
      26             : static const struct message asnotation_mode_msg[] = {
      27             :         {ASNOTATION_PLAIN, "plain"},
      28             :         {ASNOTATION_DOT, "dot"},
      29             :         {ASNOTATION_DOTPLUS, "dot+"},
      30             :         {ASNOTATION_UNDEFINED, "undefined"},
      31             :         {0}
      32             : };
      33             : 
      34             : /* converts a string into an Autonomous system number
      35             :  * "1.1" => 65536
      36             :  * "65500" => 65500
      37             :  */
      38          18 : static bool asn_str2asn_internal(const char *asstring, as_t *asn,
      39             :                                  const char **next, bool *partial,
      40             :                                  enum asnotation_mode *mode)
      41             : {
      42          18 :         uint32_t high = 0, low = 0;
      43          18 :         uint64_t temp_val;
      44          18 :         const char *p = asstring;
      45          18 :         bool ret = false;
      46          18 :         uint32_t digit;
      47          18 :         enum asnotation_mode val = ASNOTATION_PLAIN;
      48             : 
      49          18 :         if (!asstring)
      50           0 :                 goto end;
      51             : 
      52          18 :         if  (!isdigit((unsigned char)*p))
      53          12 :                 goto end;
      54             : 
      55             :         /* leading zero is forbidden */
      56           6 :         if (*p == '0' && isdigit((unsigned char)*(p + 1)))
      57           0 :                 goto end;
      58             : 
      59             :         temp_val = 0;
      60          36 :         while (isdigit((unsigned char)*p)) {
      61          30 :                 digit = (*p) - '0';
      62          30 :                 temp_val *= 10;
      63          30 :                 temp_val += digit;
      64          30 :                 if (temp_val > UINT32_MAX)
      65             :                         /* overflow */
      66           0 :                         goto end;
      67          30 :                 p++;
      68             :         }
      69           6 :         high = (uint32_t)temp_val;
      70           6 :         if (*p == '.') { /* dot format */
      71           0 :                 p++;
      72             : 
      73           0 :                 if (*p == '\0' && partial) {
      74           0 :                         *partial = true;
      75           0 :                         goto end;
      76             :                 }
      77             : 
      78             :                 /* leading zero is forbidden */
      79           0 :                 if (*p == '0' && isdigit((unsigned char)*(p + 1)))
      80           0 :                         goto end;
      81             : 
      82             :                 temp_val = 0;
      83           0 :                 while (isdigit((unsigned char)*p)) {
      84           0 :                         digit = (*p) - '0';
      85           0 :                         temp_val *= 10;
      86           0 :                         temp_val += digit;
      87           0 :                         if (temp_val > UINT16_MAX)
      88             :                                 /* overflow */
      89           0 :                                 goto end;
      90           0 :                         p++;
      91             :                 }
      92           0 :                 low = (uint32_t)temp_val;
      93             : 
      94           0 :                 if (!next && *p != '\0' && !isdigit((unsigned char)*p))
      95           0 :                         goto end;
      96             :                 /* AS <AS4B>.<AS4B> is forbidden */
      97           0 :                 if (high > UINT16_MAX)
      98           0 :                         goto end;
      99             :                 /* AS 0.0 is authorised for some case only */
     100           0 :                 if (!relax_as_zero && high == 0 && low == 0) {
     101           0 :                         if (partial)
     102           0 :                                 *partial = true;
     103           0 :                         goto end;
     104             :                 }
     105           0 :                 if (asn)
     106           0 :                         *asn = (high << 16) + low;
     107           0 :                 ret = true;
     108           0 :                 if (high == 0)
     109             :                         val = ASNOTATION_DOTPLUS;
     110             :                 else
     111           0 :                         val = ASNOTATION_DOT;
     112           0 :                 goto end;
     113             :         }
     114             :         /* AS 0 is forbidden */
     115           6 :         if (!relax_as_zero && high == 0)
     116           0 :                 goto end;
     117           6 :         if (!asn) {
     118           4 :                 ret = true;
     119           4 :                 goto end;
     120             :         }
     121           2 :         *asn = high;
     122           2 :         ret = true;
     123          18 :  end:
     124          18 :         if (next)
     125           0 :                 *next = p;
     126          18 :         if (mode)
     127           2 :                 *mode = val;
     128          18 :         return ret;
     129             : }
     130             : 
     131           0 : static void asn_asn2asdot(as_t asn, char *asstring, size_t len)
     132             : {
     133           0 :         uint16_t low, high;
     134             : 
     135           0 :         high = (asn >> 16) & 0xffff;
     136           0 :         low = asn & 0xffff;
     137           0 :         snprintf(asstring, len, "%hu.%hu", high, low);
     138           0 : }
     139             : 
     140           6 : bool asn_str2asn(const char *asstring, as_t *asn)
     141             : {
     142           6 :         return asn_str2asn_internal(asstring, asn, NULL, NULL, NULL);
     143             : }
     144             : 
     145           0 : const char *asn_asn2asplain(as_t asn)
     146             : {
     147           0 :         static char buf[ASN_STRING_MAX_SIZE];
     148             : 
     149           0 :         snprintf(buf, sizeof(buf), "%u", asn);
     150           0 :         return buf;
     151             : }
     152             : 
     153           0 : const char *asn_str2asn_parse(const char *asstring, as_t *asn, bool *found_ptr)
     154             : {
     155           0 :         const char *p = NULL;
     156           0 :         const char **next = &p;
     157           0 :         bool found;
     158             : 
     159           0 :         found = asn_str2asn_internal(asstring, asn, next, NULL, NULL);
     160           0 :         if (found_ptr)
     161           0 :                 *found_ptr = found;
     162           0 :         return *next;
     163             : }
     164             : 
     165           0 : void asn_relax_as_zero(bool relax)
     166             : {
     167           0 :         relax_as_zero = relax;
     168           0 : }
     169             : 
     170          10 : enum match_type asn_str2asn_match(const char *str)
     171             : {
     172          10 :         bool found, partial = false;
     173             : 
     174          10 :         found = asn_str2asn_internal(str, NULL, NULL, &partial, NULL);
     175          10 :         if (found && !partial)
     176             :                 return exact_match;
     177             : 
     178           8 :         if (partial)
     179           0 :                 return partly_match;
     180             : 
     181             :         return no_match;
     182             : }
     183             : 
     184           2 : bool asn_str2asn_notation(const char *asstring, as_t *asn,
     185             :                           enum asnotation_mode *asnotation)
     186             : {
     187           2 :         return asn_str2asn_internal(asstring, asn, NULL, NULL, asnotation);
     188             : }
     189             : 
     190           0 : const char *asn_mode2str(enum asnotation_mode asnotation)
     191             : {
     192           0 :         return lookup_msg(asnotation_mode_msg, asnotation,
     193             :                           "Unrecognized AS notation mode");
     194             : }
     195             : 
     196          20 : void asn_asn2json(json_object *json, const char *attr,
     197             :                   as_t asn, enum asnotation_mode asnotation)
     198             : {
     199          20 :         static char as_str[ASN_STRING_MAX_SIZE];
     200             : 
     201          20 :         if ((asnotation == ASNOTATION_PLAIN) ||
     202           0 :             ((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX))
     203          20 :                 json_object_int_add(json, attr, asn);
     204             :         else {
     205           0 :                 asn_asn2asdot(asn, as_str, sizeof(as_str));
     206           0 :                 json_object_string_add(json, attr, as_str);
     207             :         }
     208          20 : }
     209             : 
     210           0 : void asn_asn2json_array(json_object *jseg_list, as_t asn,
     211             :                         enum asnotation_mode asnotation)
     212             : {
     213           0 :         static char as_str[ASN_STRING_MAX_SIZE];
     214             : 
     215           0 :         if ((asnotation == ASNOTATION_PLAIN) ||
     216           0 :             ((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX))
     217           0 :                 json_object_array_add(jseg_list,
     218             :                                       json_object_new_int64(asn));
     219             :         else {
     220           0 :                 asn_asn2asdot(asn, as_str, sizeof(as_str));
     221           0 :                 json_array_string_add(jseg_list, as_str);
     222             :         }
     223           0 : }
     224             : 
     225          18 : char *asn_asn2string(const as_t *asn, char *buf, size_t len,
     226             :                      enum asnotation_mode asnotation)
     227             : {
     228          18 :         if ((asnotation == ASNOTATION_PLAIN) ||
     229           0 :             ((asnotation == ASNOTATION_DOT) && *asn < UINT16_MAX))
     230          18 :                 snprintf(buf, len, "%u", *asn);
     231             :         else
     232           0 :                 asn_asn2asdot(*asn, buf, len);
     233          18 :         return buf;
     234             : }
     235             : 
     236          18 : static ssize_t printfrr_asnotation(struct fbuf *buf, struct printfrr_eargs *ea,
     237             :                                    const void *ptr,
     238             :                                    enum asnotation_mode asnotation)
     239             : {
     240             :         /* for alignemnt up to 33 chars - %33pASD for instance - */
     241          18 :         char as_str[ASN_STRING_MAX_SIZE*3];
     242          18 :         const as_t *asn;
     243             : 
     244          18 :         if (!ptr)
     245           0 :                 return bputs(buf, "(null)");
     246          18 :         asn = ptr;
     247          18 :         asn_asn2string(asn, as_str, sizeof(as_str), asnotation);
     248          18 :         return bputs(buf, as_str);
     249             : }
     250             : 
     251           4 : printfrr_ext_autoreg_p("ASP", printfrr_asplain);
     252          18 : static ssize_t printfrr_asplain(struct fbuf *buf, struct printfrr_eargs *ea,
     253             :                                 const void *ptr)
     254             : {
     255          18 :         return printfrr_asnotation(buf, ea, ptr, ASNOTATION_PLAIN);
     256             : }
     257             : 
     258           4 : printfrr_ext_autoreg_p("ASD", printfrr_asdot);
     259           0 : static ssize_t printfrr_asdot(struct fbuf *buf, struct printfrr_eargs *ea,
     260             :                                 const void *ptr)
     261             : {
     262           0 :         return printfrr_asnotation(buf, ea, ptr, ASNOTATION_DOT);
     263             : }
     264             : 
     265           4 : printfrr_ext_autoreg_p("ASE", printfrr_asdotplus);
     266           0 : static ssize_t printfrr_asdotplus(struct fbuf *buf, struct printfrr_eargs *ea,
     267             :                                   const void *ptr)
     268             : {
     269           0 :         return printfrr_asnotation(buf, ea, ptr, ASNOTATION_DOTPLUS);
     270             : }

Generated by: LCOV version v1.16-topotato