summaryrefslogtreecommitdiff
path: root/lib/asn.c
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2022-11-02 18:17:21 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2023-02-10 10:27:17 +0100
commit8079a4138d61500117ebbffb250ceba0a894f9c0 (patch)
treedea5e0834d075574c1a485928cb843446bad0d20 /lib/asn.c
parent9eb11997104e3ba5e436220f758f7881c0c0556d (diff)
lib, bgp: add initial support for asdot format
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>
Diffstat (limited to 'lib/asn.c')
-rw-r--r--lib/asn.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/lib/asn.c b/lib/asn.c
new file mode 100644
index 0000000000..7a786866cb
--- /dev/null
+++ b/lib/asn.c
@@ -0,0 +1,150 @@
+/*
+ * 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;
+}