Line data Source code
1 : /*
2 : * Copyright (c) 2020 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : #include <vppinfra/cJSON.h>
17 : #include <vnet/ethernet/mac_address.h>
18 : #include <vnet/ip/ip6_packet.h>
19 : #include <vnet/ip/ip_format_fns.h>
20 : #include <vpp/api/types.h>
21 : #include "jsonformat.h"
22 :
23 : #define _(T) \
24 : int vl_api_##T##_fromjson (cJSON *o, T *d) \
25 : { \
26 : if (!cJSON_IsNumber (o)) \
27 : return -1; \
28 : d[0] = (T) cJSON_GetNumberValue (o); \
29 : return 0; \
30 : }
31 0 : foreach_type_fromjson
32 : #undef _
33 :
34 : int
35 0 : vl_api_bool_fromjson (cJSON *o, bool *d)
36 : {
37 0 : if (!cJSON_IsBool(o)) return -1;
38 0 : *d = o->valueint ? true : false;
39 0 : return 0;
40 : }
41 :
42 0 : int vl_api_u8_string_fromjson(cJSON *o, u8 *s, int len)
43 : {
44 : unformat_input_t input;
45 0 : char *p = cJSON_GetStringValue(o);
46 0 : unformat_init_string (&input, p, strlen(p));
47 0 : if (!unformat (&input, "0x%U", unformat_hex_string, s))
48 0 : return -1;
49 0 : return 0;
50 : }
51 :
52 : u8 *
53 0 : u8string_fromjson(cJSON *o, char *fieldname)
54 : {
55 0 : u8 *s = 0;
56 : unformat_input_t input;
57 0 : cJSON *item = cJSON_GetObjectItem(o, fieldname);
58 0 : if (!item) {
59 0 : printf("Illegal JSON, no such fieldname %s\n", fieldname);
60 0 : return 0;
61 : }
62 :
63 0 : char *p = cJSON_GetStringValue(item);
64 0 : unformat_init_string (&input, p, strlen(p));
65 0 : if (!unformat (&input, "0x%U", unformat_hex_string, &s))
66 0 : return 0;
67 0 : return s;
68 : }
69 :
70 : int
71 0 : u8string_fromjson2(cJSON *o, char *fieldname, u8 *data)
72 : {
73 0 : u8 *s = u8string_fromjson(o, fieldname);
74 0 : if (!s)
75 0 : return -1;
76 0 : memcpy(data, s, vec_len(s));
77 0 : vec_free(s);
78 0 : return 0;
79 : }
80 :
81 : /* Parse an IP4 address %d.%d.%d.%d. */
82 : uword
83 0 : unformat_ip4_address (unformat_input_t * input, va_list * args)
84 : {
85 0 : u8 *result = va_arg (*args, u8 *);
86 : unsigned a[4];
87 :
88 0 : if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
89 0 : return 0;
90 :
91 0 : if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
92 0 : return 0;
93 :
94 0 : result[0] = a[0];
95 0 : result[1] = a[1];
96 0 : result[2] = a[2];
97 0 : result[3] = a[3];
98 :
99 0 : return 1;
100 : }
101 :
102 : /* Parse an IP6 address. */
103 : uword
104 0 : unformat_ip6_address (unformat_input_t * input, va_list * args)
105 : {
106 0 : ip6_address_t *result = va_arg (*args, ip6_address_t *);
107 : u16 hex_quads[8];
108 : uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
109 : uword c, n_colon, double_colon_index;
110 :
111 0 : n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
112 0 : double_colon_index = ARRAY_LEN (hex_quads);
113 0 : while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
114 : {
115 0 : hex_digit = 16;
116 0 : if (c >= '0' && c <= '9')
117 0 : hex_digit = c - '0';
118 0 : else if (c >= 'a' && c <= 'f')
119 0 : hex_digit = c + 10 - 'a';
120 0 : else if (c >= 'A' && c <= 'F')
121 0 : hex_digit = c + 10 - 'A';
122 0 : else if (c == ':' && n_colon < 2)
123 0 : n_colon++;
124 : else
125 : {
126 0 : unformat_put_input (input);
127 0 : break;
128 : }
129 :
130 : /* Too many hex quads. */
131 0 : if (n_hex_quads >= ARRAY_LEN (hex_quads))
132 0 : return 0;
133 :
134 0 : if (hex_digit < 16)
135 : {
136 0 : hex_quad = (hex_quad << 4) | hex_digit;
137 :
138 : /* Hex quad must fit in 16 bits. */
139 0 : if (n_hex_digits >= 4)
140 0 : return 0;
141 :
142 0 : n_colon = 0;
143 0 : n_hex_digits++;
144 : }
145 :
146 : /* Save position of :: */
147 0 : if (n_colon == 2)
148 : {
149 : /* More than one :: ? */
150 0 : if (double_colon_index < ARRAY_LEN (hex_quads))
151 0 : return 0;
152 0 : double_colon_index = n_hex_quads;
153 : }
154 :
155 0 : if (n_colon > 0 && n_hex_digits > 0)
156 : {
157 0 : hex_quads[n_hex_quads++] = hex_quad;
158 0 : hex_quad = 0;
159 0 : n_hex_digits = 0;
160 : }
161 : }
162 :
163 0 : if (n_hex_digits > 0)
164 0 : hex_quads[n_hex_quads++] = hex_quad;
165 :
166 :
167 : {
168 : word i;
169 :
170 : /* Expand :: to appropriate number of zero hex quads. */
171 0 : if (double_colon_index < ARRAY_LEN (hex_quads))
172 : {
173 0 : word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
174 :
175 0 : for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
176 0 : hex_quads[n_zero + i] = hex_quads[i];
177 :
178 0 : for (i = 0; i < n_zero; i++)
179 : {
180 0 : ASSERT ((double_colon_index + i) < ARRAY_LEN (hex_quads));
181 0 : hex_quads[double_colon_index + i] = 0;
182 : }
183 :
184 0 : n_hex_quads = ARRAY_LEN (hex_quads);
185 : }
186 :
187 : /* Too few hex quads given. */
188 0 : if (n_hex_quads < ARRAY_LEN (hex_quads))
189 0 : return 0;
190 :
191 0 : for (i = 0; i < ARRAY_LEN (hex_quads); i++)
192 0 : result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
193 :
194 0 : return 1;
195 : }
196 : }
197 :
198 : u8 *
199 0 : format_ip6_address (u8 * s, va_list * args)
200 : {
201 0 : ip6_address_t *a = va_arg (*args, ip6_address_t *);
202 0 : u32 max_zero_run = 0, this_zero_run = 0;
203 0 : int max_zero_run_index = -1, this_zero_run_index = 0;
204 0 : int in_zero_run = 0, i;
205 0 : int last_double_colon = 0;
206 :
207 : /* Ugh, this is a pain. Scan forward looking for runs of 0's */
208 0 : for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
209 : {
210 0 : if (a->as_u16[i] == 0)
211 : {
212 0 : if (in_zero_run)
213 0 : this_zero_run++;
214 : else
215 : {
216 0 : in_zero_run = 1;
217 0 : this_zero_run = 1;
218 0 : this_zero_run_index = i;
219 : }
220 : }
221 : else
222 : {
223 0 : if (in_zero_run)
224 : {
225 : /* offer to compress the biggest run of > 1 zero */
226 0 : if (this_zero_run > max_zero_run && this_zero_run > 1)
227 : {
228 0 : max_zero_run_index = this_zero_run_index;
229 0 : max_zero_run = this_zero_run;
230 : }
231 : }
232 0 : in_zero_run = 0;
233 0 : this_zero_run = 0;
234 : }
235 : }
236 :
237 0 : if (in_zero_run)
238 : {
239 0 : if (this_zero_run > max_zero_run && this_zero_run > 1)
240 : {
241 0 : max_zero_run_index = this_zero_run_index;
242 0 : max_zero_run = this_zero_run;
243 : }
244 : }
245 :
246 0 : for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
247 : {
248 0 : if (i == max_zero_run_index)
249 : {
250 0 : s = format (s, "::");
251 0 : i += max_zero_run - 1;
252 0 : last_double_colon = 1;
253 : }
254 : else
255 : {
256 0 : s = format (s, "%s%x",
257 0 : (last_double_colon || i == 0) ? "" : ":",
258 0 : clib_net_to_host_u16 (a->as_u16[i]));
259 0 : last_double_colon = 0;
260 : }
261 : }
262 :
263 0 : return s;
264 : }
265 :
266 : int
267 0 : vl_api_ip4_address_t_fromjson (void **mp, int *len, cJSON *o,
268 : vl_api_ip4_address_t *a)
269 : {
270 : unformat_input_t input;
271 0 : char *p = cJSON_GetStringValue(o);
272 0 : if (!p)
273 0 : return -1;
274 0 : unformat_init_string (&input, p, strlen(p));
275 0 : if (!unformat (&input, "%U", unformat_ip4_address, a))
276 0 : return -1;
277 0 : return 0;
278 : }
279 :
280 : int
281 0 : vl_api_ip4_prefix_t_fromjson (void **mp, int *len, cJSON *o,
282 : vl_api_ip4_prefix_t *a)
283 : {
284 : unformat_input_t input;
285 0 : char *p = cJSON_GetStringValue(o);
286 0 : if (!p)
287 0 : return -1;
288 0 : unformat_init_string (&input, p, strlen(p));
289 0 : if (!unformat (&input, "%U/%d", unformat_ip4_address, &a->address,
290 : &a->len))
291 0 : return -1;
292 0 : return 0;
293 : }
294 :
295 : int
296 0 : vl_api_ip4_address_with_prefix_t_fromjson (void **mp, int *len, cJSON *o,
297 : vl_api_ip4_prefix_t *a)
298 : {
299 0 : return vl_api_ip4_prefix_t_fromjson(mp, len, o, a);
300 : }
301 : int
302 0 : vl_api_ip6_address_t_fromjson (void **mp, int *len, cJSON *o,
303 : vl_api_ip6_address_t *a)
304 : {
305 : unformat_input_t input;
306 0 : char *p = cJSON_GetStringValue(o);
307 0 : if (!p)
308 0 : return -1;
309 0 : unformat_init_string (&input, p, strlen(p));
310 0 : if (!unformat (&input, "%U", unformat_ip6_address, a))
311 0 : return -1;
312 0 : return 0;
313 : }
314 :
315 : int
316 0 : vl_api_ip6_prefix_t_fromjson (void **mp, int *len, cJSON *o,
317 : vl_api_ip6_prefix_t *a)
318 : {
319 : unformat_input_t input;
320 0 : char *p = cJSON_GetStringValue(o);
321 0 : if (!p)
322 0 : return -1;
323 0 : unformat_init_string (&input, p, strlen(p));
324 0 : if (!unformat (&input, "%U/%d", unformat_ip6_address, &a->address, &a->len))
325 0 : return -1;
326 0 : return 0;
327 : }
328 :
329 : int
330 0 : vl_api_ip6_address_with_prefix_t_fromjson (void **mp, int *len, cJSON *o,
331 : vl_api_ip6_prefix_t *a)
332 : {
333 0 : return vl_api_ip6_prefix_t_fromjson(mp, len, o, a);
334 : }
335 :
336 : int
337 0 : vl_api_address_t_fromjson (void **mp, int *len, cJSON *o, vl_api_address_t *a)
338 : {
339 : unformat_input_t input;
340 :
341 0 : char *p = cJSON_GetStringValue(o);
342 0 : if (!p)
343 0 : return -1;
344 0 : unformat_init_string (&input, p, strlen(p));
345 0 : if (unformat (&input, "%U", unformat_ip4_address, &a->un.ip4))
346 0 : a->af = ADDRESS_IP4;
347 0 : else if (unformat (&input, "%U", unformat_ip6_address, &a->un.ip6))
348 0 : a->af = ADDRESS_IP6;
349 : else
350 0 : return -1;
351 0 : return 0;
352 : }
353 :
354 : int
355 0 : vl_api_prefix_t_fromjson (void **mp, int *len, cJSON *o, vl_api_prefix_t *a)
356 : {
357 : unformat_input_t input;
358 :
359 0 : char *p = cJSON_GetStringValue(o);
360 :
361 0 : if (!p)
362 0 : return -1;
363 0 : unformat_init_string (&input, p, strlen(p));
364 : int plen;
365 0 : if (unformat (&input, "%U/%d", unformat_ip4_address, &a->address.un.ip4, &plen))
366 0 : a->address.af = ADDRESS_IP4;
367 0 : else if (unformat (&input, "%U/%d", unformat_ip6_address, &a->address.un.ip6, &plen))
368 0 : a->address.af = ADDRESS_IP6;
369 : else
370 0 : return -1;
371 0 : a->len = plen;
372 0 : return 0;
373 : }
374 :
375 : int
376 0 : vl_api_address_with_prefix_t_fromjson (void **mp, int *len, cJSON *o,
377 : vl_api_prefix_t *a)
378 : {
379 0 : return vl_api_prefix_t_fromjson(mp, len, o, a);
380 : }
381 :
382 : uword
383 0 : unformat_mac_address (unformat_input_t * input, va_list * args)
384 : {
385 0 : mac_address_t *mac = va_arg (*args, mac_address_t *);
386 : u32 i, a[3];
387 :
388 0 : if (unformat (input, "%_%X:%X:%X:%X:%X:%X%_",
389 : 1, &mac->bytes[0], 1, &mac->bytes[1], 1, &mac->bytes[2],
390 : 1, &mac->bytes[3], 1, &mac->bytes[4], 1, &mac->bytes[5]))
391 0 : return (1);
392 0 : else if (unformat (input, "%_%x.%x.%x%_", &a[0], &a[1], &a[2]))
393 : {
394 0 : for (i = 0; i < ARRAY_LEN (a); i++)
395 0 : if (a[i] >= (1 << 16))
396 0 : return 0;
397 :
398 0 : mac->bytes[0] = (a[0] >> 8) & 0xff;
399 0 : mac->bytes[1] = (a[0] >> 0) & 0xff;
400 0 : mac->bytes[2] = (a[1] >> 8) & 0xff;
401 0 : mac->bytes[3] = (a[1] >> 0) & 0xff;
402 0 : mac->bytes[4] = (a[2] >> 8) & 0xff;
403 0 : mac->bytes[5] = (a[2] >> 0) & 0xff;
404 :
405 0 : return (1);
406 : }
407 0 : return (0);
408 : }
409 :
410 : int
411 1 : vl_api_mac_address_t_fromjson (void **mp, int *len, cJSON *o,
412 : vl_api_mac_address_t *a)
413 : {
414 : unformat_input_t input;
415 :
416 1 : char *p = cJSON_GetStringValue(o);
417 1 : unformat_init_string (&input, p, strlen(p));
418 1 : if (!unformat (&input, "%U", unformat_mac_address, a))
419 0 : return -1;
420 1 : return 0;
421 : }
422 :
423 : /* Format an IP4 address. */
424 : u8 *
425 0 : format_ip4_address (u8 * s, va_list * args)
426 : {
427 0 : u8 *a = va_arg (*args, u8 *);
428 0 : return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
429 : }
430 :
431 : void
432 2 : vl_api_string_cJSON_AddToObject(cJSON * const object, const char * const name, vl_api_string_t *astr)
433 : {
434 :
435 2 : if (astr == 0) return;
436 2 : u32 length = clib_net_to_host_u32 (astr->length);
437 :
438 2 : char *cstr = malloc(length + 1);
439 2 : memcpy(cstr, astr->buf, length);
440 2 : cstr[length] = '\0';
441 2 : cJSON_AddStringToObject(object, name, cstr);
442 2 : free(cstr);
443 : }
444 :
445 : u8 *
446 0 : format_vl_api_timestamp_t(u8 * s, va_list * args)
447 : {
448 0 : f64 timestamp = va_arg (*args, f64);
449 : struct tm *tm;
450 : word msec;
451 :
452 0 : time_t t = timestamp;
453 0 : tm = gmtime (&t);
454 0 : msec = 1e6 * (timestamp - t);
455 0 : return format (s, "%4d-%02d-%02dT%02d:%02d:%02d.%06dZ", 1900 + tm->tm_year,
456 0 : 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min,
457 : tm->tm_sec, msec);
458 : }
459 :
460 : u8 *
461 0 : format_vl_api_timedelta_t(u8 * s, va_list * args)
462 : {
463 0 : return format_vl_api_timestamp_t(s, args);
464 : }
465 :
466 : uword
467 0 : unformat_vl_api_timedelta_t(unformat_input_t * input, va_list * args)
468 : {
469 0 : return 0;
470 : }
471 :
472 : uword
473 0 : unformat_vl_api_timestamp_t(unformat_input_t * input, va_list * args)
474 : {
475 0 : return 0;
476 : }
477 0 : uword unformat_vl_api_gbp_scope_t(unformat_input_t * input, va_list * args)
478 : {
479 0 : return 0;
480 : }
481 :
482 : cJSON *
483 0 : vl_api_ip4_address_with_prefix_t_tojson (vl_api_ip4_prefix_t *a) {
484 0 : return vl_api_ip4_prefix_t_tojson (a);
485 : }
486 : cJSON *
487 0 : vl_api_ip6_address_with_prefix_t_tojson (vl_api_ip6_prefix_t *a) {
488 0 : return vl_api_ip6_prefix_t_tojson (a);
489 : }
490 : cJSON *
491 0 : vl_api_address_with_prefix_t_tojson (vl_api_prefix_t *a) {
492 0 : return vl_api_prefix_t_tojson (a);
493 : }
494 : u8 *
495 0 : format_vl_api_mac_address_t (u8 * s, va_list * args)
496 : {
497 0 : const mac_address_t *mac = va_arg (*args, mac_address_t *);
498 :
499 0 : return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
500 0 : mac->bytes[0], mac->bytes[1], mac->bytes[2],
501 0 : mac->bytes[3], mac->bytes[4], mac->bytes[5]);
502 : }
503 : #define _(T) \
504 : cJSON *vl_api_ ##T## _t_tojson (vl_api_ ##T## _t *a) { \
505 : u8 *s = format(0, "%U", format_vl_api_ ##T## _t, a); \
506 : cJSON *o = cJSON_CreateString((char *)s); \
507 : vec_free(s); \
508 : return o; \
509 : }
510 0 : foreach_type_tojson
511 : #undef _
|