/// =-=-=-=-=-=-=-
/// @brief function which sends the negotiation message
    error send_client_server_negotiation_message(
        irods::network_object_ptr _ptr,
        cs_neg_t&                  _cs_neg_msg ) {
        // =-=-=-=-=-=-=-
        // pack the negotiation message
        bytesBuf_t* cs_neg_buf = 0;
        int status = packStruct( &_cs_neg_msg,
                                 &cs_neg_buf,
                                 "CS_NEG_PI",
                                 RodsPackTable,
                                 0, XML_PROT );
        if ( status < 0 ) {
            return ERROR( status, "failed to pack client-server message" );
        }

        // =-=-=-=-=-=-=-
        // pack the negotiation message
        irods::error ret = sendRodsMsg( _ptr,
                                        RODS_CS_NEG_T,
                                        cs_neg_buf,
                                        0, 0, 0,
                                        XML_PROT );
        freeBBuf( cs_neg_buf );
        if ( !ret.ok() ) {
            return PASSMSG( "failed to send client-server negotiation message", ret );

        }

        return SUCCESS();

    } // send_client_server_negotiation_message
Example #2
0
// =-=-=-=-=-=-=-
//
irods::error writeMsgHeader(
    irods::network_object_ptr _ptr,
    msgHeader_t*               _header ) {
    // =-=-=-=-=-=-=-
    // always use XML_PROT for the Header
    bytesBuf_t* header_buf = 0;
    int status = packStruct(
                     static_cast<void *>( _header ),
                     &header_buf,
                     "MsgHeader_PI",
                     RodsPackTable,
                     0, XML_PROT );
    if ( status < 0 ||
            0 == header_buf ) {
        return ERROR( status, "packstruct error" );
    }

    // =-=-=-=-=-=-=-
    // resolve a network interface plugin from the
    // network object
    irods::plugin_ptr p_ptr;
    irods::error ret = _ptr->resolve( irods::NETWORK_INTERFACE, p_ptr );
    if ( !ret.ok() ) {
        freeBBuf( header_buf );
        return PASSMSG( "failed to resolve network interface", ret );
    }

    // =-=-=-=-=-=-=-
    // make the call to the plugin interface
    irods::first_class_object_ptr ptr = boost::dynamic_pointer_cast< irods::first_class_object >( _ptr );
    irods::network_ptr            net = boost::dynamic_pointer_cast< irods::network >( p_ptr );
    ret = net->call< bytesBuf_t* >(
              irods::NETWORK_OP_WRITE_HEADER,
              ptr,
              header_buf );

    freeBBuf( header_buf );

    if ( !ret.ok() ) {
        return PASS( ret );
    }

    return SUCCESS();

} // writeMsgHeader
Example #3
0
irods::error sendVersion(
    irods::network_object_ptr _ptr,
    int                 versionStatus,
    int                 reconnPort,
    char*               reconnAddr,
    int                 cookie ) {
    version_t myVersion;
    int status;
    bytesBuf_t *versionBBuf = NULL;


    /* setup the version struct */

    memset( &myVersion, 0, sizeof( myVersion ) );
    myVersion.status = versionStatus;
    rstrcpy( myVersion.relVersion, RODS_REL_VERSION,  NAME_LEN );
    rstrcpy( myVersion.apiVersion, RODS_API_VERSION,  NAME_LEN );
    if ( reconnAddr != NULL ) {
        myVersion.reconnPort = reconnPort;
        rstrcpy( myVersion.reconnAddr, reconnAddr, LONG_NAME_LEN );
        myVersion.cookie = cookie;
    }
    else {
        // =-=-=-=-=-=-=-
        // super secret jargon irods detection
        // sshhhhhhh...
        myVersion.cookie = 400;

    }

    /* alway use XML for version */
    status = packStruct( ( char * ) &myVersion, &versionBBuf,
                         "Version_PI", RodsPackTable, 0, XML_PROT );
    if ( status < 0 ) {
        return ERROR( status, "packStruct error" );
    }

    irods::error ret = sendRodsMsg(
                           _ptr,
                           RODS_VERSION_T,
                           versionBBuf,
                           NULL, NULL, 0,
                           XML_PROT );
    freeBBuf( versionBBuf );
    if ( !ret.ok() ) {
        return PASS( ret );
    }

    return SUCCESS();

} // sendVersion
Example #4
0
// =-=-=-=-=-=-=-
// interface for requesting a reconnection
irods::error sendReconnMsg(
    irods::network_object_ptr _ptr,
    reconnMsg_t*        _msg ) {
    // =-=-=-=-=-=-=-
    // trap invalid param
    if ( _msg == NULL ) {
        return ERROR( USER__NULL_INPUT_ERR, "null msg buf" );
    }

    // =-=-=-=-=-=-=-
    // pack outgoing message - alway use XML for version
    bytesBuf_t* recon_buf = NULL;
    int status = packStruct(
                     static_cast<void*>( _msg ),
                     &recon_buf,
                     "ReconnMsg_PI",
                     RodsPackTable,
                     0, XML_PROT );
    if ( status < 0 ) {
        return ERROR( status, "failed to pack struct" );
    }

    // =-=-=-=-=-=-=-
    // pack outgoing message - alway use XML for version
    irods::error ret = sendRodsMsg(
                           _ptr,
                           RODS_RECONNECT_T,
                           recon_buf,
                           NULL,
                           NULL,
                           0,
                           XML_PROT );
    freeBBuf( recon_buf );
    if ( !ret.ok() ) {
        rodsLogError( LOG_ERROR, status,
                      "sendReconnMsg: sendRodsMsg of reconnect msg failed, status = %d",
                      status );
    }

    return CODE( status );

} // sendReconnMsg
Example #5
0
int
sendApiReply( rsComm_t * rsComm, int apiInx, int retVal,
              void * myOutStruct, bytesBuf_t * myOutBsBBuf ) {
    int status = 0;
    bytesBuf_t *outStructBBuf = NULL;
    bytesBuf_t *myOutStructBBuf;
    bytesBuf_t *rErrorBBuf = NULL;
    bytesBuf_t *myRErrorBBuf;

//#ifndef windows_platform
    svrChkReconnAtSendStart( rsComm );
//#endif

    if ( retVal == SYS_HANDLER_DONE_NO_ERROR ) {
        /* not actually an error */
        retVal = 0;
    }

    // =-=-=-=-=-=-=-
    // create a network object
    irods::network_object_ptr net_obj;
    irods::error ret = irods::network_factory( rsComm, net_obj );
    if ( !ret.ok() ) {
        irods::log( PASS( ret ) );
        return ret.code();

    }


    irods::api_entry_table& RsApiTable = irods::get_server_api_table();
    if ( RsApiTable[apiInx]->outPackInstruct != NULL && myOutStruct != NULL ) {

        status = packStruct( ( char * ) myOutStruct, &outStructBBuf,
                             ( char* )RsApiTable[apiInx]->outPackInstruct, RodsPackTable, FREE_POINTER,
                             rsComm->irodsProt );

        if ( status < 0 ) {
            rodsLog( LOG_NOTICE,
                     "sendApiReply: packStruct error, status = %d", status );
            sendRodsMsg( net_obj, RODS_API_REPLY_T, NULL,
                         NULL, NULL, status, rsComm->irodsProt );
            svrChkReconnAtSendEnd( rsComm );
            return status;
        }

        myOutStructBBuf = outStructBBuf;
    }
    else {
        myOutStructBBuf = NULL;
    }

    if ( RsApiTable[apiInx]->outBsFlag == 0 ) {
        myOutBsBBuf = NULL;
    }

    if ( rsComm->rError.len > 0 ) {
        status = packStruct( ( char * ) &rsComm->rError, &rErrorBBuf,
                             "RError_PI", RodsPackTable, 0, rsComm->irodsProt );

        if ( status < 0 ) {
            rodsLog( LOG_NOTICE,
                     "sendApiReply: packStruct error, status = %d", status );
            sendRodsMsg( net_obj, RODS_API_REPLY_T, NULL,
                         NULL, NULL, status, rsComm->irodsProt );
            svrChkReconnAtSendEnd( rsComm );
            freeBBuf( outStructBBuf );
            freeBBuf( rErrorBBuf );
            return status;
        }

        myRErrorBBuf = rErrorBBuf;
    }
    else {
        myRErrorBBuf = NULL;
    }
    ret = sendRodsMsg( net_obj, RODS_API_REPLY_T, myOutStructBBuf,
                       myOutBsBBuf, myRErrorBBuf, retVal, rsComm->irodsProt );
    if ( !ret.ok() ) {
        int status1;
        irods::log( PASS( ret ) );

        if ( rsComm->reconnSock > 0 ) {
            int savedStatus = ret.code();
            boost::unique_lock< boost::mutex > boost_lock( *rsComm->thread_ctx->lock );
            rodsLog( LOG_DEBUG,
                     "sendApiReply: svrSwitchConnect. cliState = %d,agState=%d",
                     rsComm->clientState, rsComm->agentState );
            status1 = svrSwitchConnect( rsComm );
            boost_lock.unlock();
            if ( status1 > 0 ) {
                /* should not be here */
                rodsLog( LOG_NOTICE,
                         "sendApiReply: Switch connection and retry sendRodsMsg" );
                ret = sendRodsMsg( net_obj, RODS_API_REPLY_T,
                                   myOutStructBBuf, myOutBsBBuf, myRErrorBBuf,
                                   retVal, rsComm->irodsProt );

                if ( ret.code() >= 0 ) {
                    rodsLog( LOG_NOTICE,
                             "sendApiReply: retry sendRodsMsg succeeded" );
                }
                else {
                    status = savedStatus;
                }
            }
        }
    }

    svrChkReconnAtSendEnd( rsComm );

    freeBBuf( outStructBBuf );
    freeBBuf( rErrorBBuf );

    return status;
}
Example #6
0
int
sendStartupPack( rcComm_t *conn, int connectCnt, int reconnFlag ) {
    startupPack_t startupPack;
    int status;
    char *tmpStr;
    bytesBuf_t *startupPackBBuf = NULL;


    /* setup the startup pack */

    startupPack.irodsProt  = conn->irodsProt;
    startupPack.connectCnt = connectCnt;
    startupPack.reconnFlag = reconnFlag;

    rstrcpy( startupPack.proxyUser,      conn->proxyUser.userName,  NAME_LEN );
    rstrcpy( startupPack.proxyRodsZone,  conn->proxyUser.rodsZone,  NAME_LEN );
    rstrcpy( startupPack.clientUser,     conn->clientUser.userName, NAME_LEN );
    rstrcpy( startupPack.clientRodsZone, conn->clientUser.rodsZone, NAME_LEN );

    rstrcpy( startupPack.relVersion, RODS_REL_VERSION,  NAME_LEN );
    rstrcpy( startupPack.apiVersion, RODS_API_VERSION,  NAME_LEN );

    if ( ( tmpStr = getenv( SP_OPTION ) ) != NULL ) {
        rstrcpy( startupPack.option, tmpStr, NAME_LEN );
    }
    else {
        startupPack.option[0] = '\0';
    }

    // =-=-=-=-=-=-=-
    // if the advanced negotiation is requested from the irodsEnv,
    // tack those results onto the startup pack option string
    rodsEnv rods_env;
    status = getRodsEnv( &rods_env );

    if ( status >= 0 && strlen( rods_env.rodsClientServerNegotiation ) > 0 ) {
        strncat( startupPack.option,
                 rods_env.rodsClientServerNegotiation,
                 strlen( rods_env.rodsClientServerNegotiation ) );
    }

    /* always use XML_PROT for the startupPack */
    status = packStruct( ( void * ) &startupPack, &startupPackBBuf,
                         "StartupPack_PI", RodsPackTable, 0, XML_PROT );
    if ( status < 0 ) {
        rodsLogError( LOG_NOTICE, status,
                      "sendStartupPack: packStruct error, status = %d", status );
        return status;
    }

    irods::network_object_ptr net_obj;
    irods::error ret = irods::network_factory( conn, net_obj );
    if ( !ret.ok() ) {
        irods::log( PASS( ret ) );
        freeBBuf( startupPackBBuf );
        return ret.code();
    }

    ret = sendRodsMsg(
              net_obj,
              RODS_CONNECT_T,
              startupPackBBuf,
              NULL, NULL, 0,
              XML_PROT );
    freeBBuf( startupPackBBuf );
    if ( !ret.ok() ) {
        irods::log( PASS( ret ) );
        return ret.code();
    }

    return ret.code();

} // sendStartupPack
Example #7
0
/**
 * \fn msiPrintGenQueryOutToBuffer(msParam_t *queryOut, msParam_t *format, msParam_t *buffer, ruleExecInfo_t *rei)
 *
 * \brief  Writes the contents of a GenQueryOut_MS_T into a BUF_LEN_MS_T.
 *
 * \module core
 *
 * \author  Antoine de Torcy
 * \date    2009-12-16
 *
 * \note This microservice writes the contents of a GenQueryOut_MS_T into a BUF_LEN_MS_T.
 *       The results can be formatted with an optional C-style format string the same way it is done in iquest.
 *
 * \usage See clients/icommands/test/rules3.0/
 *
 * \param[in] queryOut - Required - A GenQueryOut_MS_T.
 * \param[in] format - Optional - A STR_MS_T with a C-style format string, like in iquest.
 * \param[out] buffer - A BUF_LEN_MS_T
 * \param[in,out] rei - The RuleExecInfo structure that is automatically
 *    handled by the rule engine. The user does not include rei as a
 *    parameter in the rule invocation.
 *
 * \DolVarDependence none
 * \DolVarModified none
 * \iCatAttrDependence none
 * \iCatAttrModified none
 * \sideeffect none
 *
 * \return integer
 * \retval 0 on success
 * \pre none
 * \post none
 * \sa none
**/
int
msiPrintGenQueryOutToBuffer( msParam_t *queryOut, msParam_t *format, msParam_t *buffer, ruleExecInfo_t *rei ) {
    genQueryOut_t *genQueryOut;
    char *format_str;
    bytesBuf_t *bytesBuf;
    FILE *stream;
    char readbuffer[MAX_NAME_LEN];

    /*************************************  INIT **********************************/

    /* For testing mode when used with irule --test */
    RE_TEST_MACRO( "    Calling msiPrintGenQueryOutToBuffer" )

    /* Sanity checks */
    if ( rei == NULL || rei->rsComm == NULL ) {
        rodsLog( LOG_ERROR, "msiPrintGenQueryOutToBuffer: input rei or rsComm is NULL." );
        return ( SYS_INTERNAL_NULL_INPUT_ERR );
    }


    /********************************** PARAM PARSING  *********************************/

    /* Check for proper param type */
    if ( !queryOut || !queryOut->inOutStruct || !queryOut->type || strcmp( queryOut->type, GenQueryOut_MS_T ) ) {
        rodsLog( LOG_ERROR, "msiPrintGenQueryOutToBuffer: Invalid input for queryOut." );
        return( USER_PARAM_TYPE_ERR );
    }
    genQueryOut = ( genQueryOut_t * )queryOut->inOutStruct;


    /* Parse format */
    format_str = parseMspForStr( format );


    /********************************** EXTRACT SQL RESULTS  *********************************/

    /* Let's use printGenQueryOut() here for the sake of consistency over efficiency (somewhat). It needs a stream. */
    stream = tmpfile();
    if ( !stream ) { /* Since it won't be caught by printGenQueryOut */
        rodsLog( LOG_ERROR, "msiPrintGenQueryOutToBuffer: tmpfile() failed." );
        return( FILE_OPEN_ERR ); /* accurate enough */
    }

    /* Write results to temp file */
    rei->status = printGenQueryOut( stream, format_str, NULL, genQueryOut );
    if ( rei->status < 0 ) {
        rodsLog( LOG_ERROR, "msiPrintGenQueryOutToBuffer: printGenQueryOut() failed, status = %d", rei->status );
        return( rei->status );
    }

    /* bytesBuf init */
    bytesBuf = ( bytesBuf_t * )malloc( sizeof( bytesBuf_t ) );
    memset( bytesBuf, 0, sizeof( bytesBuf_t ) );

    /* Read from temp file and write to bytesBuf */
    rewind( stream );
    while ( fgets( readbuffer, MAX_NAME_LEN, stream ) != NULL ) {
        appendToByteBuf( bytesBuf, readbuffer );
    }


    /********************************* RETURN AND DONE **********************************/

    /* Free memory previously allocated for previous result batches (when used in loop). */
    if ( buffer && buffer->inpOutBuf ) {
        freeBBuf( buffer->inpOutBuf );
    }
    resetMsParam( buffer );

    /* Fill bytesBuf in our buffer output */
    fillBufLenInMsParam( buffer, bytesBuf->len, bytesBuf );

    return 0;

}
Example #8
0
int _rsClientHints(
    rsComm_t*    _comm,
    bytesBuf_t** _bbuf ) {

    if ( !_comm || !_bbuf ) {
        rodsLog(
            LOG_ERROR,
            "_rsServerReport: null comm or bbuf" );
        return SYS_INVALID_INPUT_PARAM;
    }

    ( *_bbuf ) = ( bytesBuf_t* ) malloc( sizeof( bytesBuf_t ) );
    if ( !( *_bbuf ) ) {
        rodsLog(
            LOG_ERROR,
            "_rsClientHints: failed to allocate _bbuf" );
        return SYS_MALLOC_ERR;

    }

    bytesBuf_t* ies_buf = 0;
    int status = rsIESClientHints(
                     _comm,
                     &ies_buf );
    if( status < 0 ) {
        rodsLog(
            LOG_ERROR,
            "_rsClientHints: rsIESClientHints failed %d",
            status );
        return status;
    }

    json_error_t j_err;
    json_t* client_hints = json_loads(
                               ( char* )ies_buf->buf,
                               ies_buf->len, &j_err );
    freeBBuf( ies_buf );
    if ( !client_hints ) {
        rodsLog(
            LOG_ERROR,
            "_rsClientHints - json_loads failed [%s]",
            j_err.text );
        return ACTION_FAILED_ERR;
    }

    std::string hash, hash_policy;
    irods::error ret = get_hash_and_policy( _comm, hash, hash_policy );
    if ( !ret.ok() ) {
        irods::log( PASS( ret ) );
    }

    json_object_set(
        client_hints,
        "hash_scheme",
        json_string( hash.c_str() ) );
    json_object_set(
        client_hints,
        "match_hash_policy",
        json_string( hash_policy.c_str() ) );


    char* tmp_buf = json_dumps(
                        client_hints,
                        JSON_INDENT( 4 ) );

    // *SHOULD* free All The Things...
    json_decref( client_hints );

    ( *_bbuf )->buf = tmp_buf;
    ( *_bbuf )->len = strlen( tmp_buf );

    return 0;

} // _rsClientHints
int
sendApiRequest( rcComm_t *conn, int apiInx, void *inputStruct,
                bytesBuf_t *inputBsBBuf ) {
    int status = 0;
    bytesBuf_t *inputStructBBuf = NULL;
    bytesBuf_t *myInputStructBBuf = NULL;

    cliChkReconnAtSendStart( conn );

    irods::api_entry_table& RcApiTable = irods::get_client_api_table();

    irods::api_entry_table::iterator itr = RcApiTable.find( apiInx );
    if ( itr == RcApiTable.end() ) {
        rodsLogError( LOG_ERROR, SYS_UNMATCHED_API_NUM, "API Entry not found at index %d", apiInx );
        return SYS_UNMATCHED_API_NUM;
    }


    if ( RcApiTable[apiInx]->inPackInstruct != NULL ) {
        if ( inputStruct == NULL ) {
            cliChkReconnAtSendEnd( conn );
            return ( USER_API_INPUT_ERR );
        }
        status = packStruct( ( void * ) inputStruct, &inputStructBBuf,
                             ( char* )RcApiTable[apiInx]->inPackInstruct, RodsPackTable, 0, conn->irodsProt );
        if ( status < 0 ) {
            rodsLogError( LOG_ERROR, status,
                          "sendApiRequest: packStruct error, status = %d", status );
            cliChkReconnAtSendEnd( conn );
            return status;
        }

        myInputStructBBuf = inputStructBBuf;
    }
    else {
        myInputStructBBuf = NULL;
    };


    if ( RcApiTable[apiInx]->inBsFlag <= 0 ) {
        inputBsBBuf = NULL;
    }

    irods::network_object_ptr net_obj;
    irods::error ret = irods::network_factory( conn, net_obj );
    if ( !ret.ok() ) {
        irods::log( PASS( ret ) );
        return ret.code();
    }

    ret = sendRodsMsg(
              net_obj,
              RODS_API_REQ_T,
              myInputStructBBuf,
              inputBsBBuf,
              NULL,
              RcApiTable[apiInx]->apiNumber,
              conn->irodsProt );
    if ( !ret.ok() ) {
        irods::log( PASS( ret ) );
        if ( conn->svrVersion != NULL &&
                conn->svrVersion->reconnPort > 0 ) {
            int status1;
            int savedStatus = ret.code() ;
            conn->thread_ctx->lock->lock();
            status1 = cliSwitchConnect( conn );
            rodsLog( LOG_DEBUG,
                     "sendApiRequest: svrSwitchConnect. cliState = %d,agState=%d",
                     conn->clientState, conn->agentState );
            conn->thread_ctx->lock->unlock();
            if ( status1 > 0 ) {
                /* should not be here */
                rodsLog( LOG_NOTICE,
                         "sendApiRequest: Switch connection and retry sendRodsMsg" );
                ret = sendRodsMsg(
                          net_obj,
                          RODS_API_REQ_T,
                          myInputStructBBuf,
                          inputBsBBuf,
                          NULL,
                          RcApiTable[apiInx]->apiNumber,
                          conn->irodsProt );
                if ( !ret.ok() ) {
                    irods::log( PASS( ret ) );
                }
                else {
                    status = savedStatus;
                }

            } // if status1 > 0

        } // if svrVersion != NULL ...

    }
    else {
        // =-=-=-=-=-=-=-
        // be sure to pass along the return code from the
        // plugin call
        status = ret.code();

    }

    freeBBuf( inputStructBBuf );

    return ( status );
}
Example #10
0
static
irods::error get_server_reports(rsComm_t* _comm, json& _resc_arr)
{
    _resc_arr = json::array();

    std::map< rodsServerHost_t*, int > svr_reported;
    rodsServerHost_t* icat_host = 0;
    char* zone_name = getLocalZoneName();
    int status = getRcatHost( MASTER_RCAT, zone_name, &icat_host );
    if ( status < 0 ) {
        return ERROR(status, "getRcatHost failed");
    }

    for (irods::resource_manager::iterator itr = resc_mgr.begin();
         itr != resc_mgr.end();
         ++itr)
    {
        irods::resource_ptr resc = itr->second;

        rodsServerHost_t* tmp_host = 0;
        irods::error ret = resc->get_property< rodsServerHost_t* >( irods::RESOURCE_HOST, tmp_host );
        if ( !ret.ok() ) {
            irods::log( PASS( ret ) );
            continue;
        }

        // skip the icat server as that is done separately
        // also skip null tmp_hosts resources ( coordinating )
        // skip local host
        if ( !tmp_host || tmp_host == icat_host || LOCAL_HOST == tmp_host->localFlag ) {
            continue;
        }

        // skip previously reported servers
        std::map< rodsServerHost_t*, int >::iterator svr_itr =
            svr_reported.find( tmp_host );
        if ( svr_itr != svr_reported.end() ) {
            continue;
        }

        std::string resc_name;
        ret = resc->get_property< std::string >( irods::RESOURCE_NAME, resc_name );
        if ( !ret.ok() ) {
            irods::log( PASS( ret ) );
            continue;
        }

        svr_reported[ tmp_host ] = 1;

        int status = svrToSvrConnect( _comm, tmp_host );
        if ( status < 0 ) {
            report_server_connect_error(
                status,
                tmp_host->hostName->name,
                resc_name,
                _resc_arr);
            continue;
        }

        bytesBuf_t* bbuf = NULL;
        status = rcServerReport( tmp_host->conn, &bbuf );
        if ( status < 0 ) {
            freeBBuf( bbuf );
            bbuf = NULL;
            rodsLog(
                LOG_ERROR,
                "rcServerReport failed for [%s], status = %d",
                tmp_host->hostName->name,
                status );
        }

        // possible null termination issues
        std::string tmp_str = bbuf ? std::string((char*) bbuf->buf, bbuf->len) : std::string();

        try {
            _resc_arr.push_back(json::parse(tmp_str));
            freeBBuf(bbuf);
        }
        catch (const json::type_error& e) {
            std::string msg = "json_loads failed [";
            msg += e.what();
            msg += "]";
            irods::log(ERROR(ACTION_FAILED_ERR, msg));
        }
    } // for itr

    return SUCCESS();
} // get_server_reports
Example #11
0
int _rsZoneReport(rsComm_t* _comm, bytesBuf_t** _bbuf)
{
    bytesBuf_t* bbuf = 0;
    int status = rsServerReport(_comm, &bbuf);
    if ( status < 0 ) {
        freeBBuf(bbuf);
        rodsLog(LOG_ERROR, "_rsZoneReport - rsServerReport failed %d", status);
        return status;
    }

    json cat_svr;

    try {
        cat_svr = json::parse(std::string(static_cast<char*>(bbuf->buf), bbuf->len));
        freeBBuf(bbuf);
    }
    catch (const json::type_error& e) {
        rodsLog(LOG_ERROR, "_rsZoneReport - json::parse failed [%s]", e.what());
        return ACTION_FAILED_ERR;
    }

    json coord_resc;
    irods::error ret = get_coordinating_resources( _comm, coord_resc );
    if ( !ret.ok() ) {
        rodsLog(LOG_ERROR, "_rsZoneReport - get_server_reports failed, status = %d", ret.code());
        return ret.code();
    }

    json svr_arr;
    ret = get_server_reports( _comm, svr_arr );
    if ( !ret.ok() ) {
        rodsLog(LOG_ERROR, "_rsZoneReport - get_server_reports failed, status = %d", ret.code());
        return ret.code();
    }

    cat_svr["coordinating_resources"] = coord_resc;

    auto zone_obj = json::object();
    zone_obj["servers"] = svr_arr;
    zone_obj["icat_server"] = cat_svr;

    auto zone_arr = json::array();
    zone_arr.push_back(zone_obj);

    auto zone = json::object();
    zone["schema_version"] = (boost::format("%s/%s/zone_bundle.json")
         % irods::get_server_property<const std::string>("schema_validation_base_uri")
         % irods::get_server_property<const std::string>("schema_version")).str();

    zone["zones"] = zone_arr;

    const auto zr = zone.dump(4);
    char* tmp_buf = new char[zr.length() + 1]{};
    std::strncpy(tmp_buf, zr.c_str(), zr.length());

    *_bbuf = (bytesBuf_t*) malloc(sizeof(bytesBuf_t));
    if (!*_bbuf) {
        delete [] tmp_buf;
        rodsLog( LOG_ERROR, "_rsZoneReport: failed to allocate _bbuf" );
        return SYS_MALLOC_ERR;
    }

    (*_bbuf)->buf = tmp_buf;
    (*_bbuf)->len = zr.length();

    return 0;
} // _rsZoneReport