/* $Copyright: * * Copyright 2004-2006 by the Massachusetts Institute of Technology. * * All rights reserved. * * Export of this software from the United States of America may require a * specific license from the United States Government. It is the * responsibility of any person or organization contemplating export to * obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and distribute * this software and its documentation for any purpose and without fee is * hereby granted, provided that the above copyright notice appear in all * copies and that both that copyright notice and this permission notice * appear in supporting documentation, and that the name of M.I.T. not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. Furthermore if you * modify this software you must label your software as modified software * and not distribute it in such a fashion that it might be confused with * the original MIT software. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Individual source code files are copyright MIT, Cygnus Support, * OpenVision, Oracle, Sun Soft, FundsXpress, and others. * * Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, * and Zephyr are trademarks of the Massachusetts Institute of Technology * (MIT). No commercial use of these trademarks may be made without prior * written permission of MIT. * * "Commercial use" means use of a name in a product or other for-profit * manner. It does NOT prevent a commercial firm from referring to the MIT * trademarks in order to convey information (although in doing so, * recognition of their trademark status should be given). * $ */ /* context.c */ #include #include #include #include #include "context.h" #include "ccache.h" #include "ccache_iterator.h" #include "cc_rpc.h" #include "msg.h" #include "msg_headers.h" #include "ccstring.h" /* cc_int_context_new * * input parameters (handle, version) are in host order */ cc_int32 cc_int_context_new( cc_context_t * pcontext, cc_handle handle, cc_uint32 version ) { cc_int_context_t context = (cc_int_context_t)malloc(sizeof(cc_int_context_d)); if (context == NULL) return ccErrNoMem; context->functions = (cc_context_f*)malloc(sizeof(cc_context_f)); if (context->functions == NULL) { free(context); return ccErrNoMem; } context->functions->release = cc_int_context_release; context->functions->get_change_time = cc_int_context_get_change_time; context->functions->get_default_ccache_name = cc_int_context_get_default_ccache_name; context->functions->open_ccache = cc_int_context_open_ccache; context->functions->open_default_ccache = cc_int_context_open_default_ccache; context->functions->create_ccache = cc_int_context_create_ccache; context->functions->create_default_ccache = cc_int_context_create_default_ccache; context->functions->create_new_ccache = cc_int_context_create_new_ccache; context->functions->new_ccache_iterator = cc_int_context_new_ccache_iterator; context->functions->lock = cc_int_context_lock; context->functions->unlock = cc_int_context_unlock; context->functions->compare = cc_int_context_compare; context->magic = CC_CONTEXT_MAGIC; context->handle = handle; context->api_version = version; *pcontext = (cc_context_t)context; return ccNoError; } cc_int32 cc_int_context_release( cc_context_t context ) { cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ctx_release_t *request_header = NULL; cc_msg_t *response = NULL; cc_uint32 type; cc_int32 code; if ( context == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ctx_release_t*)malloc(sizeof(ccmsg_ctx_release_t)); if (request_header == NULL) return ccErrNoMem; request_header->ctx = htonll(int_context->handle); code = cci_msg_new(ccmsg_CTX_RELEASE, &request); if (code != ccNoError) goto cleanup; code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_release_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { code = ccNoError; } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) request_header = NULL; if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); free(int_context->functions); free(int_context); return code; } cc_int32 cc_int_context_get_change_time( cc_context_t context, cc_time* time) { cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ctx_get_change_time_t *request_header = NULL; cc_msg_t *response = NULL; ccmsg_ctx_get_change_time_resp_t *response_header; cc_time64 t64; cc_uint32 type; cc_int32 code; if ( context == NULL || time == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ctx_get_change_time_t*)malloc(sizeof(ccmsg_ctx_get_change_time_t)); if (request_header == NULL) return ccErrNoMem; request_header->ctx = htonll(int_context->handle); code = cci_msg_new(ccmsg_CTX_GET_CHANGE_TIME, &request); if (code != ccNoError) goto cleanup; code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_get_change_time_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (response->type == ccmsg_ACK) { response_header = (ccmsg_ctx_get_change_time_resp_t*)response->header; t64 = ntohll(response_header->time); /* TODO: validate that value is not greater than can fit in cc_time */ *time = (cc_time)t64; code = ccNoError; } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_get_default_ccache_name( cc_context_t context, cc_string_t* name ) { cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ctx_get_default_ccache_name_t *request_header = NULL; cc_msg_t *response = NULL; ccmsg_ctx_get_default_ccache_name_resp_t *response_header; char *string = NULL; cc_uint32 type; cc_int32 code; if ( context == NULL || name == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ctx_get_default_ccache_name_t*)malloc(sizeof(ccmsg_ctx_get_default_ccache_name_t)); if (request_header == NULL) return ccErrNoMem; request_header->ctx = htonll(int_context->handle); code = cci_msg_new(ccmsg_CTX_GET_DEFAULT_CCACHE_NAME, &request); if (code != ccNoError) goto cleanup; code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_get_default_ccache_name_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { response_header = (ccmsg_ctx_get_default_ccache_name_resp_t*)response->header; code = cci_msg_retrieve_blob(response, response_header->name_offset, response_header->name_len, &string); if (code == ccNoError) code = cci_string_new(name, string); } else { code = ccErrBadInternalMessage; } cleanup: if (string) free(string); if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_compare( cc_context_t context, cc_context_t compare_to, cc_uint32* equal ) { cc_int_context_t int_context, int_compare_to; cc_msg_t *request = NULL; ccmsg_ctx_compare_t *request_header = NULL; cc_msg_t *response = NULL; ccmsg_ctx_compare_resp_t *response_header; cc_uint32 type; cc_int32 code; if ( context == NULL || compare_to == NULL || equal == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; int_compare_to = (cc_int_context_t)compare_to; if ( int_context->magic != CC_CONTEXT_MAGIC || int_compare_to->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ctx_compare_t*)malloc(sizeof(ccmsg_ctx_compare_t)); if (request_header == NULL) return ccErrNoMem; request_header->ctx1 = htonll(int_context->handle); request_header->ctx2 = htonll(int_compare_to->handle); code = cci_msg_new(ccmsg_CTX_COMPARE, &request); if (code != ccNoError) goto cleanup; code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_compare_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { response_header = (ccmsg_ctx_compare_resp_t*)response->header; *equal = ntohl(response_header->is_equal); code = ccNoError; } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_new_ccache_iterator( cc_context_t context, cc_ccache_iterator_t* iterator ) { cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ctx_new_ccache_iterator_t *request_header = NULL; cc_msg_t *response = NULL; ccmsg_ctx_new_ccache_iterator_resp_t *response_header; cc_uint32 type; cc_int32 code; if ( context == NULL || iterator == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ctx_new_ccache_iterator_t*)malloc(sizeof(ccmsg_ctx_new_ccache_iterator_t)); if (request_header == NULL) return ccErrNoMem; request_header->ctx = htonll(int_context->handle); code = cci_msg_new(ccmsg_CTX_NEW_CCACHE_ITERATOR, &request); if (code != ccNoError) goto cleanup; code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_new_ccache_iterator_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { response_header = (ccmsg_ctx_new_ccache_iterator_resp_t*)response->header; code = cc_int_ccache_iterator_new(iterator, int_context->handle, ntohll(response_header->iterator)); } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_open_ccache( cc_context_t context, const char* name, cc_ccache_t* ccache ) { cc_uint32 blob_pos; cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ccache_open_t *request_header = NULL; cc_msg_t *response = NULL; ccmsg_ccache_open_resp_t *response_header; cc_uint32 type; cc_int32 code; if ( context == NULL || name == NULL || ccache == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ccache_open_t*)malloc(sizeof(ccmsg_ccache_open_t)); if (request_header == NULL) return ccErrNoMem; code = cci_msg_new(ccmsg_CTX_CCACHE_OPEN, &request); if (code != ccNoError) goto cleanup; code = cci_msg_add_data_blob(request, (void *)name, strlen(name) + 1, &blob_pos); if (code != ccNoError) goto cleanup; request_header->ctx = htonll(int_context->handle); request_header->name_offset = htonl(blob_pos); request_header->name_len = htonl(strlen(name) + 1); code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_open_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { response_header = (ccmsg_ccache_open_resp_t*)response->header; code = cc_int_ccache_new(ccache, int_context->handle, ntohll(response_header->ccache)); } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_open_default_ccache( cc_context_t context, cc_ccache_t* ccache) { cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ccache_open_default_t *request_header = NULL; cc_msg_t *response = NULL; ccmsg_ccache_open_resp_t *response_header; cc_uint32 type; cc_int32 code; if ( context == NULL || ccache == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ccache_open_default_t*)malloc(sizeof(ccmsg_ccache_open_default_t)); if (request_header == NULL) return ccErrNoMem; code = cci_msg_new(ccmsg_CTX_CCACHE_OPEN_DEFAULT, &request); if (code != ccNoError) goto cleanup; request_header->ctx = htonll(int_context->handle); code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_open_default_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { response_header = (ccmsg_ccache_open_resp_t*)response->header; code = cc_int_ccache_new(ccache, int_context->handle, ntohll(response_header->ccache)); } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_create_ccache( cc_context_t context, const char* name, cc_uint32 cred_vers, const char* principal, cc_ccache_t* ccache ) { cc_uint32 blob_pos; cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ccache_create_t *request_header = NULL; cc_msg_t *response = NULL; ccmsg_ccache_create_resp_t *response_header; cc_uint32 type; cc_int32 code; if ( context == NULL || name == NULL || cred_vers == 0 || cred_vers > cc_credentials_v4_v5 || principal == NULL || ccache == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ccache_create_t*)malloc(sizeof(ccmsg_ccache_create_t)); if (request_header == NULL) return ccErrNoMem; code = cci_msg_new(ccmsg_CTX_CCACHE_CREATE, &request); if (code != ccNoError) goto cleanup; code = cci_msg_add_data_blob(request, (void *)name, strlen(name) + 1, &blob_pos); if (code != ccNoError) goto cleanup; request_header->ctx = htonll(int_context->handle); request_header->version = htonl(cred_vers); request_header->name_offset = htonl(blob_pos); request_header->name_len = htonl(strlen(name) + 1); code = cci_msg_add_data_blob(request, (void *)principal, strlen(principal) + 1, &blob_pos); if (code != ccNoError) goto cleanup; request_header->principal_offset = htonl(blob_pos); request_header->principal_len = htonl(strlen(principal) + 1); code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_create_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { response_header = (ccmsg_ccache_create_resp_t*)response->header; code = cc_int_ccache_new(ccache, int_context->handle, ntohll(response_header->ccache)); } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_create_default_ccache( cc_context_t context, cc_uint32 cred_vers, const char* principal, cc_ccache_t* ccache ) { cc_uint32 blob_pos; cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ccache_create_default_t *request_header = NULL; cc_msg_t *response = NULL; ccmsg_ccache_create_resp_t *response_header; cc_uint32 type; cc_int32 code; if ( context == NULL || cred_vers == 0 || cred_vers > cc_credentials_v4_v5 || principal == NULL || ccache == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ccache_create_default_t*)malloc(sizeof(ccmsg_ccache_create_default_t)); if (request_header == NULL) return ccErrNoMem; code = cci_msg_new(ccmsg_CTX_CCACHE_CREATE_DEFAULT, &request); if (code != ccNoError) goto cleanup; request_header->ctx = htonll(int_context->handle); request_header->version = htonl(cred_vers); code = cci_msg_add_data_blob(request, (void *)principal, strlen(principal) + 1, &blob_pos); if (code != ccNoError) goto cleanup; request_header->principal_offset = htonl(blob_pos); request_header->principal_len = htonl(strlen(principal) + 1); code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_create_default_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { response_header = (ccmsg_ccache_create_resp_t*)response->header; code = cc_int_ccache_new(ccache, int_context->handle, ntohll(response_header->ccache)); } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_create_new_ccache( cc_context_t context, cc_uint32 cred_vers, const char* principal, cc_ccache_t* ccache ) { cc_uint32 blob_pos; cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ccache_create_unique_t *request_header = NULL; cc_msg_t *response = NULL; ccmsg_ccache_create_resp_t *response_header; cc_uint32 type; cc_int32 code; if ( context == NULL || cred_vers == 0 || cred_vers > cc_credentials_v4_v5 || principal == NULL || ccache == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ccache_create_unique_t*)malloc(sizeof(ccmsg_ccache_create_unique_t)); if (request_header == NULL) return ccErrNoMem; code = cci_msg_new(ccmsg_CTX_CCACHE_CREATE_UNIQUE, &request); if (code != ccNoError) goto cleanup; request_header->ctx = htonll(int_context->handle); request_header->version = htonl(cred_vers); code = cci_msg_add_data_blob(request, (void *)principal, strlen(principal) + 1, &blob_pos); if (code != ccNoError) goto cleanup; request_header->principal_offset = htonl(blob_pos); request_header->principal_len = htonl(strlen(principal) + 1); code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ccache_create_unique_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = htonl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { response_header = (ccmsg_ccache_create_resp_t*)response-> header; code = cc_int_ccache_new(ccache, int_context->handle, ntohll(response_header->ccache)); } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_lock( cc_context_t context, cc_uint32 lock_type, cc_uint32 block ) { cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ctx_lock_t *request_header = NULL; cc_msg_t *response = NULL; cc_uint32 type; cc_int32 code; if ( context == NULL || (lock_type != cc_lock_read && lock_type != cc_lock_write && lock_type != cc_lock_upgrade && lock_type != cc_lock_downgrade) || (block != cc_lock_block && block != cc_lock_noblock) ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ctx_lock_t*)malloc(sizeof(ccmsg_ctx_lock_t)); if (request_header == NULL) return ccErrNoMem; code = cci_msg_new(ccmsg_CTX_LOCK, &request); if (code != ccNoError) goto cleanup; request_header->ctx = htonll(int_context->handle); request_header->lock_type = htonl(lock_type); code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_lock_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); // TODO: if (block == cc_lock_block) ..... } else if (type == ccmsg_ACK) { code = ccNoError; } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_unlock( cc_context_t context ) { cc_int_context_t int_context; cc_msg_t *request = NULL; ccmsg_ctx_unlock_t *request_header = NULL; cc_msg_t *response = NULL; cc_uint32 type; cc_int32 code; if ( context == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; request_header = (ccmsg_ctx_unlock_t*)malloc(sizeof(ccmsg_ctx_unlock_t)); if (request_header == NULL) return ccErrNoMem; code = cci_msg_new(ccmsg_CTX_UNLOCK, &request); if (code != ccNoError) goto cleanup; request_header->ctx = htonll(int_context->handle); code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_unlock_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { code = ccNoError; } else { code = ccErrBadInternalMessage; } cleanup: if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_clone( cc_context_t inContext, cc_context_t* outContext, cc_int32 requestedVersion, cc_int32* supportedVersion, char const** vendor ) { cc_int_context_t int_context; static char vendor_st[128] = ""; cc_msg_t *request = NULL; ccmsg_ctx_clone_t *request_header = NULL; cc_msg_t *response = NULL; ccmsg_ctx_clone_resp_t *response_header; char *string = NULL; cc_uint32 type; cc_int32 code; if ( inContext == NULL || outContext == NULL || supportedVersion == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)inContext; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; if ((requestedVersion != ccapi_version_2) && (requestedVersion != ccapi_version_3) && (requestedVersion != ccapi_version_4) && (requestedVersion != ccapi_version_5) && (requestedVersion != ccapi_version_6)) { if (supportedVersion != NULL) { *supportedVersion = ccapi_version_max; } return ccErrBadAPIVersion; } request_header = (ccmsg_ctx_clone_t*)malloc(sizeof(ccmsg_ctx_clone_t)); if (request_header == NULL) return ccErrNoMem; request_header->ctx = htonll(int_context->handle); request_header->in_version = htonl(requestedVersion); code = cci_msg_new(ccmsg_INIT, &request); if (code != ccNoError) goto cleanup; code = cci_msg_add_header(request, request_header, sizeof(ccmsg_ctx_clone_t)); if (code != ccNoError) goto cleanup; request_header = NULL; code = cci_perform_rpc(request, &response); if (code != ccNoError) goto cleanup; type = ntohl(response->type); if (type == ccmsg_NACK) { ccmsg_nack_t * nack_header = (ccmsg_nack_t *)response->header; code = ntohl(nack_header->err_code); } else if (type == ccmsg_ACK) { response_header = (ccmsg_ctx_clone_resp_t *)response->header; *supportedVersion = ntohl(response_header->out_version); code = cc_int_context_new(outContext, ntohll(response_header->out_ctx), ntohl(response_header->out_version)); if (!vendor_st[0]) { code = cci_msg_retrieve_blob(response, ntohl(response_header->vendor_offset), ntohl(response_header->vendor_length), &string); strncpy(vendor_st, string, sizeof(vendor_st)-1); vendor_st[sizeof(vendor_st)-1] = '\0'; } *vendor = vendor_st; code = ccNoError; } else { code = ccErrBadInternalMessage; } cleanup: if (string) free(string); if (request_header) free(request_header); if (request) cci_msg_destroy(request); if (response) cci_msg_destroy(response); return code; } cc_int32 cc_int_context_get_version( cc_context_t context, cc_int32* version ) { cc_int_context_t int_context; if ( context == NULL || version == NULL ) return ccErrBadParam; int_context = (cc_int_context_t)context; if ( int_context->magic != CC_CONTEXT_MAGIC ) return ccErrInvalidContext; *version = int_context->api_version; return ccNoError; }