LCOV - code coverage report
Current view: top level - vppinfra - jsonformat.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 13 241 5.4 %
Date: 2023-10-26 01:39:38 Functions: 2 44 4.5 %

          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 _

Generated by: LCOV version 1.14