From: Quentin Young Date: Sun, 1 Mar 2020 00:55:35 +0000 (-0500) Subject: lib: add zapi clientside fuzz entrypoint X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=6f26d5afac85c7987d83aaa48e34f562efd0d1b1;p=mirror%2Ffrr.git lib: add zapi clientside fuzz entrypoint This can be used by daemon-specific fuzzing targets to feed inputs to their zclient Signed-off-by: Quentin Young --- diff --git a/lib/zclient.c b/lib/zclient.c index 24546f3c45..25e26ceba6 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -3866,6 +3866,299 @@ static zclient_handler *const lib_handlers[] = { [ZEBRA_INTERFACE_BFD_DEST_UPDATE] = zclient_bfd_session_update, }; +#ifdef FUZZING +int zclient_read_fuzz(struct zclient *zclient, const uint8_t *data, size_t len) +{ + uint16_t length, command; + uint8_t marker, version; + vrf_id_t vrf_id; + + /* Length check. */ + if (len > STREAM_SIZE(zclient->ibuf)) { + struct stream *ns; + flog_err( + EC_LIB_ZAPI_ENCODE, + "%s: message size %zu exceeds buffer size %lu, expanding...", + __func__, len, + (unsigned long)STREAM_SIZE(zclient->ibuf)); + ns = stream_new(len); + stream_free(zclient->ibuf); + zclient->ibuf = ns; + } + + if (len < ZEBRA_HEADER_SIZE) { + flog_err(EC_LIB_ZAPI_MISSMATCH, + "%s: socket %d message length %zu is less than %d ", + __func__, zclient->sock, len, ZEBRA_HEADER_SIZE); + return -1; + } + + stream_reset(zclient->ibuf); + stream_put(zclient->ibuf, data, len); + + length = stream_getw(zclient->ibuf); + marker = stream_getc(zclient->ibuf); + version = stream_getc(zclient->ibuf); + vrf_id = stream_getl(zclient->ibuf); + command = stream_getw(zclient->ibuf); + + if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { + flog_err( + EC_LIB_ZAPI_MISSMATCH, + "%s: socket %d version mismatch, marker %d, version %d", + __func__, zclient->sock, marker, version); + return -1; + } + + length -= ZEBRA_HEADER_SIZE; + + zlog_debug("zclient 0x%p command %s VRF %u", (void *)zclient, + zserv_command_string(command), vrf_id); + + switch (command) { + case ZEBRA_CAPABILITIES: + zclient_capability_decode(command, zclient, length, vrf_id); + break; + case ZEBRA_ROUTER_ID_UPDATE: + if (zclient->router_id_update) + (*zclient->router_id_update)(command, zclient, length, + vrf_id); + break; + case ZEBRA_VRF_ADD: + zclient_vrf_add(zclient, vrf_id); + break; + case ZEBRA_VRF_DELETE: + zclient_vrf_delete(zclient, vrf_id); + break; + case ZEBRA_INTERFACE_ADD: + zclient_interface_add(zclient, vrf_id); + break; + case ZEBRA_INTERFACE_DELETE: + zclient_interface_delete(zclient, vrf_id); + break; + case ZEBRA_INTERFACE_ADDRESS_ADD: + if (zclient->interface_address_add) + (*zclient->interface_address_add)(command, zclient, + length, vrf_id); + break; + case ZEBRA_INTERFACE_ADDRESS_DELETE: + if (zclient->interface_address_delete) + (*zclient->interface_address_delete)(command, zclient, + length, vrf_id); + break; + case ZEBRA_INTERFACE_BFD_DEST_UPDATE: + if (zclient->interface_bfd_dest_update) + (*zclient->interface_bfd_dest_update)(command, zclient, + length, vrf_id); + break; + case ZEBRA_INTERFACE_NBR_ADDRESS_ADD: + if (zclient->interface_nbr_address_add) + (*zclient->interface_nbr_address_add)(command, zclient, + length, vrf_id); + break; + case ZEBRA_INTERFACE_NBR_ADDRESS_DELETE: + if (zclient->interface_nbr_address_delete) + (*zclient->interface_nbr_address_delete)( + command, zclient, length, vrf_id); + break; + case ZEBRA_INTERFACE_UP: + zclient_interface_up(zclient, vrf_id); + break; + case ZEBRA_INTERFACE_DOWN: + zclient_interface_down(zclient, vrf_id); + break; + case ZEBRA_INTERFACE_VRF_UPDATE: + if (zclient->interface_vrf_update) + (*zclient->interface_vrf_update)(command, zclient, + length, vrf_id); + break; + case ZEBRA_NEXTHOP_UPDATE: + if (zclient_debug) + zlog_debug("zclient rcvd nexthop update"); + if (zclient->nexthop_update) + (*zclient->nexthop_update)(command, zclient, length, + vrf_id); + break; + case ZEBRA_IMPORT_CHECK_UPDATE: + if (zclient_debug) + zlog_debug("zclient rcvd import check update"); + if (zclient->import_check_update) + (*zclient->import_check_update)(command, zclient, + length, vrf_id); + break; + case ZEBRA_BFD_DEST_REPLAY: + if (zclient->bfd_dest_replay) + (*zclient->bfd_dest_replay)(command, zclient, length, + vrf_id); + break; + case ZEBRA_REDISTRIBUTE_ROUTE_ADD: + if (zclient->redistribute_route_add) + (*zclient->redistribute_route_add)(command, zclient, + length, vrf_id); + break; + case ZEBRA_REDISTRIBUTE_ROUTE_DEL: + if (zclient->redistribute_route_del) + (*zclient->redistribute_route_del)(command, zclient, + length, vrf_id); + break; + case ZEBRA_INTERFACE_LINK_PARAMS: + if (zclient->interface_link_params) + (*zclient->interface_link_params)(command, zclient, + length, vrf_id); + break; + case ZEBRA_FEC_UPDATE: + if (zclient_debug) + zlog_debug("zclient rcvd fec update"); + if (zclient->fec_update) + (*zclient->fec_update)(command, zclient, length); + break; + case ZEBRA_LOCAL_ES_ADD: + if (zclient->local_es_add) + (*zclient->local_es_add)(command, zclient, length, + vrf_id); + break; + case ZEBRA_LOCAL_ES_DEL: + if (zclient->local_es_del) + (*zclient->local_es_del)(command, zclient, length, + vrf_id); + break; + case ZEBRA_VNI_ADD: + if (zclient->local_vni_add) + (*zclient->local_vni_add)(command, zclient, length, + vrf_id); + break; + case ZEBRA_VNI_DEL: + if (zclient->local_vni_del) + (*zclient->local_vni_del)(command, zclient, length, + vrf_id); + break; + case ZEBRA_L3VNI_ADD: + if (zclient->local_l3vni_add) + (*zclient->local_l3vni_add)(command, zclient, length, + vrf_id); + break; + case ZEBRA_L3VNI_DEL: + if (zclient->local_l3vni_del) + (*zclient->local_l3vni_del)(command, zclient, length, + vrf_id); + break; + case ZEBRA_MACIP_ADD: + if (zclient->local_macip_add) + (*zclient->local_macip_add)(command, zclient, length, + vrf_id); + break; + case ZEBRA_MACIP_DEL: + if (zclient->local_macip_del) + (*zclient->local_macip_del)(command, zclient, length, + vrf_id); + break; + case ZEBRA_IP_PREFIX_ROUTE_ADD: + if (zclient->local_ip_prefix_add) + (*zclient->local_ip_prefix_add)(command, zclient, + length, vrf_id); + break; + case ZEBRA_IP_PREFIX_ROUTE_DEL: + if (zclient->local_ip_prefix_del) + (*zclient->local_ip_prefix_del)(command, zclient, + length, vrf_id); + break; + case ZEBRA_PW_STATUS_UPDATE: + if (zclient->pw_status_update) + (*zclient->pw_status_update)(command, zclient, length, + vrf_id); + break; + case ZEBRA_ROUTE_NOTIFY_OWNER: + if (zclient->route_notify_owner) + (*zclient->route_notify_owner)(command, zclient, length, + vrf_id); + break; + case ZEBRA_RULE_NOTIFY_OWNER: + if (zclient->rule_notify_owner) + (*zclient->rule_notify_owner)(command, zclient, length, + vrf_id); + break; + case ZEBRA_GET_LABEL_CHUNK: + if (zclient->label_chunk) + (*zclient->label_chunk)(command, zclient, length, + vrf_id); + break; + case ZEBRA_IPSET_NOTIFY_OWNER: + if (zclient->ipset_notify_owner) + (*zclient->ipset_notify_owner)(command, zclient, length, + vrf_id); + break; + case ZEBRA_IPSET_ENTRY_NOTIFY_OWNER: + if (zclient->ipset_entry_notify_owner) + (*zclient->ipset_entry_notify_owner)(command, + zclient, length, + vrf_id); + break; + case ZEBRA_IPTABLE_NOTIFY_OWNER: + if (zclient->iptable_notify_owner) + (*zclient->iptable_notify_owner)(command, + zclient, length, + vrf_id); + break; + case ZEBRA_VXLAN_SG_ADD: + if (zclient->vxlan_sg_add) + (*zclient->vxlan_sg_add)(command, zclient, length, + vrf_id); + break; + case ZEBRA_VXLAN_SG_DEL: + if (zclient->vxlan_sg_del) + (*zclient->vxlan_sg_del)(command, zclient, length, + vrf_id); + break; + case ZEBRA_MLAG_PROCESS_UP: + zclient_mlag_process_up(command, zclient, length, vrf_id); + break; + case ZEBRA_MLAG_PROCESS_DOWN: + zclient_mlag_process_down(command, zclient, length, vrf_id); + break; + case ZEBRA_MLAG_FORWARD_MSG: + zclient_mlag_handle_msg(command, zclient, length, vrf_id); + break; + case ZEBRA_ERROR: + zclient_handle_error(command, zclient, length, vrf_id); + break; + case ZEBRA_OPAQUE_MESSAGE: + if (zclient->opaque_msg_handler) + (*zclient->opaque_msg_handler)(command, zclient, length, + vrf_id); + break; + case ZEBRA_OPAQUE_REGISTER: + if (zclient->opaque_register_handler) + (*zclient->opaque_register_handler)(command, zclient, + length, vrf_id); + break; + case ZEBRA_OPAQUE_UNREGISTER: + if (zclient->opaque_unregister_handler) + (*zclient->opaque_unregister_handler)(command, zclient, + length, vrf_id); + break; + case ZEBRA_SR_POLICY_NOTIFY_STATUS: + if (zclient->sr_policy_notify_status) + (*zclient->sr_policy_notify_status)(command, zclient, + length, vrf_id); + break; + case ZEBRA_CLIENT_CLOSE_NOTIFY: + if (zclient->zebra_client_close_notify) + (*zclient->zebra_client_close_notify)(command, zclient, + length, vrf_id); + default: + break; + } + + if (zclient->sock < 0) + /* Connection was closed during packet processing. */ + return -1; + + stream_reset(zclient->ibuf); + + return 0; +} +#endif + /* Zebra client message read function. */ static int zclient_read(struct thread *thread) { diff --git a/lib/zclient.h b/lib/zclient.h index 82eaefda42..ed6cbe1c27 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -23,6 +23,7 @@ struct zclient; +#define FUZZING 1 /* For struct zapi_route. */ #include "prefix.h" #include "ipaddr.h" @@ -1236,6 +1237,10 @@ struct zapi_client_close_info { uint32_t session_id; }; +#ifdef FUZZING +int zclient_read_fuzz(struct zclient *zclient, const uint8_t *data, size_t len); +#endif + /* Decode incoming client close notify */ extern int zapi_client_close_notify_decode(struct stream *s, struct zapi_client_close_info *info);