aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKlement Sekera <ksekera@cisco.com>2021-11-22 21:26:20 +0100
committerOle Tr�an <otroan@employees.org>2021-12-14 09:15:48 +0000
commit9b7e8acf792cced80e6775bc5668d9db415cdb46 (patch)
treeb600764a60f9978017a567390a025d2777b864a1
parent755042dec0fcc733d456adc2a74042c529eff039 (diff)
api: verify message size on receipt
When a message is received, verify that it's sufficiently large to accomodate any VLAs within message. To do that, we need a way to calculate message size including any VLAs. This patch adds such funcionality to vppapigen and necessary C code to use those to validate message size on receipt. Drop messages which are malformed. Type: improvement Signed-off-by: Klement Sekera <ksekera@cisco.com> Change-Id: I2903aa21dee84be6822b064795ba314de46c18f4
-rw-r--r--src/plugins/hs_apps/sapi/vpp_echo_bapi.c7
-rw-r--r--src/plugins/tracedump/tracedump_test.c6
-rw-r--r--src/tools/vppapigen/vppapigen_c.py110
-rw-r--r--src/vat/api_format.c14
-rw-r--r--src/vcl/vcl_bapi.c7
-rw-r--r--src/vlibapi/api_common.h17
-rw-r--r--src/vlibapi/api_shared.c89
-rw-r--r--src/vlibmemory/memclnt_api.c28
-rw-r--r--src/vlibmemory/memory_client.c29
-rw-r--r--src/vlibmemory/socket_api.c16
-rw-r--r--src/vlibmemory/socket_client.c16
-rw-r--r--src/vnet/ip/ip_api.c4
-rw-r--r--src/vnet/ip/ip_test.c4
-rw-r--r--src/vnet/ipsec/ipsec_test.c4
-rw-r--r--src/vnet/l2/l2_test.c4
-rw-r--r--src/vnet/srmpls/sr_mpls_api.c13
16 files changed, 280 insertions, 88 deletions
diff --git a/src/plugins/hs_apps/sapi/vpp_echo_bapi.c b/src/plugins/hs_apps/sapi/vpp_echo_bapi.c
index 30f3b78aff3..2e997096f85 100644
--- a/src/plugins/hs_apps/sapi/vpp_echo_bapi.c
+++ b/src/plugins/hs_apps/sapi/vpp_echo_bapi.c
@@ -548,6 +548,10 @@ _(APP_DEL_CERT_KEY_PAIR_REPLY, app_del_cert_key_pair_reply)
#include <vnet/session/session.api.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vnet/session/session.api.h>
+#undef vl_calcsizefun
+
#define vl_printfun
#include <vnet/session/session.api.h>
#undef vl_printfun
@@ -573,7 +577,8 @@ echo_api_hookup (echo_main_t * em)
REPLY_MSG_ID_BASE + VL_API_##N, #n, vl_api_##n##_t_handler, \
vl_noop_handler, vl_api_##n##_t_endian, vl_api_##n##_t_print, \
sizeof (vl_api_##n##_t), 1, vl_api_##n##_t_print_json, \
- vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson);
+ vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson, \
+ vl_api_##n##_t_calc_size);
foreach_quic_echo_msg;
#undef _
}
diff --git a/src/plugins/tracedump/tracedump_test.c b/src/plugins/tracedump/tracedump_test.c
index 05191a49ac4..abb81059199 100644
--- a/src/plugins/tracedump/tracedump_test.c
+++ b/src/plugins/tracedump/tracedump_test.c
@@ -242,6 +242,9 @@ api_trace_clear_capture (vat_main_t * vam)
#define vl_printfun
#include <tracedump/tracedump.api.h>
#undef vl_printfun
+#define vl_calcsizefun
+#include <tracedump/tracedump.api.h>
+#undef vl_calcsizefun
void
manual_setup_message_id_table (vat_main_t * vam)
@@ -251,7 +254,8 @@ manual_setup_message_id_table (vat_main_t * vam)
vl_api_trace_details_t_handler, vl_noop_handler,
vl_api_trace_details_t_endian, vl_api_trace_details_t_print,
sizeof (vl_api_trace_details_t), 1, vl_api_trace_details_t_print_json,
- vl_api_trace_details_t_tojson, vl_api_trace_details_t_fromjson);
+ vl_api_trace_details_t_tojson, vl_api_trace_details_t_fromjson,
+ vl_api_trace_details_t_calc_size);
}
#define VL_API_LOCAL_SETUP_MESSAGE_ID_TABLE manual_setup_message_id_table
diff --git a/src/tools/vppapigen/vppapigen_c.py b/src/tools/vppapigen/vppapigen_c.py
index 1e18a83e65e..f93e89843a3 100644
--- a/src/tools/vppapigen/vppapigen_c.py
+++ b/src/tools/vppapigen/vppapigen_c.py
@@ -210,7 +210,8 @@ class ToJSON():
if b[1] == 0:
continue
write(' if (a & {})\n'.format(b[0]))
- write(' cJSON_AddItemToArray(array, cJSON_CreateString("{}"));\n'.format(b[0]))
+ write(
+ ' cJSON_AddItemToArray(array, cJSON_CreateString("{}"));\n'.format(b[0]))
write(' return array;\n')
write('}\n')
@@ -685,7 +686,7 @@ TOP_BOILERPLATE = '''\
|| defined(vl_printfun) ||defined(vl_endianfun) \\
|| defined(vl_api_version)||defined(vl_typedefs) \\
|| defined(vl_msg_name)||defined(vl_msg_name_crc_list) \\
- || defined(vl_api_version_tuple)
+ || defined(vl_api_version_tuple) || defined(vl_calcsizefun)
/* ok, something was selected */
#else
#warning no content included from {input_filename}
@@ -750,7 +751,7 @@ def msg_name_crc_list(s, suffix):
for t in s['Define']:
output += "\\\n_(VL_API_%s, %s, %08x) " % \
- (t.name.upper(), t.name, t.crc)
+ (t.name.upper(), t.name, t.crc)
output += "\n#endif"
return output
@@ -970,13 +971,13 @@ static inline void *vl_api_{name}_t_print{suffix} (vl_api_{name}_t *a, void *han
write(signature.format(name=t.name, suffix='_json'))
write(' cJSON * o = vl_api_{}_t_tojson(a);\n'.format(t.name))
- write(' (void)s;\n');
+ write(' (void)s;\n')
write(' char *out = cJSON_Print(o);\n')
- write(' vl_print(handle, out);\n');
+ write(' vl_print(handle, out);\n')
write(' cJSON_Delete(o);\n')
- write(' cJSON_free(out);\n');
+ write(' cJSON_free(out);\n')
write(' return handle;\n')
- write('}\n\n');
+ write('}\n\n')
write("\n#endif")
write("\n#endif /* vl_printfun */\n")
@@ -1145,7 +1146,7 @@ static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a)
'''
for t in objs:
- if t.__class__.__name__ == 'Enum' or t.__class__.__name__ == 'EnumFlag' :
+ if t.__class__.__name__ == 'Enum' or t.__class__.__name__ == 'EnumFlag':
output += signature.format(name=t.name)
if t.enumtype in ENDIAN_STRINGS:
output += (' *a = {}(*a);\n'
@@ -1187,6 +1188,78 @@ static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a)
return output
+def calc_size_fun(objs, modulename):
+ '''Main entry point for calculate size function generation'''
+ output = '''\
+
+/****** Calculate size functions *****/\n\
+#ifdef vl_calcsizefun
+#ifndef included_{module}_calcsizefun
+#define included_{module}_calcsizefun
+
+'''
+ output = output.format(module=modulename)
+
+ signature = '''\
+/* calculate message size of message in network byte order */
+static inline uword vl_api_{name}_t_calc_size (vl_api_{name}_t *a)
+{{
+'''
+
+ for o in objs:
+ tname = o.__class__.__name__
+
+ output += signature.format(name=o.name)
+ output += f" return sizeof(*a)"
+ if tname == 'Using':
+ if 'length' in o.alias:
+ try:
+ tmp = int(o.alias['length'])
+ if tmp == 0:
+ raise (f"Unexpected length '0' for alias {o}")
+ except:
+ # output += f" + vl_api_{o.alias.name}_t_calc_size({o.name})"
+ print("culprit:")
+ print(o)
+ print(dir(o.alias))
+ print(o.alias)
+ raise
+ elif tname == 'Enum' or tname == 'EnumFlag':
+ pass
+ else:
+ for b in o.block:
+ if b.type == 'Option':
+ continue
+ elif b.type == 'Field':
+ if b.fieldtype.startswith('vl_api_'):
+ output += f" - sizeof(a->{b.fieldname})"
+ output += f" + {b.fieldtype}_calc_size(&a->{b.fieldname})"
+ elif b.type == 'Array':
+ if b.lengthfield:
+ m = list(filter(lambda x: x.fieldname == b.lengthfield, o.block))
+ if len(m) != 1:
+ raise Exception(f"Expected 1 match for field '{b.lengthfield}', got '{m}'")
+ lf = m[0]
+ if lf.fieldtype in ENDIAN_STRINGS:
+ output += f" + {ENDIAN_STRINGS[lf.fieldtype]}(a->{b.lengthfield}) * sizeof(a->{b.fieldname}[0])"
+ elif lf.fieldtype == "u8":
+ output += f" + a->{b.lengthfield} * sizeof(a->{b.fieldname}[0])"
+ else:
+ raise Exception(f"Don't know how to endian swap {lf.fieldtype}")
+ else:
+ # Fixed length strings decay to nul terminated u8
+ if b.fieldtype == 'string':
+ if b.modern_vla:
+ output += f" + vl_api_string_len(&a->{b.fieldname})"
+
+ output += ";\n"
+ output += '}\n\n'
+ output += "\n#endif"
+ output += "\n#endif /* vl_calcsizefun */\n\n"
+
+ return output
+
+
def version_tuple(s, module):
'''Generate semantic version string'''
output = '''\
@@ -1336,6 +1409,10 @@ def generate_c_boilerplate(services, defines, counters, file_crc,
#include "{module}.api.h"
#undef vl_endianfun
+#define vl_calcsizefun
+#include "{module}.api.h"
+#undef vl_calsizefun
+
/* instantiate all the print functions we know about */
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
#define vl_printfun
@@ -1371,6 +1448,7 @@ def generate_c_boilerplate(services, defines, counters, file_crc,
' .print_json = vl_api_{n}_t_print_json,\n'
' .tojson = vl_api_{n}_t_tojson,\n'
' .fromjson = vl_api_{n}_t_fromjson,\n'
+ ' .calc_size = vl_api_{n}_t_calc_size,\n'
' .is_autoendian = {auto}}};\n'
.format(n=s.caller, ID=s.caller.upper(),
auto=d.autoendian))
@@ -1389,6 +1467,7 @@ def generate_c_boilerplate(services, defines, counters, file_crc,
' .print_json = vl_api_{n}_t_print_json,\n'
' .tojson = vl_api_{n}_t_tojson,\n'
' .fromjson = vl_api_{n}_t_fromjson,\n'
+ ' .calc_size = vl_api_{n}_t_calc_size,\n'
' .is_autoendian = {auto}}};\n'
.format(n=s.reply, ID=s.reply.upper(),
auto=d.autoendian))
@@ -1427,6 +1506,10 @@ def generate_c_test_boilerplate(services, defines, file_crc, module, plugin,
#include "{module}.api.h"
#undef vl_endianfun
+#define vl_calcsizefun
+#include "{module}.api.h"
+#undef vl_calsizefun
+
/* instantiate all the print functions we know about */
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
#define vl_printfun
@@ -1488,7 +1571,8 @@ def generate_c_test_boilerplate(services, defines, file_crc, module, plugin,
' sizeof(vl_api_{n}_t), 1,\n'
' vl_api_{n}_t_print_json,\n'
' vl_api_{n}_t_tojson,\n'
- ' vl_api_{n}_t_fromjson);\n'
+ ' vl_api_{n}_t_fromjson,\n'
+ ' vl_api_{n}_t_calc_size);\n'
.format(n=s.reply, ID=s.reply.upper()))
write(' hash_set_mem (vam->function_by_name, "{n}", api_{n});\n'
.format(n=s.caller))
@@ -1510,7 +1594,8 @@ def generate_c_test_boilerplate(services, defines, file_crc, module, plugin,
' sizeof(vl_api_{n}_t), 1,\n'
' vl_api_{n}_t_print_json,\n'
' vl_api_{n}_t_tojson,\n'
- ' vl_api_{n}_t_fromjson);\n'
+ ' vl_api_{n}_t_fromjson,\n'
+ ' vl_api_{n}_t_calc_size);\n'
.format(n=e, ID=e.upper()))
write('}\n')
@@ -1729,6 +1814,10 @@ def generate_c_test2_boilerplate(services, defines, module, stream):
#include "{module}.api.h"
#undef vl_endianfun
+#define vl_calcsizefun
+#include "{module}.api.h"
+#undef vl_calsizefun
+
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
#define vl_printfun
#include "{module}.api.h"
@@ -1863,6 +1952,7 @@ def run(args, apifilename, s):
output += stream.getvalue()
stream.close()
output += endianfun(s['types'] + s['Define'], modulename)
+ output += calc_size_fun(s['types'] + s['Define'], modulename)
output += version_tuple(s, basename)
output += BOTTOM_BOILERPLATE.format(input_filename=basename,
file_crc=s['file_crc'])
diff --git a/src/vat/api_format.c b/src/vat/api_format.c
index a759ba25b1f..4827d55815c 100644
--- a/src/vat/api_format.c
+++ b/src/vat/api_format.c
@@ -64,6 +64,10 @@
#include <vlibmemory/memclnt.api.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vlibmemory/memclnt.api.h>
+#undef vl_calcsizefun
+
/* instantiate all the print functions we know about */
#if VPP_API_TEST_BUILTIN == 0
#define vl_print(handle, ...)
@@ -2737,11 +2741,11 @@ void
vat_api_hookup (vat_main_t * vam)
{
#define _(N, n) \
- vl_msg_api_set_handlers (VL_API_##N + 1, #n, vl_api_##n##_t_handler_uni, \
- vl_noop_handler, vl_api_##n##_t_endian, \
- vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 1, \
- vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
- vl_api_##n##_t_fromjson);
+ vl_msg_api_set_handlers ( \
+ VL_API_##N + 1, #n, vl_api_##n##_t_handler_uni, vl_noop_handler, \
+ vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 1, \
+ vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
+ vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);
foreach_vpe_api_reply_msg;
#if VPP_API_TEST_BUILTIN == 0
foreach_standalone_reply_msg;
diff --git a/src/vcl/vcl_bapi.c b/src/vcl/vcl_bapi.c
index 72440989727..bb2b94f04d8 100644
--- a/src/vcl/vcl_bapi.c
+++ b/src/vcl/vcl_bapi.c
@@ -276,6 +276,10 @@ vl_api_app_del_cert_key_pair_reply_t_handler (
#include <vnet/session/session.api.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vnet/session/session.api.h>
+#undef vl_calcsizefun
+
/* instantiate all the print functions we know about */
#define vl_printfun
#include <vnet/session/session.api.h>
@@ -303,7 +307,8 @@ vcl_bapi_hookup (void)
REPLY_MSG_ID_BASE + VL_API_##N, #n, vl_api_##n##_t_handler, \
vl_noop_handler, vl_api_##n##_t_endian, vl_api_##n##_t_print, \
sizeof (vl_api_##n##_t), 1, vl_api_##n##_t_print_json, \
- vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson);
+ vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson, \
+ vl_api_##n##_t_calc_size);
foreach_sock_msg;
#undef _
}
diff --git a/src/vlibapi/api_common.h b/src/vlibapi/api_common.h
index 320e7c44e16..6b36314e7bb 100644
--- a/src/vlibapi/api_common.h
+++ b/src/vlibapi/api_common.h
@@ -132,6 +132,7 @@ typedef struct
void *print_json; /**< message print function (JSON format) */
void *tojson; /**< binary to JSON convert function */
void *fromjson; /**< JSON to binary convert function */
+ void *calc_size; /**< message size calculation */
int size; /**< message size */
int traced; /**< is this message to be traced? */
int replay; /**< is this message to be replayed? */
@@ -170,17 +171,18 @@ VL_MSG_API_POISON (const void *a)
}
/* api_shared.c prototypes */
-void vl_msg_api_handler (void *the_msg);
-void vl_msg_api_handler_no_free (void *the_msg);
-void vl_msg_api_handler_no_trace_no_free (void *the_msg);
-void vl_msg_api_trace_only (void *the_msg);
+void vl_msg_api_handler (void *the_msg, uword msg_len);
+void vl_msg_api_handler_no_free (void *the_msg, uword msg_len);
+void vl_msg_api_handler_no_trace_no_free (void *the_msg, uword msg_len);
+void vl_msg_api_trace_only (void *the_msg, uword msg_len);
void vl_msg_api_cleanup_handler (void *the_msg);
void vl_msg_api_replay_handler (void *the_msg);
-void vl_msg_api_socket_handler (void *the_msg);
+void vl_msg_api_socket_handler (void *the_msg, uword msg_len);
void vl_msg_api_set_handlers (int msg_id, char *msg_name, void *handler,
void *cleanup, void *endian, void *print,
int msg_size, int traced, void *print_json,
- void *tojson, void *fromjson);
+ void *tojson, void *fromjson,
+ void *validate_size);
void vl_msg_api_clean_handlers (int msg_id);
void vl_msg_api_config (vl_msg_api_msg_config_t *);
void vl_msg_api_set_cleanup_handler (int msg_id, void *fp);
@@ -251,6 +253,9 @@ typedef struct api_main_t
/** Message convert function vector */
void *(**msg_fromjson_handlers) (cJSON *, int *);
+ /** Message calc size function vector */
+ uword (**msg_calc_size_funcs) (void *);
+
/** Message name vector */
const char **msg_names;
diff --git a/src/vlibapi/api_shared.c b/src/vlibapi/api_shared.c
index dd51ee5fae1..f11344e6e66 100644
--- a/src/vlibapi/api_shared.c
+++ b/src/vlibapi/api_shared.c
@@ -500,8 +500,8 @@ vl_msg_api_barrier_release (void)
}
always_inline void
-msg_handler_internal (api_main_t * am,
- void *the_msg, int trace_it, int do_it, int free_it)
+msg_handler_internal (api_main_t *am, void *the_msg, uword msg_len,
+ int trace_it, int do_it, int free_it)
{
u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
u8 *(*print_fp) (void *, void *);
@@ -545,8 +545,35 @@ msg_handler_internal (api_main_t * am,
}
}
- if (do_it)
+ uword calc_size = 0;
+ uword (*calc_size_fp) (void *);
+ calc_size_fp = am->msg_calc_size_funcs[id];
+ ASSERT (NULL != calc_size_fp);
+ if (calc_size_fp)
{
+ calc_size = (*calc_size_fp) (the_msg);
+ ASSERT (calc_size <= msg_len);
+ if (calc_size > msg_len)
+ {
+ clib_warning (
+ "Truncated message '%s' (id %u) received, calculated size "
+ "%lu is bigger than actual size %llu, message dropped.",
+ am->msg_names[id], id, calc_size, msg_len);
+ }
+ }
+ else
+ {
+ clib_warning ("Message '%s' (id %u) has NULL calc_size_func, cannot "
+ "verify message size is correct",
+ am->msg_names[id], id);
+ }
+
+ /* don't process message if it's truncated, otherwise byte swaps
+ * and stuff could corrupt memory even beyond message if it's malicious
+ * e.g. VLA length field set to 1M elements, but VLA empty */
+ if (do_it && calc_size <= msg_len)
+ {
+
if (!am->is_mp_safe[id])
{
vl_msg_api_barrier_trace_context (am->msg_names[id]);
@@ -569,6 +596,7 @@ msg_handler_internal (api_main_t * am,
if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
clib_call_callbacks (am->perf_counter_cbs, am, id,
1 /* after */ );
+
if (!am->is_mp_safe[id])
vl_msg_api_barrier_release ();
}
@@ -767,32 +795,30 @@ vl_msg_api_handler_with_vm_node (api_main_t * am, svm_region_t * vlib_rp,
}
void
-vl_msg_api_handler (void *the_msg)
+vl_msg_api_handler (void *the_msg, uword msg_len)
{
api_main_t *am = vlibapi_get_main ();
- msg_handler_internal (am, the_msg,
- (am->rx_trace
- && am->rx_trace->enabled) /* trace_it */ ,
- 1 /* do_it */ , 1 /* free_it */ );
+ msg_handler_internal (am, the_msg, msg_len,
+ (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
+ 1 /* do_it */, 1 /* free_it */);
}
void
-vl_msg_api_handler_no_free (void *the_msg)
+vl_msg_api_handler_no_free (void *the_msg, uword msg_len)
{
api_main_t *am = vlibapi_get_main ();
- msg_handler_internal (am, the_msg,
- (am->rx_trace
- && am->rx_trace->enabled) /* trace_it */ ,
- 1 /* do_it */ , 0 /* free_it */ );
+ msg_handler_internal (am, the_msg, msg_len,
+ (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
+ 1 /* do_it */, 0 /* free_it */);
}
void
-vl_msg_api_handler_no_trace_no_free (void *the_msg)
+vl_msg_api_handler_no_trace_no_free (void *the_msg, uword msg_len)
{
api_main_t *am = vlibapi_get_main ();
- msg_handler_internal (am, the_msg, 0 /* trace_it */ , 1 /* do_it */ ,
- 0 /* free_it */ );
+ msg_handler_internal (am, the_msg, msg_len, 0 /* trace_it */, 1 /* do_it */,
+ 0 /* free_it */);
}
/*
@@ -805,14 +831,13 @@ vl_msg_api_handler_no_trace_no_free (void *the_msg)
*
*/
void
-vl_msg_api_trace_only (void *the_msg)
+vl_msg_api_trace_only (void *the_msg, uword msg_len)
{
api_main_t *am = vlibapi_get_main ();
- msg_handler_internal (am, the_msg,
- (am->rx_trace
- && am->rx_trace->enabled) /* trace_it */ ,
- 0 /* do_it */ , 0 /* free_it */ );
+ msg_handler_internal (am, the_msg, msg_len,
+ (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
+ 0 /* do_it */, 0 /* free_it */);
}
void
@@ -863,14 +888,13 @@ vl_msg_api_get_msg_length (void *msg_arg)
* vl_msg_api_socket_handler
*/
void
-vl_msg_api_socket_handler (void *the_msg)
+vl_msg_api_socket_handler (void *the_msg, uword msg_len)
{
api_main_t *am = vlibapi_get_main ();
- msg_handler_internal (am, the_msg,
- (am->rx_trace
- && am->rx_trace->enabled) /* trace_it */ ,
- 1 /* do_it */ , 0 /* free_it */ );
+ msg_handler_internal (am, the_msg, msg_len,
+ (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
+ 1 /* do_it */, 0 /* free_it */);
}
#define foreach_msg_api_vector \
@@ -882,6 +906,7 @@ vl_msg_api_socket_handler (void *the_msg)
_ (msg_print_json_handlers) \
_ (msg_tojson_handlers) \
_ (msg_fromjson_handlers) \
+ _ (msg_calc_size_funcs) \
_ (api_trace_cfg) \
_ (message_bounce) \
_ (is_mp_safe) \
@@ -927,6 +952,7 @@ vl_msg_api_config (vl_msg_api_msg_config_t * c)
am->msg_print_json_handlers[c->id] = c->print_json;
am->msg_tojson_handlers[c->id] = c->tojson;
am->msg_fromjson_handlers[c->id] = c->fromjson;
+ am->msg_calc_size_funcs[c->id] = c->calc_size;
am->message_bounce[c->id] = c->message_bounce;
am->is_mp_safe[c->id] = c->is_mp_safe;
am->is_autoendian[c->id] = c->is_autoendian;
@@ -948,7 +974,8 @@ vl_msg_api_config (vl_msg_api_msg_config_t * c)
void
vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
void *endian, void *print, int size, int traced,
- void *print_json, void *tojson, void *fromjson)
+ void *print_json, void *tojson, void *fromjson,
+ void *calc_size)
{
vl_msg_api_msg_config_t cfg;
vl_msg_api_msg_config_t *c = &cfg;
@@ -969,6 +996,7 @@ vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
c->tojson = tojson;
c->fromjson = fromjson;
c->print_json = print_json;
+ c->calc_size = calc_size;
vl_msg_api_config (c);
}
@@ -999,8 +1027,11 @@ vl_msg_api_queue_handler (svm_queue_t * q)
{
uword msg;
- while (!svm_queue_sub (q, (u8 *) & msg, SVM_Q_WAIT, 0))
- vl_msg_api_handler ((void *) msg);
+ while (!svm_queue_sub (q, (u8 *) &msg, SVM_Q_WAIT, 0))
+ {
+ msgbuf_t *msgbuf = (msgbuf_t *) ((u8 *) msg - offsetof (msgbuf_t, data));
+ vl_msg_api_handler ((void *) msg, ntohl (msgbuf->data_len));
+ }
}
u32
diff --git a/src/vlibmemory/memclnt_api.c b/src/vlibmemory/memclnt_api.c
index 2b4a2393db3..87bb36a5426 100644
--- a/src/vlibmemory/memclnt_api.c
+++ b/src/vlibmemory/memclnt_api.c
@@ -58,6 +58,10 @@
#include <vlibmemory/vl_memory_api_h.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vlibmemory/vl_memory_api_h.h>
+#undef vl_calcsizefun
+
static void
vl_api_get_first_msg_id_t_handler (vl_api_get_first_msg_id_t *mp)
{
@@ -177,6 +181,7 @@ vlib_api_init (void)
c->print_json = vl_api_##n##_t_print_json; \
c->tojson = vl_api_##n##_t_tojson; \
c->fromjson = vl_api_##n##_t_fromjson; \
+ c->calc_size = vl_api_##n##_t_calc_size; \
c->size = sizeof (vl_api_##n##_t); \
c->traced = 1; /* trace, so these msgs print */ \
c->replay = 0; /* don't replay client create/delete msgs */ \
@@ -505,8 +510,9 @@ api_rx_from_node (vlib_main_t *vm, vlib_node_runtime_t *node,
vec_add (long_msg, msg, msg_len);
}
msg = long_msg;
+ msg_len = vec_len (long_msg);
}
- vl_msg_api_handler_no_trace_no_free (msg);
+ vl_msg_api_handler_no_trace_no_free (msg, msg_len);
}
/* Free what we've been given. */
@@ -704,20 +710,20 @@ rpc_api_hookup (vlib_main_t *vm)
{
api_main_t *am = vlibapi_get_main ();
#define _(N, n) \
- vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \
- vl_noop_handler, vl_noop_handler, \
- vl_api_##n##_t_print, sizeof (vl_api_##n##_t), \
- 0 /* do not trace */, vl_api_##n##_t_print_json, \
- vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson);
+ vl_msg_api_set_handlers ( \
+ VL_API_##N, #n, vl_api_##n##_t_handler, vl_noop_handler, vl_noop_handler, \
+ vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0 /* do not trace */, \
+ vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
+ vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);
foreach_rpc_api_msg;
#undef _
#define _(N, n) \
- vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \
- vl_noop_handler, vl_noop_handler, \
- vl_api_##n##_t_print, sizeof (vl_api_##n##_t), \
- 1 /* do trace */, vl_api_##n##_t_print_json, \
- vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson);
+ vl_msg_api_set_handlers ( \
+ VL_API_##N, #n, vl_api_##n##_t_handler, vl_noop_handler, vl_noop_handler, \
+ vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 1 /* do trace */, \
+ vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
+ vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);
foreach_plugin_trace_msg;
#undef _
diff --git a/src/vlibmemory/memory_client.c b/src/vlibmemory/memory_client.c
index f0b05b70695..54bc8d8f859 100644
--- a/src/vlibmemory/memory_client.c
+++ b/src/vlibmemory/memory_client.c
@@ -39,6 +39,10 @@
#include <vlibmemory/vl_memory_api_h.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vlibmemory/vl_memory_api_h.h>
+#undef vl_calcsizefun
+
/* instantiate all the print functions we know about */
#define vl_print(handle, ...) clib_warning (__VA_ARGS__)
#define vl_printfun
@@ -240,7 +244,8 @@ vl_client_connect (const char *name, int ctx_quota, int input_queue_size)
}
rv = clib_net_to_host_u32 (rp->response);
- vl_msg_api_handler ((void *) rp);
+ msgbuf_t *msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data));
+ vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len));
break;
}
return (rv);
@@ -289,6 +294,7 @@ vl_client_disconnect (void)
svm_queue_t *vl_input_queue;
api_main_t *am = vlibapi_get_main ();
time_t begin;
+ msgbuf_t *msgbuf;
vl_input_queue = am->vl_input_queue;
vl_client_send_disconnect (0 /* wait for reply */ );
@@ -321,10 +327,12 @@ vl_client_disconnect (void)
if (ntohs (rp->_vl_msg_id) != VL_API_MEMCLNT_DELETE_REPLY)
{
clib_warning ("queue drain: %d", ntohs (rp->_vl_msg_id));
- vl_msg_api_handler ((void *) rp);
+ msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data));
+ vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len));
continue;
}
- vl_msg_api_handler ((void *) rp);
+ msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data));
+ vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len));
break;
}
@@ -364,11 +372,11 @@ vl_client_install_client_message_handlers (void)
{
api_main_t *am = vlibapi_get_main ();
#define _(N, n) \
- vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \
- noop_handler, vl_api_##n##_t_endian, \
- vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0, \
- vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
- vl_api_##n##_t_fromjson); \
+ vl_msg_api_set_handlers ( \
+ VL_API_##N, #n, vl_api_##n##_t_handler, noop_handler, \
+ vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0, \
+ vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
+ vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size); \
am->api_trace_cfg[VL_API_##N].replay_enable = 0;
foreach_api_msg;
#undef _
@@ -569,6 +577,11 @@ vl_client_get_first_plugin_msg_id (const char *plugin_name)
old_handler = am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY];
am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = (void *)
vl_api_get_first_msg_id_reply_t_handler;
+ if (!am->msg_calc_size_funcs[VL_API_GET_FIRST_MSG_ID_REPLY])
+ {
+ am->msg_calc_size_funcs[VL_API_GET_FIRST_MSG_ID_REPLY] =
+ (uword (*) (void *)) vl_api_get_first_msg_id_reply_t_calc_size;
+ }
/* Ask the data-plane for the message-ID base of the indicated plugin */
mm->first_msg_id_reply_ready = 0;
diff --git a/src/vlibmemory/socket_api.c b/src/vlibmemory/socket_api.c
index ce834a70aac..3e3f7d5bc04 100644
--- a/src/vlibmemory/socket_api.c
+++ b/src/vlibmemory/socket_api.c
@@ -45,6 +45,10 @@
#include <vlibmemory/vl_memory_api_h.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vlibmemory/vl_memory_api_h.h>
+#undef vl_calcsizefun
+
socket_main_t socket_main;
#define SOCK_API_REG_HANDLE_BIT (1<<31)
@@ -200,7 +204,7 @@ vl_socket_process_api_msg (vl_api_registration_t * rp, i8 * input_v)
u8 *the_msg = (u8 *) (mbp->data);
socket_main.current_rp = rp;
- vl_msg_api_socket_handler (the_msg);
+ vl_msg_api_socket_handler (the_msg, ntohl (mbp->data_len));
socket_main.current_rp = 0;
}
@@ -792,11 +796,11 @@ vl_sock_api_init (vlib_main_t * vm)
return 0;
#define _(N, n, t) \
- vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \
- vl_noop_handler, vl_api_##n##_t_endian, \
- vl_api_##n##_t_print, sizeof (vl_api_##n##_t), t, \
- vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
- vl_api_##n##_t_fromjson); \
+ vl_msg_api_set_handlers ( \
+ VL_API_##N, #n, vl_api_##n##_t_handler, vl_noop_handler, \
+ vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), t, \
+ vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
+ vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size); \
am->api_trace_cfg[VL_API_##N].replay_enable = 0;
foreach_vlib_api_msg;
#undef _
diff --git a/src/vlibmemory/socket_client.c b/src/vlibmemory/socket_client.c
index 2fb6b8a0c4e..7082d8ba7e0 100644
--- a/src/vlibmemory/socket_client.c
+++ b/src/vlibmemory/socket_client.c
@@ -36,6 +36,10 @@
#include <vlibmemory/vl_memory_api_h.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vlibmemory/vl_memory_api_h.h>
+#undef vl_calcsizefun
+
/* instantiate all the print functions we know about */
#define vl_print(handle, ...) clib_warning (__VA_ARGS__)
#define vl_printfun
@@ -134,7 +138,7 @@ vl_socket_client_read_internal (socket_client_main_t * scm, int wait)
if (vec_len (scm->socket_rx_buffer) >= data_len + sizeof (*mbp))
{
- vl_msg_api_socket_handler ((void *) (mbp->data));
+ vl_msg_api_socket_handler ((void *) (mbp->data), data_len);
if (vec_len (scm->socket_rx_buffer) == data_len + sizeof (*mbp))
_vec_len (scm->socket_rx_buffer) = 0;
@@ -433,11 +437,11 @@ vl_sock_client_install_message_handlers (void)
{
#define _(N, n) \
- vl_msg_api_set_handlers (VL_API_##N, #n, vl_api_##n##_t_handler, \
- noop_handler, vl_api_##n##_t_endian, \
- vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0, \
- vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
- vl_api_##n##_t_fromjson);
+ vl_msg_api_set_handlers ( \
+ VL_API_##N, #n, vl_api_##n##_t_handler, noop_handler, \
+ vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 0, \
+ vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
+ vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);
foreach_sock_client_api_msg;
#undef _
}
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index e197057d8c5..b1b7ff3a7ae 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -514,7 +514,9 @@ vl_api_add_del_ip_punt_redirect_v2_t_handler (
goto out;
if (0 != n_paths)
- vec_validate (rpaths, n_paths - 1);
+ {
+ vec_validate (rpaths, n_paths - 1);
+ }
for (ii = 0; ii < n_paths; ii++)
{
diff --git a/src/vnet/ip/ip_test.c b/src/vnet/ip/ip_test.c
index c47cd3d208e..f87b47f8912 100644
--- a/src/vnet/ip/ip_test.c
+++ b/src/vnet/ip/ip_test.c
@@ -36,6 +36,10 @@
#include <vnet/ip/ip.api.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vnet/ip/ip.api.h>
+#undef vl_calcsizefun
+
typedef struct
{
/* API message ID base */
diff --git a/src/vnet/ipsec/ipsec_test.c b/src/vnet/ipsec/ipsec_test.c
index f399032eb9a..f3a9992e916 100644
--- a/src/vnet/ipsec/ipsec_test.c
+++ b/src/vnet/ipsec/ipsec_test.c
@@ -26,6 +26,10 @@
#include <vnet/ipsec/ipsec.api.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vnet/ipsec/ipsec.api.h>
+#undef vl_calcsizefun
+
typedef struct
{
/* API message ID base */
diff --git a/src/vnet/l2/l2_test.c b/src/vnet/l2/l2_test.c
index c7cd1d255c1..3be4a46223d 100644
--- a/src/vnet/l2/l2_test.c
+++ b/src/vnet/l2/l2_test.c
@@ -28,6 +28,10 @@
#include <vnet/l2/l2.api.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vnet/l2/l2.api.h>
+#undef vl_calcsizefun
+
typedef struct
{
/* API message ID base */
diff --git a/src/vnet/srmpls/sr_mpls_api.c b/src/vnet/srmpls/sr_mpls_api.c
index 7d42f1ba451..45107f08ab1 100644
--- a/src/vnet/srmpls/sr_mpls_api.c
+++ b/src/vnet/srmpls/sr_mpls_api.c
@@ -39,6 +39,10 @@
#include <vnet/srmpls/sr_mpls.api.h>
#undef vl_endianfun
+#define vl_calcsizefun
+#include <vnet/srmpls/sr_mpls.api.h>
+#undef vl_calcsizefun
+
#define vl_printfun
#include <vnet/srmpls/sr_mpls.api.h>
#undef vl_printfun
@@ -194,7 +198,8 @@ sr_mpls_api_hookup (vlib_main_t * vm)
REPLY_MSG_ID_BASE + VL_API_##N, #n, vl_api_##n##_t_handler, \
vl_noop_handler, vl_api_##n##_t_endian, vl_api_##n##_t_print, \
sizeof (vl_api_##n##_t), 1, vl_api_##n##_t_print_json, \
- vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson);
+ vl_api_##n##_t_tojson, vl_api_##n##_t_fromjson, \
+ vl_api_##n##_t_calc_size);
foreach_vpe_api_msg;
#undef _
@@ -207,7 +212,8 @@ sr_mpls_api_hookup (vlib_main_t * vm)
vl_api_sr_mpls_policy_add_t_handler, vl_noop_handler,
vl_api_sr_mpls_policy_add_t_endian, vl_api_sr_mpls_policy_add_t_print, 256,
1, vl_api_sr_mpls_policy_add_t_print_json,
- vl_api_sr_mpls_policy_mod_t_tojson, vl_api_sr_mpls_policy_mod_t_fromjson);
+ vl_api_sr_mpls_policy_add_t_tojson, vl_api_sr_mpls_policy_add_t_fromjson,
+ vl_api_sr_mpls_policy_add_t_calc_size);
/*
* Manually register the sr policy mod msg, so we trace enough bytes
@@ -218,7 +224,8 @@ sr_mpls_api_hookup (vlib_main_t * vm)
vl_api_sr_mpls_policy_mod_t_handler, vl_noop_handler,
vl_api_sr_mpls_policy_mod_t_endian, vl_api_sr_mpls_policy_mod_t_print, 256,
1, vl_api_sr_mpls_policy_mod_t_print_json,
- vl_api_sr_mpls_policy_mod_t_tojson, vl_api_sr_mpls_policy_mod_t_fromjson);
+ vl_api_sr_mpls_policy_mod_t_tojson, vl_api_sr_mpls_policy_mod_t_fromjson,
+ vl_api_sr_mpls_policy_mod_t_calc_size);
/*
* Set up the (msg_name, crc, message-id) table