]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: add zapi clientside fuzz entrypoint
authorQuentin Young <qlyoung@cumulusnetworks.com>
Sun, 1 Mar 2020 00:55:35 +0000 (19:55 -0500)
committerQuentin Young <qlyoung@nvidia.com>
Mon, 15 Nov 2021 22:12:30 +0000 (17:12 -0500)
This can be used by daemon-specific fuzzing targets to feed inputs to
their zclient

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
lib/zclient.c
lib/zclient.h

index 24546f3c4583ac1d8f9773611d58bf929575c712..25e26ceba61f4d3d0f4f3ab506d2895c8a5c417e 100644 (file)
@@ -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)
 {
index 82eaefda429a215f36a3516860a2048197311c28..ed6cbe1c278c3d105788d7cdbbaec80e4219f4a5 100644 (file)
@@ -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);