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