diff options
Diffstat (limited to 'zebra/zapi_msg.c')
| -rw-r--r-- | zebra/zapi_msg.c | 91 |
1 files changed, 62 insertions, 29 deletions
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 16714acc6e..cea8edf752 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -24,23 +24,16 @@ #include <libgen.h> #include "lib/prefix.h" -#include "lib/command.h" -#include "lib/if.h" -#include "lib/thread.h" #include "lib/stream.h" #include "lib/memory.h" #include "lib/table.h" #include "lib/network.h" -#include "lib/sockunion.h" #include "lib/log.h" #include "lib/zclient.h" #include "lib/privs.h" -#include "lib/network.h" -#include "lib/buffer.h" #include "lib/nexthop.h" #include "lib/vrf.h" #include "lib/libfrr.h" -#include "lib/sockopt.h" #include "lib/lib_errors.h" #include "zebra/zebra_router.h" @@ -52,7 +45,6 @@ #include "zebra/redistribute.h" #include "zebra/debug.h" #include "zebra/zebra_rnh.h" -#include "zebra/rt_netlink.h" #include "zebra/interface.h" #include "zebra/zebra_ptm.h" #include "zebra/rtadv.h" @@ -66,6 +58,7 @@ #include "zebra/zebra_errors.h" #include "zebra/zebra_mlag.h" #include "zebra/connected.h" +#include "zebra/zebra_opaque.h" /* Encoding helpers -------------------------------------------------------- */ @@ -2870,38 +2863,78 @@ static void zserv_write_incoming(struct stream *orig, uint16_t command) } #endif -void zserv_handle_commands(struct zserv *client, struct stream *msg) +/* + * Process a batch of zapi messages. + */ +void zserv_handle_commands(struct zserv *client, struct stream_fifo *fifo) { struct zmsghdr hdr; struct zebra_vrf *zvrf; + struct stream *msg; + struct stream_fifo temp_fifo; - if (STREAM_READABLE(msg) > ZEBRA_MAX_PACKET_SIZ) { - if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) - zlog_debug( - "ZAPI message is %zu bytes long but the maximum packet size is %u; dropping", - STREAM_READABLE(msg), ZEBRA_MAX_PACKET_SIZ); - return; - } + stream_fifo_init(&temp_fifo); - zapi_parse_header(msg, &hdr); + while (stream_fifo_head(fifo)) { + msg = stream_fifo_pop(fifo); - if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) - zserv_log_message(NULL, msg, &hdr); + if (STREAM_READABLE(msg) > ZEBRA_MAX_PACKET_SIZ) { + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zlog_debug( + "ZAPI message is %zu bytes long but the maximum packet size is %u; dropping", + STREAM_READABLE(msg), + ZEBRA_MAX_PACKET_SIZ); + goto continue_loop; + } + + zapi_parse_header(msg, &hdr); + + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zserv_log_message(NULL, msg, &hdr); #if defined(HANDLE_ZAPI_FUZZING) - zserv_write_incoming(msg, hdr.command); + zserv_write_incoming(msg, hdr.command); #endif - hdr.length -= ZEBRA_HEADER_SIZE; + hdr.length -= ZEBRA_HEADER_SIZE; - /* lookup vrf */ - zvrf = zebra_vrf_lookup_by_id(hdr.vrf_id); - if (!zvrf) - return zserv_error_no_vrf(client, &hdr, msg, zvrf); + /* Before checking for a handler function, check for + * special messages that are handled in another module; + * we'll treat these as opaque. + */ + if (zebra_opaque_handles_msgid(hdr.command)) { + /* Reset message buffer */ + stream_set_getp(msg, 0); + + stream_fifo_push(&temp_fifo, msg); + + /* Continue without freeing the message */ + msg = NULL; + goto continue_loop; + } + + /* lookup vrf */ + zvrf = zebra_vrf_lookup_by_id(hdr.vrf_id); + if (!zvrf) { + zserv_error_no_vrf(client, &hdr, msg, zvrf); + goto continue_loop; + } + + if (hdr.command >= array_size(zserv_handlers) + || zserv_handlers[hdr.command] == NULL) { + zserv_error_invalid_msg_type(client, &hdr, msg, zvrf); + goto continue_loop; + } + + zserv_handlers[hdr.command](client, &hdr, msg, zvrf); + +continue_loop: + stream_free(msg); + } - if (hdr.command >= array_size(zserv_handlers) - || zserv_handlers[hdr.command] == NULL) - return zserv_error_invalid_msg_type(client, &hdr, msg, zvrf); + /* Dispatch any special messages from the temp fifo */ + if (stream_fifo_head(&temp_fifo) != NULL) + zebra_opaque_enqueue_batch(&temp_fifo); - zserv_handlers[hdr.command](client, &hdr, msg, zvrf); + stream_fifo_deinit(&temp_fifo); } |
