Tool/software: WEBENCH® Design Tools
fix the access of "zclport_registerZclHandleExternal" in zcl_port.h like this
extern bool zclport_registerZclHandleExternal(uint8_t endpoint, zclport_pFnZclHandleExternal pfn);
Then fix zcl_port.c
// multiple endpoint for ZCL handler external, added by luoyiming 2020-02-08
typedef struct
{
    void *next;
    uint8_t endpoint;
    zclport_pFnZclHandleExternal pfn;
} zclHandleExternalList_t;
// Function pointer for applications to ZCL Handle External
// added multiple endpoint processing by luoyiming at 2020-02-08
zclHandleExternalList_t *zclHandleExternalList = NULL;
/**
 * Call to register a function pointer to handle zcl_HandleExternal() messages.
 * Added multiple endpoint processing by luoyiming at 2020-02-08.
 *
 * Public function defined in zcl_port.h
 */
bool zclport_registerZclHandleExternal( uint8_t endpoint, zclport_pFnZclHandleExternal pfn )
{
    zclHandleExternalList_t *find = zclHandleExternalList;
    zclHandleExternalList_t *tail = NULL;
    // If endpoint is valid, added by luoyiming 2020-02-08
    if ( zcl_afFindEndPointDesc( endpoint ) == NULL )
    {
        return false;
    }
    // match if there be same endpoint and find tail item, fixed by luoyiming 2020-02-08
    while ( find )
    {
        if ( find->endpoint == endpoint )
        {
            find->pfn = pfn;
            return true;
        }
        if ( find->next == NULL )
        {
            tail = find;
        }
        find = find->next;
    }
    // add new item,  fixed by luoyiming 2020-02-08
    zclHandleExternalList_t *newItem = zcl_mem_alloc( sizeof(zclHandleExternalList_t) );
    if ( newItem )
    {
        newItem->next = NULL;
        newItem->endpoint = endpoint;
        newItem->pfn = pfn;
        if ( zclHandleExternalList == NULL )
        {
            zclHandleExternalList = newItem;
        }
        else
        {
            tail->next = newItem;
        }
        return true;
    }
    return false;
}
/*********************************************************************
 * @fn      zcl_HandleExternal
 *
 * @brief   Callback function to handle messages externally
 *
 * @param   pInMsg - incoming message to process
 *
 * @return  TRUE
 */
uint8_t zcl_HandleExternal(zclIncoming_t *pInMsg)
{
#ifdef BDB_REPORTING
    zclIncomingMsg_t *pCmd;
    pCmd = (zclIncomingMsg_t *)OsalPort_msgAllocate( sizeof ( zclIncomingMsg_t ) );
    if ( pCmd != NULL )
    {
      // fill in the message
      pCmd->hdr.event = ZCL_INCOMING_MSG;
      pCmd->zclHdr    = pInMsg->hdr;
      pCmd->clusterId = pInMsg->msg->clusterId;
      pCmd->srcAddr   = pInMsg->msg->srcAddr;
      pCmd->endPoint  = pInMsg->msg->endPoint;
      pCmd->attrCmd   = pInMsg->attrCmd;
      if(pCmd->zclHdr.commandID == ZCL_CMD_CONFIG_REPORT)
      {
        zstack_bdbProcessInConfigReportReq_t Req = {0};
        Req.pZclIncommingMsg = pCmd;
        Zstackapi_bdbProcessInConfigReportCmd(zclPortFindEntity(pCmd->endPoint),&Req);
        OsalPort_msgDeallocate((uint8_t*)pCmd);
        return TRUE;
      }
      if(pCmd->zclHdr.commandID == ZCL_CMD_READ_REPORT_CFG)
      {
        zstack_bdbProcessInReadReportCfgReq_t Req = {0};
        Req.pZclIncommingMsg = pCmd;
        Zstackapi_bdbProcessInReadReportCfgCmd(zclPortFindEntity(pCmd->endPoint),&Req);
        OsalPort_msgDeallocate((uint8_t*)pCmd);
        return TRUE;
      }
      OsalPort_msgDeallocate((uint8_t*)pCmd);
    }
#endif
    // zclHandleExternal for multiple endpoint, fixed by luoyiming 2020-02-08
    zclHandleExternalList_t *find = zclHandleExternalList;
    // Did the application register to handle this message
    while ( find )
    {
        if ( ( find->endpoint == pInMsg->msg->endPoint ) && ( find->pfn ) )
        {
            // Let the application handle it
            return (find->pfn( pInMsg ));
        }
        find = find->next;
    }
    return(TRUE);
}
The completely solution is in my GitHub