]> git.proxmox.com Git - mirror_frr.git/blob - lib/asn.c
tests: Drop `tableVersion` from EVPN PIM test case
[mirror_frr.git] / lib / asn.c
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 static bool asn_str2asn_internal(const char *asstring, as_t *asn,
39 const char **next, bool *partial,
40 enum asnotation_mode *mode)
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;
47 enum asnotation_mode val = ASNOTATION_PLAIN;
48
49 if (!asstring)
50 goto end;
51
52 if (!isdigit((unsigned char)*p))
53 goto end;
54
55 /* leading zero is forbidden */
56 if (*p == '0' && isdigit((unsigned char)*(p + 1)))
57 goto end;
58
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++;
72
73 if (*p == '\0' && partial) {
74 *partial = true;
75 goto end;
76 }
77
78 /* leading zero is forbidden */
79 if (*p == '0' && isdigit((unsigned char)*(p + 1)))
80 goto end;
81
82 temp_val = 0;
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 }
105 if (asn)
106 *asn = (high << 16) + low;
107 ret = true;
108 if (high == 0)
109 val = ASNOTATION_DOTPLUS;
110 else
111 val = ASNOTATION_DOT;
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;
126 if (mode)
127 *mode = val;
128 return ret;
129 }
130
131 static 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
140 bool asn_str2asn(const char *asstring, as_t *asn)
141 {
142 return asn_str2asn_internal(asstring, asn, NULL, NULL, NULL);
143 }
144
145 const 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
153 const 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
159 found = asn_str2asn_internal(asstring, asn, next, NULL, NULL);
160 if (found_ptr)
161 *found_ptr = found;
162 return *next;
163 }
164
165 void asn_relax_as_zero(bool relax)
166 {
167 relax_as_zero = relax;
168 }
169
170 enum match_type asn_str2asn_match(const char *str)
171 {
172 bool found, partial = false;
173
174 found = asn_str2asn_internal(str, NULL, NULL, &partial, NULL);
175 if (found && !partial)
176 return exact_match;
177
178 if (partial)
179 return partly_match;
180
181 return no_match;
182 }
183
184 bool 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
190 const char *asn_mode2str(enum asnotation_mode asnotation)
191 {
192 return lookup_msg(asnotation_mode_msg, asnotation,
193 "Unrecognized AS notation mode");
194 }
195
196 void 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
210 void 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
225 char *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
236 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 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;
247 asn_asn2string(asn, as_str, sizeof(as_str), asnotation);
248 return bputs(buf, as_str);
249 }
250
251 printfrr_ext_autoreg_p("ASP", printfrr_asplain);
252 static 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
258 printfrr_ext_autoreg_p("ASD", printfrr_asdot);
259 static 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
265 printfrr_ext_autoreg_p("ASE", printfrr_asdotplus);
266 static 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 }