From 9b7e8acf792cced80e6775bc5668d9db415cdb46 Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Mon, 22 Nov 2021 21:26:20 +0100 Subject: [PATCH] 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 Change-Id: I2903aa21dee84be6822b064795ba314de46c18f4 --- src/plugins/hs_apps/sapi/vpp_echo_bapi.c | 7 +- src/plugins/tracedump/tracedump_test.c | 6 +- src/tools/vppapigen/vppapigen_c.py | 110 ++++++++++++++++++++++++++++--- src/vat/api_format.c | 14 ++-- src/vcl/vcl_bapi.c | 7 +- src/vlibapi/api_common.h | 17 +++-- src/vlibapi/api_shared.c | 89 +++++++++++++++++-------- src/vlibmemory/memclnt_api.c | 28 ++++---- src/vlibmemory/memory_client.c | 29 +++++--- src/vlibmemory/socket_api.c | 16 +++-- src/vlibmemory/socket_client.c | 16 +++-- src/vnet/ip/ip_api.c | 4 +- src/vnet/ip/ip_test.c | 4 ++ src/vnet/ipsec/ipsec_test.c | 4 ++ src/vnet/l2/l2_test.c | 4 ++ src/vnet/srmpls/sr_mpls_api.c | 13 +++- 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 #undef vl_endianfun +#define vl_calcsizefun +#include +#undef vl_calcsizefun + #define vl_printfun #include #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 #undef vl_printfun +#define vl_calcsizefun +#include +#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 #undef vl_endianfun +#define vl_calcsizefun +#include +#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 #undef vl_endianfun +#define vl_calcsizefun +#include +#undef vl_calcsizefun + /* instantiate all the print functions we know about */ #define vl_printfun #include @@ -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 #undef vl_endianfun +#define vl_calcsizefun +#include +#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 #undef vl_endianfun +#define vl_calcsizefun +#include +#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 #undef vl_endianfun +#define vl_calcsizefun +#include +#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 #undef vl_endianfun +#define vl_calcsizefun +#include +#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 #undef vl_endianfun +#define vl_calcsizefun +#include +#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 #undef vl_endianfun +#define vl_calcsizefun +#include +#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 #undef vl_endianfun +#define vl_calcsizefun +#include +#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 #undef vl_endianfun +#define vl_calcsizefun +#include +#undef vl_calcsizefun + #define vl_printfun #include #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 -- 2.16.6