LCOV - code coverage report
Current view: top level - vnet/ip - ip4_format.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 61 117 52.1 %
Date: 2023-10-26 01:39:38 Functions: 4 7 57.1 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 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             :  * ip/ip4_format.c: ip4 formatting
      17             :  *
      18             :  * Copyright (c) 2008 Eliot Dresselhaus
      19             :  *
      20             :  * Permission is hereby granted, free of charge, to any person obtaining
      21             :  * a copy of this software and associated documentation files (the
      22             :  * "Software"), to deal in the Software without restriction, including
      23             :  * without limitation the rights to use, copy, modify, merge, publish,
      24             :  * distribute, sublicense, and/or sell copies of the Software, and to
      25             :  * permit persons to whom the Software is furnished to do so, subject to
      26             :  * the following conditions:
      27             :  *
      28             :  * The above copyright notice and this permission notice shall be
      29             :  * included in all copies or substantial portions of the Software.
      30             :  *
      31             :  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      32             :  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      33             :  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      34             :  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      35             :  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      36             :  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      37             :  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      38             :  */
      39             : 
      40             : #include <vnet/ip/ip.h>
      41             : 
      42             : /* Format an IP4 address. */
      43             : u8 *
      44     3529960 : format_ip4_address (u8 * s, va_list * args)
      45             : {
      46     3529960 :   u8 *a = va_arg (*args, u8 *);
      47     3529960 :   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
      48             : }
      49             : 
      50             : /* Format an IP4 route destination and length. */
      51             : u8 *
      52        8476 : format_ip4_address_and_length (u8 * s, va_list * args)
      53             : {
      54        8476 :   u8 *a = va_arg (*args, u8 *);
      55        8476 :   u8 l = va_arg (*args, u32);
      56        8476 :   return format (s, "%U/%d", format_ip4_address, a, l);
      57             : }
      58             : 
      59             : u8 *
      60           0 : format_ip4_address_and_mask (u8 * s, va_list * args)
      61             : {
      62           0 :   ip4_address_and_mask_t *am = va_arg (*args, ip4_address_and_mask_t *);
      63             : 
      64           0 :   if (am->addr.as_u32 == 0 && am->mask.as_u32 == 0)
      65           0 :     return format (s, "any");
      66             : 
      67           0 :   if (am->mask.as_u32 == ~0)
      68           0 :     return format (s, "%U", format_ip4_address, &am->addr);
      69             : 
      70           0 :   return format (s, "%U/%U", format_ip4_address, &am->addr,
      71             :                  format_ip4_address, &am->mask);
      72             : }
      73             : 
      74             : /* Parse an IP4 address %d.%d.%d.%d. */
      75             : uword
      76         848 : unformat_ip4_address (unformat_input_t * input, va_list * args)
      77             : {
      78         848 :   u8 *result = va_arg (*args, u8 *);
      79             :   unsigned a[4];
      80             : 
      81         848 :   if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
      82         498 :     return 0;
      83             : 
      84         350 :   if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
      85           0 :     return 0;
      86             : 
      87         350 :   result[0] = a[0];
      88         350 :   result[1] = a[1];
      89         350 :   result[2] = a[2];
      90         350 :   result[3] = a[3];
      91             : 
      92         350 :   return 1;
      93             : }
      94             : 
      95             : uword
      96           0 : unformat_ip4_address_and_mask (unformat_input_t * input, va_list * args)
      97             : {
      98           0 :   ip4_address_and_mask_t *am = va_arg (*args, ip4_address_and_mask_t *);
      99           0 :   u32 addr = 0, mask = 0;
     100             : 
     101           0 :   if (unformat (input, "any"))
     102             :     ;
     103           0 :   else if (unformat (input, "%U/%U", unformat_ip4_address, &addr,
     104             :                      unformat_ip4_address, &mask))
     105             :     ;
     106           0 :   else if (unformat (input, "%U", unformat_ip4_address, &addr))
     107           0 :     mask = ~0;
     108             :   else
     109           0 :     return 0;
     110             : 
     111           0 :   am->addr.as_u32 = addr;
     112           0 :   am->mask.as_u32 = mask;
     113           0 :   return 1;
     114             : }
     115             : 
     116             : /* Format an IP4 header. */
     117             : u8 *
     118     1397000 : format_ip4_header (u8 * s, va_list * args)
     119             : {
     120     1397000 :   ip4_header_t *ip = va_arg (*args, ip4_header_t *);
     121     1397000 :   u32 max_header_bytes = va_arg (*args, u32);
     122             :   u32 ip_version, header_bytes;
     123             :   u32 indent;
     124             : 
     125             :   /* Nothing to do. */
     126     1397000 :   if (max_header_bytes < sizeof (ip[0]))
     127           0 :     return format (s, "IP header truncated");
     128             : 
     129     1397000 :   indent = format_get_indent (s);
     130     1397000 :   indent += 2;
     131             : 
     132     1397000 :   ip_version = (ip->ip_version_and_header_length >> 4);
     133     1397000 :   header_bytes = (ip->ip_version_and_header_length & 0xf) * sizeof (u32);
     134             : 
     135     1397000 :   s = format (s, "%U: %U -> %U",
     136     1397000 :               format_ip_protocol, ip->protocol,
     137     1397000 :               format_ip4_address, ip->src_address.data,
     138     1397000 :               format_ip4_address, ip->dst_address.data);
     139             : 
     140             :   /* Show IP version and header length only with unexpected values. */
     141     1397000 :   if (ip_version != 4 || header_bytes != sizeof (ip4_header_t))
     142        8289 :     s = format (s, "\n%Uversion %d, header length %d",
     143             :                 format_white_space, indent, ip_version, header_bytes);
     144             : 
     145     2794010 :   s = format (s, "\n%Utos 0x%02x, ttl %d, length %d, checksum 0x%04x",
     146             :               format_white_space, indent,
     147     1397000 :               ip->tos, ip->ttl,
     148     1397000 :               clib_net_to_host_u16 (ip->length),
     149     1397000 :               clib_net_to_host_u16 (ip->checksum));
     150             : 
     151             :   /* Check and report invalid checksums. */
     152             :   {
     153     1397000 :     if (!ip4_header_checksum_is_valid (ip))
     154             :       s =
     155        8514 :         format (s, " (should be 0x%04x)",
     156        8514 :                 clib_net_to_host_u16 (ip4_header_checksum (ip)));
     157             :   }
     158             : 
     159     1397000 :   s = format (s, " dscp %U ecn %U",
     160     1397000 :               format_ip_dscp, ip4_header_get_dscp (ip),
     161     1397000 :               format_ip_ecn, ip4_header_get_ecn (ip));
     162             : 
     163             :   {
     164     1397000 :     u32 f = clib_net_to_host_u16 (ip->flags_and_fragment_offset);
     165             :     u32 o;
     166             : 
     167     1397000 :     s = format (s, "\n%Ufragment id 0x%04x",
     168             :                 format_white_space, indent,
     169     1397000 :                 clib_net_to_host_u16 (ip->fragment_id));
     170             : 
     171             :     /* Fragment offset. */
     172     1397000 :     o = 8 * (f & 0x1fff);
     173     1397000 :     f ^= f & 0x1fff;
     174     1397000 :     if (o != 0)
     175       16611 :       s = format (s, " offset %d", o);
     176             : 
     177     1397000 :     if (f != 0)
     178             :       {
     179       14325 :         s = format (s, ", flags ");
     180             : #define _(l) if (f & IP4_HEADER_FLAG_##l) s = format (s, #l);
     181       14325 :         _(MORE_FRAGMENTS);
     182       14325 :         _(DONT_FRAGMENT);
     183       14325 :         _(CONGESTION);
     184             : #undef _
     185             :       }
     186             :     /* Fragment packet but not the first. */
     187     1397000 :     if (o != 0)
     188       16611 :       return s;
     189             :   }
     190             : 
     191             :   /* Recurse into next protocol layer. */
     192     1380390 :   if (max_header_bytes != 0 && header_bytes < max_header_bytes)
     193             :     {
     194     1380080 :       ip_main_t *im = &ip_main;
     195     1380080 :       ip_protocol_info_t *pi = ip_get_protocol_info (im, ip->protocol);
     196             : 
     197     1380080 :       if (pi && pi->format_header)
     198      942538 :         s = format (s, "\n%U%U",
     199             :                     format_white_space, indent - 2, pi->format_header,
     200             :                     /* next protocol header */ (void *) ip + header_bytes,
     201             :                     max_header_bytes - header_bytes);
     202             :     }
     203             : 
     204     1380390 :   return s;
     205             : }
     206             : 
     207             : /* Parse an IP4 header. */
     208             : uword
     209           0 : unformat_ip4_header (unformat_input_t * input, va_list * args)
     210             : {
     211           0 :   u8 **result = va_arg (*args, u8 **);
     212             :   ip4_header_t *ip;
     213             :   int old_length;
     214             : 
     215             :   /* Allocate space for IP header. */
     216             :   {
     217             :     void *p;
     218             : 
     219           0 :     old_length = vec_len (*result);
     220           0 :     vec_add2 (*result, p, sizeof (ip4_header_t));
     221           0 :     ip = p;
     222             :   }
     223             : 
     224           0 :   clib_memset (ip, 0, sizeof (ip[0]));
     225           0 :   ip->ip_version_and_header_length = IP4_VERSION_AND_HEADER_LENGTH_NO_OPTIONS;
     226             : 
     227           0 :   if (!unformat (input, "%U: %U -> %U",
     228             :                  unformat_ip_protocol, &ip->protocol,
     229             :                  unformat_ip4_address, &ip->src_address,
     230             :                  unformat_ip4_address, &ip->dst_address))
     231           0 :     return 0;
     232             : 
     233             :   /* Parse options. */
     234             :   while (1)
     235           0 :     {
     236             :       int i, j;
     237             : 
     238           0 :       if (unformat (input, "tos %U", unformat_vlib_number, &i))
     239           0 :         ip->tos = i;
     240             : 
     241           0 :       else if (unformat (input, "ttl %U", unformat_vlib_number, &i))
     242           0 :         ip->ttl = i;
     243             : 
     244           0 :       else if (unformat (input, "fragment id %U offset %U",
     245             :                          unformat_vlib_number, &i, unformat_vlib_number, &j))
     246             :         {
     247           0 :           ip->fragment_id = clib_host_to_net_u16 (i);
     248           0 :           ip->flags_and_fragment_offset |=
     249           0 :             clib_host_to_net_u16 ((i / 8) & 0x1fff);
     250             :         }
     251             : 
     252             :       /* Flags. */
     253           0 :       else if (unformat (input, "mf") || unformat (input, "MF"))
     254           0 :         ip->flags_and_fragment_offset |=
     255           0 :           clib_host_to_net_u16 (IP4_HEADER_FLAG_MORE_FRAGMENTS);
     256             : 
     257           0 :       else if (unformat (input, "df") || unformat (input, "DF"))
     258           0 :         ip->flags_and_fragment_offset |=
     259           0 :           clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT);
     260             : 
     261           0 :       else if (unformat (input, "ce") || unformat (input, "CE"))
     262           0 :         ip->flags_and_fragment_offset |=
     263           0 :           clib_host_to_net_u16 (IP4_HEADER_FLAG_CONGESTION);
     264             : 
     265             :       /* Can't parse input: try next protocol level. */
     266             :       else
     267             :         break;
     268             :     }
     269             : 
     270             :   /* Fill in checksum. */
     271           0 :   ip->checksum = ip4_header_checksum (ip);
     272             : 
     273             :   /* Recurse into next protocol layer. */
     274             :   {
     275           0 :     ip_main_t *im = &ip_main;
     276           0 :     ip_protocol_info_t *pi = ip_get_protocol_info (im, ip->protocol);
     277             : 
     278           0 :     if (pi && pi->unformat_header)
     279             :       {
     280           0 :         if (!unformat_user (input, pi->unformat_header, result))
     281           0 :           return 0;
     282             : 
     283             :         /* Result may have moved. */
     284           0 :         ip = (void *) *result + old_length;
     285             :       }
     286             :   }
     287             : 
     288             :   /* Fill in IP length. */
     289           0 :   ip->length = clib_host_to_net_u16 (vec_len (*result) - old_length);
     290             : 
     291           0 :   return 1;
     292             : }
     293             : 
     294             : /*
     295             :  * fd.io coding-style-patch-verification: ON
     296             :  *
     297             :  * Local Variables:
     298             :  * eval: (c-set-style "gnu")
     299             :  * End:
     300             :  */

Generated by: LCOV version 1.14