]> git.proxmox.com Git - mirror_frr.git/blame - lib/asn.c
Merge pull request #13659 from donaldsharp/increase_mgmt_time
[mirror_frr.git] / lib / asn.c
CommitLineData
8079a413
PG
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
24static bool relax_as_zero;
25
e55b0883
PG
26static 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
8079a413
PG
34/* converts a string into an Autonomous system number
35 * "1.1" => 65536
36 * "65500" => 65500
37 */
38static bool asn_str2asn_internal(const char *asstring, as_t *asn,
e55b0883
PG
39 const char **next, bool *partial,
40 enum asnotation_mode *mode)
8079a413
PG
41{
42 uint32_t high = 0, low = 0;
43 uint64_t temp_val;
44 const char *p = asstring;
45 bool ret = false;
46 uint32_t digit;
e55b0883 47 enum asnotation_mode val = ASNOTATION_PLAIN;
8079a413
PG
48
49 if (!asstring)
50 goto end;
51
52 if (!isdigit((unsigned char)*p))
53 goto end;
54
b7d890dd 55 /* leading zero is forbidden */
56 if (*p == '0' && isdigit((unsigned char)*(p + 1)))
57 goto end;
58
8079a413
PG
59 temp_val = 0;
60 while (isdigit((unsigned char)*p)) {
61 digit = (*p) - '0';
62 temp_val *= 10;
63 temp_val += digit;
64 if (temp_val > UINT32_MAX)
65 /* overflow */
66 goto end;
67 p++;
68 }
69 high = (uint32_t)temp_val;
70 if (*p == '.') { /* dot format */
71 p++;
b7d890dd 72
8079a413
PG
73 if (*p == '\0' && partial) {
74 *partial = true;
75 goto end;
76 }
b7d890dd 77
78 /* leading zero is forbidden */
79 if (*p == '0' && isdigit((unsigned char)*(p + 1)))
80 goto end;
81
82 temp_val = 0;
8079a413
PG
83 while (isdigit((unsigned char)*p)) {
84 digit = (*p) - '0';
85 temp_val *= 10;
86 temp_val += digit;
87 if (temp_val > UINT16_MAX)
88 /* overflow */
89 goto end;
90 p++;
91 }
92 low = (uint32_t)temp_val;
93
94 if (!next && *p != '\0' && !isdigit((unsigned char)*p))
95 goto end;
96 /* AS <AS4B>.<AS4B> is forbidden */
97 if (high > UINT16_MAX)
98 goto end;
99 /* AS 0.0 is authorised for some case only */
100 if (!relax_as_zero && high == 0 && low == 0) {
101 if (partial)
102 *partial = true;
103 goto end;
104 }
e55b0883
PG
105 if (asn)
106 *asn = (high << 16) + low;
8079a413 107 ret = true;
e55b0883
PG
108 if (high == 0)
109 val = ASNOTATION_DOTPLUS;
110 else
111 val = ASNOTATION_DOT;
8079a413
PG
112 goto end;
113 }
114 /* AS 0 is forbidden */
115 if (!relax_as_zero && high == 0)
116 goto end;
117 if (!asn) {
118 ret = true;
119 goto end;
120 }
121 *asn = high;
122 ret = true;
123 end:
124 if (next)
125 *next = p;
e55b0883
PG
126 if (mode)
127 *mode = val;
8079a413
PG
128 return ret;
129}
130
17571c4a
PG
131static void asn_asn2asdot(as_t asn, char *asstring, size_t len)
132{
133 uint16_t low, high;
134
135 high = (asn >> 16) & 0xffff;
136 low = asn & 0xffff;
137 snprintf(asstring, len, "%hu.%hu", high, low);
138}
139
8079a413
PG
140bool asn_str2asn(const char *asstring, as_t *asn)
141{
e55b0883 142 return asn_str2asn_internal(asstring, asn, NULL, NULL, NULL);
8079a413
PG
143}
144
145const char *asn_asn2asplain(as_t asn)
146{
147 static char buf[ASN_STRING_MAX_SIZE];
148
149 snprintf(buf, sizeof(buf), "%u", asn);
150 return buf;
151}
152
153const char *asn_str2asn_parse(const char *asstring, as_t *asn, bool *found_ptr)
154{
155 const char *p = NULL;
156 const char **next = &p;
157 bool found;
158
e55b0883 159 found = asn_str2asn_internal(asstring, asn, next, NULL, NULL);
8079a413
PG
160 if (found_ptr)
161 *found_ptr = found;
162 return *next;
163}
164
165void asn_relax_as_zero(bool relax)
166{
167 relax_as_zero = relax;
168}
169
170enum match_type asn_str2asn_match(const char *str)
171{
172 bool found, partial = false;
173
e55b0883 174 found = asn_str2asn_internal(str, NULL, NULL, &partial, NULL);
8079a413
PG
175 if (found && !partial)
176 return exact_match;
177
178 if (partial)
179 return partly_match;
180
181 return no_match;
182}
e55b0883
PG
183
184bool asn_str2asn_notation(const char *asstring, as_t *asn,
185 enum asnotation_mode *asnotation)
186{
187 return asn_str2asn_internal(asstring, asn, NULL, NULL, asnotation);
188}
189
190const char *asn_mode2str(enum asnotation_mode asnotation)
191{
192 return lookup_msg(asnotation_mode_msg, asnotation,
193 "Unrecognized AS notation mode");
194}
17571c4a 195
e84c7c12
PG
196void asn_asn2json(json_object *json, const char *attr,
197 as_t asn, enum asnotation_mode asnotation)
198{
199 static char as_str[ASN_STRING_MAX_SIZE];
200
201 if ((asnotation == ASNOTATION_PLAIN) ||
202 ((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX))
203 json_object_int_add(json, attr, asn);
204 else {
205 asn_asn2asdot(asn, as_str, sizeof(as_str));
206 json_object_string_add(json, attr, as_str);
207 }
208}
209
17571c4a
PG
210void asn_asn2json_array(json_object *jseg_list, as_t asn,
211 enum asnotation_mode asnotation)
212{
213 static char as_str[ASN_STRING_MAX_SIZE];
214
215 if ((asnotation == ASNOTATION_PLAIN) ||
216 ((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX))
217 json_object_array_add(jseg_list,
218 json_object_new_int64(asn));
219 else {
220 asn_asn2asdot(asn, as_str, sizeof(as_str));
221 json_array_string_add(jseg_list, as_str);
222 }
223}
224
4a8cd6ad
PG
225char *asn_asn2string(const as_t *asn, char *buf, size_t len,
226 enum asnotation_mode asnotation)
227{
228 if ((asnotation == ASNOTATION_PLAIN) ||
229 ((asnotation == ASNOTATION_DOT) && *asn < UINT16_MAX))
230 snprintf(buf, len, "%u", *asn);
231 else
232 asn_asn2asdot(*asn, buf, len);
233 return buf;
234}
235
17571c4a
PG
236static 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 char as_str[ASN_STRING_MAX_SIZE*3];
242 const as_t *asn;
243
244 if (!ptr)
245 return bputs(buf, "(null)");
246 asn = ptr;
4a8cd6ad 247 asn_asn2string(asn, as_str, sizeof(as_str), asnotation);
17571c4a
PG
248 return bputs(buf, as_str);
249}
250
251printfrr_ext_autoreg_p("ASP", printfrr_asplain);
252static ssize_t printfrr_asplain(struct fbuf *buf, struct printfrr_eargs *ea,
253 const void *ptr)
254{
255 return printfrr_asnotation(buf, ea, ptr, ASNOTATION_PLAIN);
256}
257
258printfrr_ext_autoreg_p("ASD", printfrr_asdot);
259static ssize_t printfrr_asdot(struct fbuf *buf, struct printfrr_eargs *ea,
260 const void *ptr)
261{
262 return printfrr_asnotation(buf, ea, ptr, ASNOTATION_DOT);
263}
264
265printfrr_ext_autoreg_p("ASE", printfrr_asdotplus);
266static ssize_t printfrr_asdotplus(struct fbuf *buf, struct printfrr_eargs *ea,
267 const void *ptr)
268{
269 return printfrr_asnotation(buf, ea, ptr, ASNOTATION_DOTPLUS);
270}