mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 04:14:19 +00:00

AS number can be defined as an unsigned long number, or two uint16 values separated by a period (.). The possible valus are: - usual 32 bit values : [1;2^32 -1] - <1.65535>.<0.65535> for dot notation - <0.65535>.<0.65535> for dot+ notation. The 0.0 value is forbidden when configuring BGP instances or peer configurations. A new ASN type is added for parsing in the vty. The following commands use that new identifier: - router bgp .. - bgp confederation .. - neighbor <> remote-as <> - neighbor <> local-as <> - clear ip bgp <> - route-map / set as-path <> An asn library is available in lib/ and provides some services: - convert an as string into an as number. - parse an as path list string and extract a number. - convert an as number into a string. Also, the bgp tests forge an as_zero_path, and to do that, an API to relax the possibility to have a 0 as value is specifically called from the tests. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
151 lines
3.1 KiB
C
151 lines
3.1 KiB
C
/*
|
|
* ASN functions
|
|
*
|
|
* Copyright 2022 6WIND
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; see the file COPYING; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#include <zebra.h>
|
|
#include "log.h"
|
|
#include "asn.h"
|
|
|
|
static bool relax_as_zero;
|
|
|
|
/* converts a string into an Autonomous system number
|
|
* "1.1" => 65536
|
|
* "65500" => 65500
|
|
*/
|
|
static bool asn_str2asn_internal(const char *asstring, as_t *asn,
|
|
const char **next, bool *partial)
|
|
{
|
|
uint32_t high = 0, low = 0;
|
|
uint64_t temp_val;
|
|
const char *p = asstring;
|
|
bool ret = false;
|
|
uint32_t digit;
|
|
|
|
if (!asstring)
|
|
goto end;
|
|
|
|
if (!isdigit((unsigned char)*p))
|
|
goto end;
|
|
|
|
temp_val = 0;
|
|
while (isdigit((unsigned char)*p)) {
|
|
digit = (*p) - '0';
|
|
temp_val *= 10;
|
|
temp_val += digit;
|
|
if (temp_val > UINT32_MAX)
|
|
/* overflow */
|
|
goto end;
|
|
p++;
|
|
}
|
|
high = (uint32_t)temp_val;
|
|
if (*p == '.') { /* dot format */
|
|
p++;
|
|
temp_val = 0;
|
|
if (*p == '\0' && partial) {
|
|
*partial = true;
|
|
goto end;
|
|
}
|
|
while (isdigit((unsigned char)*p)) {
|
|
digit = (*p) - '0';
|
|
temp_val *= 10;
|
|
temp_val += digit;
|
|
if (temp_val > UINT16_MAX)
|
|
/* overflow */
|
|
goto end;
|
|
p++;
|
|
}
|
|
low = (uint32_t)temp_val;
|
|
|
|
if (!next && *p != '\0' && !isdigit((unsigned char)*p))
|
|
goto end;
|
|
/* AS <AS4B>.<AS4B> is forbidden */
|
|
if (high > UINT16_MAX)
|
|
goto end;
|
|
/* AS 0.0 is authorised for some case only */
|
|
if (!relax_as_zero && high == 0 && low == 0) {
|
|
if (partial)
|
|
*partial = true;
|
|
goto end;
|
|
}
|
|
if (!asn) {
|
|
ret = true;
|
|
goto end;
|
|
}
|
|
*asn = (high << 16) + low;
|
|
ret = true;
|
|
goto end;
|
|
}
|
|
/* AS 0 is forbidden */
|
|
if (!relax_as_zero && high == 0)
|
|
goto end;
|
|
if (!asn) {
|
|
ret = true;
|
|
goto end;
|
|
}
|
|
*asn = high;
|
|
ret = true;
|
|
end:
|
|
if (next)
|
|
*next = p;
|
|
return ret;
|
|
}
|
|
|
|
bool asn_str2asn(const char *asstring, as_t *asn)
|
|
{
|
|
return asn_str2asn_internal(asstring, asn, NULL, NULL);
|
|
}
|
|
|
|
const char *asn_asn2asplain(as_t asn)
|
|
{
|
|
static char buf[ASN_STRING_MAX_SIZE];
|
|
|
|
snprintf(buf, sizeof(buf), "%u", asn);
|
|
return buf;
|
|
}
|
|
|
|
const char *asn_str2asn_parse(const char *asstring, as_t *asn, bool *found_ptr)
|
|
{
|
|
const char *p = NULL;
|
|
const char **next = &p;
|
|
bool found;
|
|
|
|
found = asn_str2asn_internal(asstring, asn, next, NULL);
|
|
if (found_ptr)
|
|
*found_ptr = found;
|
|
return *next;
|
|
}
|
|
|
|
void asn_relax_as_zero(bool relax)
|
|
{
|
|
relax_as_zero = relax;
|
|
}
|
|
|
|
enum match_type asn_str2asn_match(const char *str)
|
|
{
|
|
bool found, partial = false;
|
|
|
|
found = asn_str2asn_internal(str, NULL, NULL, &partial);
|
|
if (found && !partial)
|
|
return exact_match;
|
|
|
|
if (partial)
|
|
return partly_match;
|
|
|
|
return no_match;
|
|
}
|