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