summaryrefslogtreecommitdiffstats
path: root/src/vnet/misc.c
diff options
context:
space:
mode:
authorBenoît Ganne <bganne@cisco.com>2019-02-07 13:21:42 +0100
committerFlorin Coras <florin.coras@gmail.com>2019-02-07 19:11:22 +0000
commit3d0ef26a0285b9baa486c91b2e6609125a2bc651 (patch)
tree98cb2d1ed6e60751a08c3b15c012785d033e9f1d /src/vnet/misc.c
parentd4c49be5e20406220cf89083c9df86c3c0761a81 (diff)
Fix parsing overflow in unformat_mac_address_t()
'%x' unformat specifier expects a pointer to a 4-byte object and will overflow when using a pointer to a 1-byte object. Use '%X' instead which allows to pass the size of the object alongside its pointer. The bug was exposed with the following commands: ~# make run DBGvpp# loop create loop0 DBGvpp# set ip6 neigh loop0 3001::2 a:a:a:a:a:a DBGvpp# show ip6 neigh Time Address Flags Link layer Interface 35.7743 ::2 D 0a:0a:0a:0a:0a:0a loop0 ^^^ wrong address: should be 3001::2 Note that the bug impact depends from the parsing order and memory layout. Change-Id: I29ba2eb53ba5a2daf4517215602d027508e2cb9f Signed-off-by: Benoît Ganne <bganne@cisco.com>
Diffstat (limited to 'src/vnet/misc.c')
0 files changed, 0 insertions, 0 deletions
a> 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
/*
 *------------------------------------------------------------------
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *------------------------------------------------------------------
 */

#include <stdint.h>
#include <sys/ioctl.h>
#include <inttypes.h>

#include <vlib/vlib.h>
#include <vlib/unix/unix.h>
#include <vnet/ip/ip.h>
#include <vnet/fib/fib_entry.h>
#include <vnet/fib/fib_table.h>
#include <vnet/mfib/mfib_table.h>

#include <igmp/igmp.h>

static clib_error_t *
igmp_clear_interface_command_fn (vlib_main_t * vm, unformat_input_t * input,
				 vlib_cli_command_t * cmd)
{
  unformat_input_t _line_input, *line_input = &_line_input;
  clib_error_t *error = NULL;
  vnet_main_t *vnm = vnet_get_main ();
  u32 sw_if_index;

  igmp_main_t *im = &igmp_main;
  igmp_config_t *config;

  if (!unformat_user (input, unformat_line_input, line_input))
    {
      error =
	clib_error_return (0, "'help clear igmp' or 'clear igmp ?' for help");
      return error;
    }

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat
	  (line_input, "int %U", unformat_vnet_sw_interface, vnm,
	   &sw_if_index));
      else
	{
	  error =
	    clib_error_return (0, "unknown input '%U'", format_unformat_error,
			       line_input);
	  goto done;
	}
    }

  config = igmp_config_lookup (im, sw_if_index);
  if (config)
    igmp_clear_config (config);

done:
  unformat_free (line_input);
  return error;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (igmp_clear_interface_command, static) = {
  .path = "clear igmp",
  .short_help = "clear igmp int <interface>",
  .function = igmp_clear_interface_command_fn,
};
/* *INDENT-ON* */

static clib_error_t *
igmp_listen_command_fn (vlib_main_t * vm, unformat_input_t * input,
			vlib_cli_command_t * cmd)
{
  unformat_input_t _line_input, *line_input = &_line_input;
  clib_error_t *error = NULL;
  u8 enable = 1;
  ip46_address_t saddr, gaddr;
  vnet_main_t *vnm = vnet_get_main ();
  u32 sw_if_index;
  int rv;

  if (!unformat_user (input, unformat_line_input, line_input))
    {
      error =
	clib_error_return (0,
			   "'help igmp listen' or 'igmp listen ?' for help");
      return error;
    }

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (line_input, "enable"))
	enable = 1;
      else if (unformat (line_input, "disable"))
	enable = 0;
      else
	if (unformat
	    (line_input, "int %U", unformat_vnet_sw_interface, vnm,
	     &sw_if_index));
      else
	if (unformat (line_input, "saddr %U", unformat_ip46_address, &saddr));
      else
	if (unformat (line_input, "gaddr %U", unformat_ip46_address, &gaddr));
      else
	{
	  error =
	    clib_error_return (0, "unknown input '%U'", format_unformat_error,
			       line_input);
	  goto done;
	}
    }

  if ((vnet_sw_interface_get_flags (vnm, sw_if_index)
       && VNET_SW_INTERFACE_FLAG_ADMIN_UP) == 0)
    {
      error = clib_error_return (0, "Interface is down");
      goto done;
    }

  rv = igmp_listen (vm, enable, sw_if_index, saddr, gaddr,
		    /* cli_api_listen */ 1);
  if (rv == -1)
    {
      if (enable)
	error =
	  clib_error_return (0, "This igmp configuration already exists");
      else
	error =
	  clib_error_return (0, "This igmp configuration does not nexist");
    }
  else if (rv == -2)
    error =
      clib_error_return (0,
			 "Failed to add configuration, interface is in router mode");

done:
  unformat_free (line_input);
  return error;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (igmp_listen_command, static) = {
  .path = "igmp listen",
  .short_help = "igmp listen [<enable|disable>] "
                "int <interface> saddr <ip4-address> gaddr <ip4-address>",
  .function = igmp_listen_command_fn,
};
/* *INDENT-ON* */

static clib_error_t *
igmp_show_command_fn (vlib_main_t * vm, unformat_input_t * input,
		      vlib_cli_command_t * cmd)
{
  clib_error_t *error = NULL;
  igmp_main_t *im = &igmp_main;
  vnet_main_t *vnm = vnet_get_main ();
  igmp_config_t *config;
  igmp_group_t *group;
  igmp_src_t *src;

  /* *INDENT-OFF* */
  pool_foreach (config, im->configs, (
    {
      vlib_cli_output (vm, "interface: %U", format_vnet_sw_if_index_name,
		       vnm, config->sw_if_index);
	pool_foreach (group, config->groups, (
	  {
	    vlib_cli_output (vm, "\t%U:%U", format_igmp_report_type, group->type, format_ip46_address, &group->addr, ip46_address_is_ip4 (&group->addr));
	    pool_foreach (src, group->srcs, (
	      {
		vlib_cli_output (vm, "\t\t%U", format_ip46_address, &src->addr, ip46_address_is_ip4 (&src->addr));
	      }));
	  }));
    }));
  /* *INDENT-ON* */

  return error;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (igmp_show_command, static) = {
  .path = "show igmp config",
  .short_help = "show igmp config",
  .function = igmp_show_command_fn,
};
/* *INDENT-ON* */

clib_error_t *
igmp_cli_init (vlib_main_t * vm)
{
  return 0;
}

VLIB_INIT_FUNCTION (igmp_cli_init);

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */