Beispiel #1
0
CWBool CWACGetVendorInfos(CWACVendorInfos * valPtr)
{
	if (valPtr == NULL)
		return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);

	valPtr->vendorInfosCount = 2;
	CW_CREATE_ARRAY_ERR((valPtr->vendorInfos), valPtr->vendorInfosCount, CWACVendorInfoValues,
			    return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
	    );
Beispiel #2
0
// locks a mutex among threads at the specified address (blocking)
CWBool CWThreadMutexLock(CWThreadMutex *theMutex) {
	if(theMutex == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	if(pthread_mutex_lock( theMutex ) != 0) {
		return CWErrorRaise(CW_ERROR_GENERAL, "Can't lock thread mutex");
	}
/*
	fprintf(stdout, "Mutex %p locked by %p.\n", theMutex, pthread_self());
	fflush(stdout);
*/
	return CW_TRUE;
}
Beispiel #3
0
// Creates a thread that will execute a given function with a given parameter
CWBool CWCreateThread(CWThread *newThread, CW_THREAD_FUNCTION threadFunc, void *arg) {
	if(newThread == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
	CWDebugLog("Create Thread\n");
		
	if(pthread_create(newThread, NULL, threadFunc, arg) != 0) {
		return CWErrorRaise(CW_ERROR_NEED_RESOURCE, "Can't create thread (maybe there are too many other threads)");
	}

	return CW_TRUE;
}
Beispiel #4
0
// Creates a thread condition (wrapper for pthread_cond_init)
CWBool CWCreateThreadCondition(CWThreadCondition *theCondition) {
	if(theCondition == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
	switch(pthread_cond_init(theCondition, NULL)) {
		case 0: // success
			break;
		case ENOMEM:
			return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
		default:
			return CWErrorRaise(CW_ERROR_GENERAL, "Can't create thread condition");
	}
	return CW_TRUE;
}
Beispiel #5
0
// Creates a thread mutex (wrapper for pthread_mutex_init)
CWBool CWCreateThreadMutex(CWThreadMutex *theMutex) {
	if(theMutex == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
	switch(pthread_mutex_init(theMutex, NULL)) {
		case 0: // success
			break;
		case ENOMEM:
			return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
		default:
			return CWErrorRaise(CW_ERROR_GENERAL, "Can't create thread mutex");
	}
	return CW_TRUE;
}
// send Discovery Response to the host at the specified address
CWBool CWAssembleDiscoveryResponse(CWProtocolMessage **messagesPtr, int seqNum, unsigned int WTPID) {
	CWProtocolMessage *msgElems= NULL;
	int msgElemCount = 3;
	CWProtocolMessage *msgElemsBinding= NULL;
	int msgElemBindingCount=0;
	int fragmentsNum;
	int k = -1;
	if(messagesPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
	if(CWACSupportIPv6()) {
		msgElemCount++;
	}
	wid_syslog_debug_debug(WID_WTPINFO,"Assemble Discovery Response");
	CW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););
Beispiel #7
0
// Wait for a thread condition (wrapper for pthread_cond_wait)
CWBool CWWaitThreadCondition(CWThreadCondition *theCondition, CWThreadMutex *theMutex) {
	
	if(theCondition == NULL || theMutex == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
	switch(pthread_cond_wait(theCondition, theMutex)) {
		case 0: // success
			break;
		case  ETIMEDOUT:
			return CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);
		default:
			return CWErrorRaise(CW_ERROR_GENERAL, "Error waiting on thread condition");	
	}

	return CW_TRUE;
}
Beispiel #8
0
/*
 * Manage Join State.
 */
CWStateTransition CWWTPEnterJoin() {

    CWTimerID waitJoinTimer;
    int seqNum;
    CWProtocolJoinResponseValues values;

    CWLog("\n");
    CWLog("######### Join State #########");

    /* reset Join state */
    CWNetworkCloseSocket(gWTPSocket);
    CWSecurityDestroySession(gWTPSession);
    CWSecurityDestroyContext(gWTPSecurityContext);
    gWTPSecurityContext = NULL;
    gWTPSession = NULL;

    /* Initialize gACInfoPtr */
    gACInfoPtr->ACIPv4ListInfo.ACIPv4ListCount=0;
    gACInfoPtr->ACIPv4ListInfo.ACIPv4List=NULL;
    gACInfoPtr->ACIPv6ListInfo.ACIPv6ListCount=0;
    gACInfoPtr->ACIPv6ListInfo.ACIPv6List=NULL;

    if ((waitJoinTimer = timer_add(gCWWaitJoin, 0, CWWTPWaitJoinExpired, NULL)) == -1) {
        return CW_ENTER_DISCOVERY;
    }

    if(gWTPForceACAddress != NULL) {
        CW_CREATE_OBJECT_ERR(gACInfoPtr,
                             CWACInfoValues,
                             return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););
CWBool CWACSendFragments(int WTPIndex)
{
	int i;

	if (gWTPs[WTPIndex].messages == NULL)
		return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);

	for (i = 0; i < gWTPs[WTPIndex].messagesCount; i++) {
#ifdef CW_NO_DTLS
		if (!CWNetworkSendUnsafeUnconnected(gWTPs[WTPIndex].socket,
						    &gWTPs[WTPIndex].address,
						    gWTPs[WTPIndex].messages[i].msg,
						    gWTPs[WTPIndex].messages[i].offset)) {
#else
		if (!
		    (CWSecuritySend
		     (gWTPs[WTPIndex].session, gWTPs[WTPIndex].messages[i].msg, gWTPs[WTPIndex].messages[i].offset))) {
#endif
			return CW_FALSE;
		}
	}

	/*
	 * BUG - ML12
	 *
	 * 20/10/2009 - Donato Capitella
	 */
	CW_FREE_WTP_MSG_ARRAY(WTPIndex);

	CWLog("Message Sent\n");

	return CW_TRUE;
}

CWBool CWACResendAcknowledgedPacket(int WTPIndex)
{
	if (!CWACSendFragments(WTPIndex))
		return CW_FALSE;

	CWThreadSetSignals(SIG_BLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);
	if (!
	    (CWTimerRequest
	     (gCWRetransmitTimer, &(gWTPs[WTPIndex].thread), &(gWTPs[WTPIndex].currentPacketTimer),
	      CW_SOFT_TIMER_EXPIRED_SIGNAL))) {
		return CW_FALSE;
	}
	CWThreadSetSignals(SIG_UNBLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL);

	return CW_TRUE;
}

__inline__ CWBool CWACSendAcknowledgedPacket(int WTPIndex, int msgType, int seqNum)
{
	gWTPs[WTPIndex].retransmissionCount = 0;
	gWTPs[WTPIndex].isRetransmitting = CW_TRUE;
	gWTPs[WTPIndex].responseType = msgType;
	gWTPs[WTPIndex].responseSeqNum = seqNum;
//  CWDebugLog("~~~~~~seq num in Send: %d~~~~~~", gWTPs[WTPIndex].responseSeqNum);
	return CWACResendAcknowledgedPacket(WTPIndex);
}
CWBool CWAssembleWTPVendorPayloadUCI(CWProtocolMessage *msgPtr) {
	int* iPtr;
	unsigned short  msgType;
	CWProtocolVendorSpecificValues* valuesPtr;
	CWVendorUciValues* uciPtr;

	CWLog("Assembling Protocol Configuration Update Request [VENDOR CASE]...");

	if(msgPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);

	if((iPtr = ((int*)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {
	  return CW_FALSE;
	}

	valuesPtr =gWTPs[*iPtr].vendorValues;
	switch (valuesPtr->vendorPayloadType){
			case CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:
				msgType = CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI;
				uciPtr = (CWVendorUciValues *) valuesPtr->payload;
				if (uciPtr->commandArgs != NULL) {
					/* create message */
					CW_CREATE_PROTOCOL_MESSAGE(*msgPtr, sizeof(short)+sizeof(char)+sizeof(int)+(strlen(uciPtr->commandArgs)*sizeof(char)), return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););
					CWProtocolStore16(msgPtr, (unsigned short) msgType);
					CWProtocolStore8(msgPtr, (unsigned char) uciPtr->command);
					CWProtocolStore32(msgPtr, (unsigned int) strlen(uciPtr->commandArgs));
					CWProtocolStoreStr(msgPtr, uciPtr->commandArgs);
				} else {
/*
 * Init multihomed socket. Will bind a socket for each interface + each
 * broadcast address + the wildcard addres + each multicast address in
 * multicastGroups.
 */
CWBool CWNetworkInitSocketServerMultiHomed(CWMultiHomedSocket * sockPtr,
					   int port, char **multicastGroups, int multicastGroupsCount)
{

	struct ifi_info *ifi, *ifihead;
	CWNetworkLev4Address wildaddr;
	int yes = 1;
	CWSocket sock;
	CWMultiHomedInterface *p;
	CWList interfaceList = CW_LIST_INIT;
	CWListElement *el = NULL;
	int i;

	if (sockPtr == NULL)
		return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);

	sockPtr->count = 0;

	/*
	 * note: if get_ifi_info is called with AF_INET6 on an host that doesn't
	 * support IPv6, it'll simply act like if it was called with AF_INET.
	 * Consider aliases as different interfaces (last arg of get_ifi_info is 1).
	 * Why? Just to increase the funny side of the thing.
	 */
#ifdef CW_DEBUGGING
	/* for each network interface... */
	for (ifihead = ifi = get_ifi_info((gNetworkPreferredFamily == CW_IPv6) ? AF_INET6 : AF_INET, 1); ifi != NULL;
	     ifi = ifi->ifi_next) {
#else
	/* for each network interface... */
	for (ifihead = ifi = get_ifi_info((gNetworkPreferredFamily == CW_IPv6) ? AF_INET6 : AF_INET, 0); ifi != NULL;
	     ifi = ifi->ifi_next) {
#endif
		/* bind a unicast address */
		if ((sock = socket(ifi->ifi_addr->sa_family, SOCK_DGRAM, 0)) < 0) {

			free_ifi_info(ifihead);
			CWNetworkRaiseSystemError(CW_ERROR_CREATING);
		}

		/* reuse address */
		setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));

		/* bind address */
		sock_set_port_cw(ifi->ifi_addr, htons(port));

		if (bind
		    (sock, (struct sockaddr *)ifi->ifi_addr,
		     CWNetworkGetAddressSize((CWNetworkLev4Address *) ifi->ifi_addr)) < 0) {

			close(sock);
			CWUseSockNtop(ifi->ifi_addr, CWDebugLog("failed %s", str);
			    );
			continue;
			/* CWNetworkRaiseSystemError(CW_ERROR_CREATING); */
		}

		CWUseSockNtop(ifi->ifi_addr, CWLog("bound %s (%d, %s)", str, ifi->ifi_index, ifi->ifi_name);
		    );
CWBool CWConfigFileInitLib()
{

	gConfigValuesCount = 11;

	CW_CREATE_ARRAY_ERR(gConfigValues,
			    gConfigValuesCount, CWConfigValue, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
	    );
Beispiel #13
0
CWBool CWTimerRequest(int sec, CWThread *threadPtr, CWTimerID *idPtr, int signalToRaise) {

	CWThreadTimerArg *arg;

//	CWDebugLog("Timer Request");
	if(sec < 0 || threadPtr == NULL || idPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
	CW_CREATE_OBJECT_ERR(arg, CWThreadTimerArg, return CW_FALSE;);
Beispiel #14
0
/*
@sock	:
@addrPtr	: Ä¿µÄµØÖ·
@buf	:
@len	:
*/
CWBool CWNetworkSendUnsafeUnconnected(CWSocket sock, 
				      CWNetworkLev4Address *addrPtr,
				      const char *buf,
				      int len) {

	if(buf == NULL || addrPtr == NULL) 
		return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
	CWUseSockNtop(addrPtr, CWDebugLog(str););
Beispiel #15
0
CWBool CWParseSettingsFile()
{
	char *line = NULL;
		
	gSettingsFile = fopen (CW_SETTINGS_FILE, "rb");
	if (gSettingsFile == NULL) {
		CWErrorRaiseSystemError(CW_ERROR_GENERAL);
	}
	
	CW_CREATE_ARRAY_ERR(gDefaultQosValues, NUM_QOS_PROFILES, WTPQosValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););
Beispiel #16
0
/*Update 2009:
    Assemble protocol Configuration update request.
    Mainly added to  manage vendor specific packets*/
CWBool CWProtocolAssembleConfigurationUpdateRequest(CWProtocolMessage ** msgElems, int *msgElemCountPtr,
						    int MsgElementType)
{
	int *iPtr;
	int k = -1;

	if (msgElems == NULL || msgElemCountPtr == NULL)
		return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);

	if ((iPtr = ((int *)CWThreadGetSpecific(&gIndexSpecific))) == NULL) {
		return CW_FALSE;
	}

	*msgElemCountPtr = 1;

	CWLog("Assembling Protocol Configuration Update Request...");

	CW_CREATE_PROTOCOL_MSG_ARRAY_ERR(*msgElems, *msgElemCountPtr, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
	    );
Beispiel #17
0
CWBool ACEnterJoin(int WTPIndex, CWProtocolMessage *msgPtr)
{	
	int seqNum;
	CWProtocolJoinRequestValues joinRequest;
	CWList msgElemList = NULL;
	
	CWLog("\n");
	CWLog("######### Join State #########");	

	if(msgPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
	if(!(CWParseJoinRequestMessage(msgPtr->msg, msgPtr->offset, &seqNum, &joinRequest))) {
		/* note: we can kill our thread in case of out-of-memory 
		 * error to free some space.
		 * we can see this just calling CWErrorGetLastErrorCode()
		 */
		return CW_FALSE;
	}

	// cancel waitJoin timer
	if(!CWTimerCancel(&(gWTPs[WTPIndex].currentTimer)))
	{
		return CW_FALSE;
	}

	CWBool ACIpv4List = CW_FALSE;
	CWBool ACIpv6List = CW_FALSE;
	CWBool resultCode = CW_TRUE;
	int resultCodeValue = CW_PROTOCOL_SUCCESS;
	/* CWBool sessionID = CW_FALSE; */

	if(!(CWSaveJoinRequestMessage(&joinRequest, &(gWTPs[WTPIndex].WTPProtocolManager)))) {

		resultCodeValue = CW_PROTOCOL_FAILURE_RES_DEPLETION;
	}
	
	CWMsgElemData *auxData;
	if(ACIpv4List) {
		CW_CREATE_OBJECT_ERR(auxData, CWMsgElemData, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););
                auxData->type = CW_MSG_ELEMENT_AC_IPV4_LIST_CW_TYPE;
		auxData->value = 0;
		CWAddElementToList(&msgElemList,auxData);
	}
/* send Discovery Response to the host at the specified address */
CWBool CWAssembleDiscoveryResponse(CWProtocolMessage ** messagesPtr, int seqNum)
{

	CWProtocolMessage *msgElems = NULL;
	int msgElemCount = 4;
	CWProtocolMessage *msgElemsBinding = NULL;
	int msgElemBindingCount = 0;
	int fragmentsNum;

	int k = -1;
	if (messagesPtr == NULL)
		return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);

	if (CWACSupportIPv6()) {
		msgElemCount++;
	}

	CWLog("Send Discovery Response");
	CW_CREATE_PROTOCOL_MSG_ARRAY_ERR(msgElems, msgElemCount, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
	    );
Beispiel #19
0
CWBool CWSecurityInitLib()
{

	int i;

	SSL_load_error_strings();
	SSL_library_init();

	/* setup mutexes for openssl internal locking */
	CW_CREATE_ARRAY_ERR(mutexOpensslBuf,
			    CRYPTO_num_locks() * sizeof(CWThreadMutex),
			    CWThreadMutex, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, "Cannot create openssl mutexes");
	    )
CWBool CW80211ParseFrameIESSID(char * frameReceived, int * offsetFrameReceived, char ** value) {
	
	if(frameReceived[0] != IE_TYPE_SSID)
		return CW_FALSE;
	
	(*offsetFrameReceived)++;
	
	short int len = frameReceived[1];
	if(len == 0)
		return CW_FALSE;
		
	(*offsetFrameReceived)++;
	
	CW_CREATE_ARRAY_CALLOC_ERR((*value), len+1, char, {CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL); return CW_FALSE;});
Beispiel #21
0
CWBool CWWTPCheckForWTPEventRequest(){

	CWDebugLog("\n");
	CWDebugLog("#________ WTP Event Request Message (Run) ________#");
	
	/* Send WTP Event Request */
	CWList msgElemList = NULL;
	CWProtocolMessage *messages = NULL;
	int fragmentsNum = 0;
	int seqNum;
	int *pendingReqIndex;
		
	seqNum = CWGetSeqNum();

	CW_CREATE_OBJECT_ERR(pendingReqIndex, int, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););
Beispiel #22
0
CWBool CWSecurityInitSessionClient(CWSocket sock, CWNetworkLev4Address *addrPtr, CWSafeList packetReceiveList, CWSecurityContext ctx, CWSecuritySession *sessionPtr, int *PMTUPtr) {
	BIO *sbio = NULL;
	CWNetworkLev4Address peer;
	int peerlen = sizeof(peer);
	int i;

	if(ctx == NULL || sessionPtr == NULL || PMTUPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
	if((*sessionPtr = SSL_new(ctx)) == NULL) {
		CWSecurityRaiseError(CW_ERROR_CREATING);
	}
	
	#ifdef CW_DEBUGGING
		CWDebugLog("My Certificate");
		PEM_write_X509(stdout, SSL_get_certificate(*sessionPtr));
	#endif
	
    if((sbio = BIO_new_memory(sock, addrPtr, packetReceiveList)) == NULL) {
		SSL_free(*sessionPtr);
		CWSecurityRaiseError(CW_ERROR_CREATING);
	}

	if (getsockname(sock, (struct sockaddr*)&peer, (void *)&peerlen) < 0) {
		SSL_free(*sessionPtr);
		CWSecurityRaiseSystemError(CW_ERROR_GENERAL);
	}
	
	i = BIO_ctrl_set_connected(sbio, 1, &peer);
	
	//BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); // TO-DO (pass MTU?)
	BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_MTU, 10000, NULL); // TO-DO if we don't set a big MTU, thw DTLS implementation will
														 // not be able to use a big certificate 
	

	// Let the verify_callback catch the verify_depth error so that we get
	// an appropriate error in the logfile.
	SSL_set_verify_depth((*sessionPtr), CW_DTLS_CERT_VERIFY_DEPTH + 1);

    SSL_set_read_ahead( (*sessionPtr), 1); // required by DTLS implementation to avoid data loss
	
    SSL_set_bio((*sessionPtr), sbio, sbio);
	SSL_set_connect_state((*sessionPtr));
	
	CWDebugLog("Before HS");
	CWSecurityManageSSLError(
			SSL_do_handshake(*sessionPtr), *sessionPtr, SSL_free(*sessionPtr););
CWBool ACEnterDataCheck(int WTPIndex, CWProtocolMessage * msgPtr)
{

	/*CWProtocolMessage *messages = NULL; */
	int seqNum;
	CWProtocolChangeStateEventRequestValues *changeStateEvent;

	CWLog("\n");
	CWDebugLog("######### Status Event #########");

	/* Destroy ChangeStatePending timer */
	if (!CWErr(CWTimerCancel(&(gWTPs[WTPIndex].currentTimer)))) {

		CWCloseThread();
	}

	CW_CREATE_OBJECT_ERR(changeStateEvent,
			     CWProtocolChangeStateEventRequestValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
	    );
CWBool CWParseSettingsFile()
{
	char *line = NULL;
		
	gSettingsFile = fopen (CW_SETTINGS_FILE, "rb");
	if (gSettingsFile == NULL) {
		CWErrorRaiseSystemError(CW_ERROR_GENERAL);
	}
	
	while((line = (char*)CWGetCommand(gSettingsFile)) != NULL) 
	{
		char* startTag=NULL;
		char* endTag=NULL;
		
		if((startTag=strchr (line, '<'))==NULL) 
		{
			CW_FREE_OBJECT(line);
			continue;
		}

		if((endTag=strchr (line, '>'))==NULL) 
		{
			CW_FREE_OBJECT(line);
			continue;
		}
			
		if (!strncmp(startTag+1, "IF_NAME", endTag-startTag-1))
		{
			char* startValue=NULL;
			char* endValue=NULL;
			int offset = 0;

			CWExtractValue(endTag, &startValue, &endValue, &offset);

			CW_CREATE_STRING_ERR(gInterfaceName, offset, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY,NULL););
			strncpy(gInterfaceName, startValue, offset);
			gInterfaceName[offset] ='\0';
			CWLog(": %s", gInterfaceName);
			CW_FREE_OBJECT(line);
			continue;	
		}
Beispiel #25
0
// Manage Join State
CWStateTransition CWWTPEnterJoin() {
	CWTimerID waitJoinTimer;
	int seqNum;
	CWProtocolJoinResponseValues values;
	
	CWWTPDebugLog("######### Join State #########");
	// reset Join state
	CWNetworkCloseSocket(gWTPSocket);
#ifndef CW_NO_DTLS//csc
	if(gDtlsSecurity == 1)
	{
		CWSecurityDestroySession(gWTPSession);
		CWSecurityDestroyContext(gWTPSecurityContext);
		gWTPSecurityContext = NULL;
		gWTPSession = NULL;
	}
#endif
	//Initialize gACInfoPtr
	gACInfoPtr->ACIPv4ListInfo.ACIPv4ListCount=0;
	gACInfoPtr->ACIPv4ListInfo.ACIPv4List=NULL;	
	gACInfoPtr->ACIPv6ListInfo.ACIPv6ListCount=0;
	gACInfoPtr->ACIPv6ListInfo.ACIPv6List=NULL;

	/*
	 * MAURO: allo scadere del waitJoinTimer viene invocata, in modo 
	 * asincrono, CWWTPWaitJoinExpired(0) 	
	 */

	if ((waitJoinTimer = timer_add(gCWWaitJoin, 0, CWWTPWaitJoinExpired, NULL)) == -1) {
		return CW_ENTER_DISCOVERY;
	}

	/*
	 * MAURO: gWTPForceACAddress contine l'"indirizzo" dell'AC con cui fare
	 * il JOIN nel caso che sia specificato nel file di configuarazione.
	 * Se questa var globale e' settata da WTP.c viene invocata direttamente
	 * CWWTPEnterJoin per saltare il DISCOVERY.
	 */
	if(gWTPForceACAddress != NULL) {
		CW_CREATE_OBJECT_ERR(gACInfoPtr, CWACInfoValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););	
Beispiel #26
0
// Assemble a CAPWAP Data Packet creating Transport Header.
// completeMsgPtr is an array of fragments (can be of size 1 if the packet doesn't need fragmentation)
CWBool CWAssembleDataMessage(CWProtocolMessage **completeMsgPtr, int *fragmentsNumPtr, int PMTU, CWProtocolMessage *frame, CWBindingTransportHeaderValues *bindingValuesPtr, int is_crypted) {
	CWProtocolMessage transportHdr = {0};
	CWProtocolTransportHeaderValues transportVal = {0};

	if(completeMsgPtr == NULL || fragmentsNumPtr == NULL || frame == NULL || bindingValuesPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
//	CWDebugLog("PMTU: %d", PMTU);
	
	// handle fragmentation
	
	PMTU = PMTU - gMaxCAPWAPHeaderSizeBinding;
	
	if(PMTU > 0) {
		PMTU = (PMTU/8)*8; // CAPWAP fragments are made of groups of 8 bytes
		if(PMTU == 0) goto cw_dont_fragment;
		
//		CWDebugLog("Aligned PMTU: %d", PMTU);
		*fragmentsNumPtr = (frame->offset) / PMTU;
		if((frame->offset % PMTU) != 0) (*fragmentsNumPtr)++;
		//CWDebugLog("Fragments #: %d", *fragmentsNumPtr);
	} else {
	cw_dont_fragment:
		*fragmentsNumPtr = 1;
	}
	
	transportVal.bindingValuesPtr = bindingValuesPtr;
		
	if(*fragmentsNumPtr == 1) {
//		CWDebugLog("1 Fragment");
			
		transportVal.isFragment = transportVal.last = transportVal.fragmentOffset = transportVal.fragmentID = 0;
		transportVal.payloadType = is_crypted;		

		// Assemble Message Elements
		if(!(CWAssembleTransportHeader(&transportHdr, &transportVal))) {
			CW_FREE_PROTOCOL_MESSAGE(transportHdr);
			return CW_FALSE; // will be handled by the caller
		} 
		
		CW_CREATE_OBJECT_ERR_WID(*completeMsgPtr, CWProtocolMessage, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););
/*
 * Manage Join State.
 */
CWStateTransition CWWTPEnterJoin()
{

	CWTimerID waitJoinTimer;
	int seqNum;
	CWProtocolJoinResponseValues values;
	CWStateTransition state = CW_ENTER_DISCOVERY;
	CWDebugLog("Checking if hostapd is connected...");
	if (gRADIO_MAC[0] == 0xAA){
	CWDebugLog("Waiting for hostapd to connect...");
       	while(gRADIO_MAC[0] == 0xAA) sleep(1);
	}
	else {
	CWDebugLog("Hostapd is connected...");
	}

	CWDebugLog("\n");
	CWDebugLog("######### Join State #########");

	/* reset Join state */
	CWNetworkCloseSocket(gWTPSocket);
#ifndef CW_NO_DTLS
	CWSecurityDestroySession(gWTPSession);
	CWSecurityDestroyContext(gWTPSecurityContext);
#endif
	gWTPSecurityContext = NULL;
	gWTPSession = NULL;

	/* Initialize gACInfoPtr */
	gACInfoPtr = malloc(sizeof(CWACInfoValues));
	gACInfoPtr->ACIPv4ListInfo.ACIPv4ListCount = 0;
	gACInfoPtr->ACIPv4ListInfo.ACIPv4List = NULL;
	gACInfoPtr->ACIPv6ListInfo.ACIPv6ListCount = 0;
	gACInfoPtr->ACIPv6ListInfo.ACIPv6List = NULL;
        CWDebugLog("State is %d", state);

        if (gWTPForceACAddress != NULL) {
                CW_CREATE_OBJECT_ERR(gACInfoPtr, CWACInfoValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
                    );
Beispiel #28
0
// creates a semaphore
CWBool CWThreadCreateSem(CWThreadSem *semPtr, int value) {
	if(semPtr == NULL) return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	
	// we use named semaphore on platforms that support only them (e.g. Mac OS X)
	#ifdef CW_USE_NAMED_SEMAPHORES
	{
		static int semCount = 0;
		char name[32];

		snprintf(name, 32, "/CWSem-%d-%4.4d", getpid(), semCount++);
		if ( (semPtr->semPtr = sem_open(name, O_CREAT, 0600, value)) == (sem_t *)SEM_FAILED ) {
			CWErrorRaiseSystemError(CW_ERROR_GENERAL);
		} else {
			sem_unlink(name);
		}
	}
	#else
		if ( sem_init(semPtr, 0, value) < 0 ) {
			CWErrorRaiseSystemError(CW_ERROR_GENERAL);
		}
	#endif
	
	return CW_TRUE;
}
Beispiel #29
0
CWBool CWWTPInitBinding(int radioIndex){
	
	bindingValues* aux;
	int i;

	CW_CREATE_OBJECT_ERR(aux, bindingValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););
Beispiel #30
0
CWBool ACEnterRun(int WTPIndex, CWProtocolMessage *msgPtr, CWBool dataFlag) {

	CWBool toSend = CW_FALSE, timerSet = CW_TRUE;
	CWControlHeaderValues controlVal;
	CWProtocolMessage* messages = NULL;
	int messagesCount = 0;
	unsigned char StationMacAddr[MAC_ADDR_LEN];
	char string[10];
	char socketctl_path_name[50];
	char socketserv_path_name[50];
	msgPtr->offset = 0;

	// cancel NeighborDeadTimer timer
	CWStopNeighborDeadTimer(WTPIndex);
	timerSet = CW_FALSE;

	if (dataFlag) {
		/* We have received a Data Message... now just log this event and do actions by the dataType */
		CWLog("--> Received a DATA Message");

		if (msgPtr->data_msgType == CW_DATA_MSG_FRAME_TYPE) {
			/*Retrive mac address station from msg*/
			memset(StationMacAddr, 0, MAC_ADDR_LEN);
			memcpy(StationMacAddr, msgPtr->msg + SOURCE_ADDR_START, MAC_ADDR_LEN);

			int seqNum = CWGetSeqNum();

			//Send a Station Configuration Request
			if (CWAssembleStationConfigurationRequest(&(gWTPs[WTPIndex].messages),
					&(gWTPs[WTPIndex].messagesCount), gWTPs[WTPIndex].pathMTU, seqNum,
					StationMacAddr)) {

				if (CWACSendAcknowledgedPacket(WTPIndex,
						CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_RESPONSE, seqNum))
					return CW_TRUE;
				else
					CWACStopRetransmission(WTPIndex);
			}
		} else {

			/************************************************************
			 * Update 2009:												*
			 *				Manage special data packets with frequency	*
			 *				statistics informations.					*
			 ************************************************************/

			if (msgPtr->data_msgType == CW_DATA_MSG_FREQ_STATS_TYPE) {

				int cells; /* How many cell are heard */
				int isAck;
				char * freqPayload;
				int socketIndex, indexToSend = htonl(WTPIndex);

				int sizeofAckInfoUnit = CW_FREQ_ACK_SIZE;
				int sizeofFreqInfoUnit = CW_FREQ_CELL_INFO_PAYLOAD_SIZE;
				int sizeOfPayload = 0, payload_offset = 0;

				/*-----------------------------------------------------------------------------------------------
				 *	Payload Management ( infos for frequency application) :
				 *		Ack       Structure : |  WTPIndex  |   Ack Value  | 
				 *      Freq Info Structure : |  WTPIndex  |  Number of cells  |  Frequecies Info Payload | 
				 *-----------------------------------------------------------------------------------------------*/

				memcpy(&isAck, msgPtr->msg, sizeof(int));

				isAck = ntohl(isAck);

				if (isAck == 0) { /* isnt an ack message */
					memcpy(&cells, msgPtr->msg + sizeof(int), sizeof(int));
					cells = ntohl(cells);
					sizeOfPayload = (cells * sizeofFreqInfoUnit) + (2 * sizeof(int));
				} else {
					sizeOfPayload = sizeofAckInfoUnit;
				}

				if ((freqPayload = malloc(sizeOfPayload)) != NULL) {

					memset(freqPayload, 0, sizeOfPayload);
					memcpy(freqPayload, &indexToSend, sizeof(int));
					payload_offset += sizeof(int);

					if (isAck == 0) {
						memcpy(freqPayload + payload_offset, msgPtr->msg + sizeof(int),
								sizeOfPayload - payload_offset);
					} else {
						memcpy(freqPayload + payload_offset, msgPtr->msg + sizeof(int),
								sizeOfPayload - payload_offset);
					}

					socketIndex = gWTPs[WTPIndex].applicationIndex;

					/****************************************************
					 *		Forward payload to correct application 		*
					 ****************************************************/

					if (!CWErr(CWThreadMutexLock(&appsManager.socketMutex[socketIndex]))) {
						CWLog("[ACrunState]:: Error locking socket Application Mutex");
						free(freqPayload);
						return CW_FALSE;
					}

					if (Writen(appsManager.appSocket[socketIndex], freqPayload, sizeOfPayload) < 0) {
						CWThreadMutexUnlock(&appsManager.socketMutex[socketIndex]);
						free(freqPayload);
						CWLog("[ACrunState]:: Error writing Message To Application");
						return CW_FALSE;
					}

					CWThreadMutexUnlock(&appsManager.socketMutex[socketIndex]);
					free(freqPayload);
				} else
					CWLog("[ACrunState]:: Malloc error (payload to frequency application");
			}

			if (msgPtr->data_msgType == CW_DATA_MSG_STATS_TYPE) {
				if (!UnixSocksArray[WTPIndex].data_stats_sock) { //Init Socket only the first time when the function is called
					if ((UnixSocksArray[WTPIndex].data_stats_sock = socket(AF_UNIX, SOCK_DGRAM, 0))
							< 0) {
						CWDebugLog("Error creating socket for data send");
						return CW_FALSE;
					}

					memset(&(UnixSocksArray[WTPIndex].clntaddr), (int) NULL,
							sizeof(UnixSocksArray[WTPIndex].clntaddr));
					UnixSocksArray[WTPIndex].clntaddr.sun_family = AF_UNIX;

					//make unix socket client path name by index i
					snprintf(string, sizeof(string), "%d", WTPIndex);
					string[sizeof(string) - 1] = 0;
					strcpy(socketctl_path_name, SOCKET_PATH_AC);
					strcat(socketctl_path_name, string);
					strcpy(UnixSocksArray[WTPIndex].clntaddr.sun_path, socketctl_path_name);

					unlink(socketctl_path_name);

					memset(&(UnixSocksArray[WTPIndex].servaddr), (int) NULL,
							sizeof(UnixSocksArray[WTPIndex].servaddr));
					UnixSocksArray[WTPIndex].servaddr.sun_family = AF_UNIX;

					//make unix socket server path name by index i
					strcpy(socketserv_path_name, SOCKET_PATH_RECV_AGENT);
					strcat(socketserv_path_name, string);
					strcpy(UnixSocksArray[WTPIndex].servaddr.sun_path, socketserv_path_name);
					CWDebugLog("%s\t%s", socketserv_path_name, socketctl_path_name);
					//fflush(stdout);
				}

				int nbytes;
				int totalBytesToSend = 0;
				bcopy((char*) msgPtr->msg, (char*) &totalBytesToSend, sizeof(unsigned int));
				totalBytesToSend = ntohl(totalBytesToSend);
				int pDataLen = totalBytesToSend; //len of Monitoring Data

				//CWDebugLog("\n%s\t%s", socketserv_path_name, socketctl_path_name);


				CWDebugLog("Total bytes to send %d", totalBytesToSend);

				//Send data stats from AC thread to monitor client over unix socket
				nbytes = sendto(UnixSocksArray[WTPIndex].data_stats_sock, msgPtr->msg, pDataLen, 0,
						(struct sockaddr *) &(UnixSocksArray[WTPIndex].servaddr),
						sizeof(UnixSocksArray[WTPIndex].servaddr));
				if (nbytes < 0) {
					CWDebugLog("Error sending data over socket");
					perror("send error");
					return CW_FALSE;
				}

			}
		}

		return CW_TRUE;
	}

	if (!(CWACParseGenericRunMessage(WTPIndex, msgPtr, &controlVal))) {
		/* Two possible errors: WRONG_ARG and INVALID_FORMAT
		 * In the second case we have an unexpected response: ignore the
		 * message and log the event.
		 */
		return CW_FALSE;
	}

	switch (controlVal.messageTypeValue) {
	case CW_MSG_TYPE_VALUE_CONFIGURE_UPDATE_RESPONSE: {
		CWProtocolResultCode resultCode;
		/*Update 2009:
		 Store Protocol specific response data*/
		CWProtocolVendorSpecificValues* protocolValues = NULL;

		if (!(CWParseConfigurationUpdateResponseMessage(msgPtr, controlVal.msgElemsLen,
				&resultCode, &protocolValues)))
			return CW_FALSE;

		CWACStopRetransmission(WTPIndex);

		if (timerSet) {
			if (!CWRestartNeighborDeadTimer(WTPIndex)) {
				CWDebugLog("CWRestartNeighborDeadTimer returned false");
				CWCloseThread();
			}
		} else {
			if (!CWStartNeighborDeadTimer(WTPIndex)) {
				CWDebugLog("CWStartNeighborDeadTimer returned false");
				CWCloseThread();
			}
		}

		//CWSaveConfigurationUpdateResponseMessage(resultCode, WTPIndex, protocolValues);

		if (resultCode == CW_PROTOCOL_SUCCESS) {
			CWDebugLog("Result Success for Configuration update!!");
			//gWTPs[WTPIndex].isRequestClose = CW_TRUE;
			//CWSignalThreadCondition(&gWTPs[WTPIndex].interfaceWait);
		}

		/*if (gWTPs[WTPIndex].interfaceCommandProgress == CW_TRUE) {
		 CWThreadMutexLock(&gWTPs[WTPIndex].interfaceMutex);
		 gWTPs[WTPIndex].interfaceResult = 1;
		 gWTPs[WTPIndex].interfaceCommandProgress = CW_FALSE;
		 CWSignalThreadCondition(&gWTPs[WTPIndex].interfaceComplete);

		 CWThreadMutexUnlock(&gWTPs[WTPIndex].interfaceMutex);
		 }*/

		break;
	}
	case CW_MSG_TYPE_VALUE_CHANGE_STATE_EVENT_REQUEST: {
		CWProtocolChangeStateEventRequestValues *valuesPtr;

		if (!(CWParseChangeStateEventRequestMessage2(msgPtr, controlVal.msgElemsLen, &valuesPtr)))
			return CW_FALSE;
		if (timerSet) {
			if (!CWRestartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		} else {
			if (!CWStartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		}
		if (!(CWSaveChangeStateEventRequestMessage(valuesPtr, &(gWTPs[WTPIndex].WTPProtocolManager))))
			return CW_FALSE;
		if (!(CWAssembleChangeStateEventResponse(&messages, &messagesCount,
				gWTPs[WTPIndex].pathMTU, controlVal.seqNum)))
			return CW_FALSE;

		toSend = CW_TRUE;
		break;
	}
	case CW_MSG_TYPE_VALUE_ECHO_REQUEST: {
		if (!(CWParseEchoRequestMessage(msgPtr, controlVal.msgElemsLen)))
			return CW_FALSE;
		if (timerSet) {
			if (!CWRestartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		} else {
			if (!CWStartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		}

		if (!(CWAssembleEchoResponse(&messages, &messagesCount, gWTPs[WTPIndex].pathMTU,
				controlVal.seqNum)))
			return CW_FALSE;

		toSend = CW_TRUE;
		break;
	}
	case CW_MSG_TYPE_VALUE_STATION_CONFIGURATION_RESPONSE: {
		CWProtocolResultCode resultCode;
		if (!(CWParseStationConfigurationResponseMessage(msgPtr, controlVal.msgElemsLen,
				&resultCode)))
			return CW_FALSE;
		CWACStopRetransmission(WTPIndex);
		if (timerSet) {
			if (!CWRestartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		} else {
			if (!CWStartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		}
		//CWSaveStationConfigurationResponseMessage(resultCode, WTPIndex);  <-- Must be Implemented ????

		break;
	}
	case CW_MSG_TYPE_VALUE_CLEAR_CONFIGURATION_RESPONSE: {
		CWProtocolResultCode resultCode;
		if (!(CWParseClearConfigurationResponseMessage(msgPtr, controlVal.msgElemsLen, &resultCode)))
			return CW_FALSE;
		CWACStopRetransmission(WTPIndex);
		if (timerSet) {
			if (!CWRestartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		} else {
			if (!CWStartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		}

		if (gWTPs[WTPIndex].interfaceCommandProgress == CW_TRUE) {
			CWThreadMutexLock(&gWTPs[WTPIndex].interfaceMutex);

			gWTPs[WTPIndex].interfaceResult = 1;
			gWTPs[WTPIndex].interfaceCommandProgress = CW_FALSE;
			CWSignalThreadCondition(&gWTPs[WTPIndex].interfaceComplete);

			CWThreadMutexUnlock(&gWTPs[WTPIndex].interfaceMutex);
		}

		break;
	}
	case CW_MSG_TYPE_VALUE_DATA_TRANSFER_REQUEST: {
		CWProtocolWTPDataTransferRequestValues valuesPtr;

		if (!(CWParseWTPDataTransferRequestMessage(msgPtr, controlVal.msgElemsLen, &valuesPtr)))
			return CW_FALSE;
		if (timerSet) {
			if (!CWRestartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		} else {
			if (!CWStartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		}
		if (!(CWAssembleWTPDataTransferResponse(&messages, &messagesCount, gWTPs[WTPIndex].pathMTU,
				controlVal.seqNum)))
			return CW_FALSE;
		toSend = CW_TRUE;
		break;
	}
	case CW_MSG_TYPE_VALUE_WTP_EVENT_REQUEST: {
		CWProtocolWTPEventRequestValues valuesPtr;

		if (!(CWParseWTPEventRequestMessage(msgPtr, controlVal.msgElemsLen, &valuesPtr)))
			return CW_FALSE;
		if (timerSet) {
			if (!CWRestartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		} else {
			if (!CWStartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		}
		if (!(CWSaveWTPEventRequestMessage(&valuesPtr, &(gWTPs[WTPIndex].WTPProtocolManager))))
			return CW_FALSE;

		if (!(CWAssembleWTPEventResponse(&messages, &messagesCount, gWTPs[WTPIndex].pathMTU,
				controlVal.seqNum)))
			return CW_FALSE;

		toSend = CW_TRUE;
		break;
	}
	default:
		/*
		 * We have an unexpected request and we have to send
		 * a corresponding response containing a failure result code
		 */
		CWLog("--> Not valid Request in Run State... we send a failure Response");
		if (timerSet) {
			if (!CWRestartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		} else {
			if (!CWStartNeighborDeadTimer(WTPIndex)) {
				CWCloseThread();
			}
		}
		if (!(CWAssembleUnrecognizedMessageResponse(&messages, &messagesCount,
				gWTPs[WTPIndex].pathMTU, controlVal.seqNum, controlVal.messageTypeValue + 1)))
			return CW_FALSE;

		toSend = CW_TRUE;
		/*return CWErrorRaise(CW_ERROR_INVALID_FORMAT, "Message not valid in Run State");*/
	}
	if (toSend) {
		int i;
		CWDebugLog("There is something so send...");

		if (messages == NULL)
			return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);

		for (i = 0; i < messagesCount; i++) {
#ifdef CW_NO_DTLS
			if(!CWNetworkSendUnsafeUnconnected(gWTPs[WTPIndex].socket,
							&gWTPs[WTPIndex].address,
							messages[i].msg,
							messages[i].offset) ) {
#else
			if (!(CWSecuritySend(gWTPs[WTPIndex].session, messages[i].msg, messages[i].offset))) {
#endif
				CWFreeMessageFragments(messages, messagesCount);
				CW_FREE_OBJECT(messages);
				return CW_FALSE;
			}
		}
		CWFreeMessageFragments(messages, messagesCount);
		CW_FREE_OBJECT(messages);
	}
	gWTPs[WTPIndex].currentState = CW_ENTER_RUN;
	gWTPs[WTPIndex].subState = CW_WAITING_REQUEST;

	CWDebugLog("Coming out of ACEnterRun..");

	return CW_TRUE;
}

CWBool CWACParseGenericRunMessage(int WTPIndex, CWProtocolMessage *msg,
		CWControlHeaderValues* controlVal) {

	if (msg == NULL || controlVal == NULL)
		return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);

	if (!(CWParseControlHeader(msg, controlVal)))
		/* will be handled by the caller */
		return CW_FALSE;

	/* skip timestamp */
	controlVal->msgElemsLen -= CW_CONTROL_HEADER_OFFSET_FOR_MSG_ELEMS;

	/* Check if it is a request */
	if (controlVal->messageTypeValue % 2 == 1) {

		return CW_TRUE;
	}

	if ((gWTPs[WTPIndex].responseSeqNum != controlVal->seqNum) || (gWTPs[WTPIndex].responseType
			!= controlVal->messageTypeValue)) {

		CWDebugLog("gWTPs: %d\n", gWTPs[WTPIndex].responseSeqNum);
		CWDebugLog("controlVal: %d\n", controlVal->seqNum);
		CWErrorRaise(CW_ERROR_INVALID_FORMAT, "Seq Num or Msg Type not valid!");
		return CW_FALSE;
	}

	return CW_TRUE;
}

/*Update 2009:
 Added vendValues to include a response payload (to pass response data)*/
CWBool CWParseConfigurationUpdateResponseMessage(CWProtocolMessage* msgPtr, int len,
		CWProtocolResultCode* resultCode, CWProtocolVendorSpecificValues** vendValues) {

	int offsetTillMessages;

	if (msgPtr == NULL || resultCode == NULL)
		return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
	if ((msgPtr->msg) == NULL)
		return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);

	offsetTillMessages = msgPtr->offset;

	CWLog("Parsing Configuration Update Response...");

	/* parse message elements */
	while ((msgPtr->offset - offsetTillMessages) < len) {

		unsigned short int elemType = 0;
		unsigned short int elemLen = 0;

		CWParseFormatMsgElem(msgPtr, &elemType, &elemLen);

		switch (elemType) {
		case CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE:
			*resultCode = CWProtocolRetrieve32(msgPtr);
			break;

			/*Update 2009:
			 Added case to implement conf update response with payload*/
		case CW_MSG_ELEMENT_RESULT_CODE_CW_TYPE_WITH_PAYLOAD: {
			int payloadSize = 0;
			CW_CREATE_OBJECT_ERR(*vendValues, CWProtocolVendorSpecificValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););

			*resultCode = CWProtocolRetrieve32(msgPtr);

			if (CWProtocolRetrieve16(msgPtr) != CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_CW_TYPE)
				/*For now, we only have UCI payloads, so we will accept only vendor payloads for protocol data*/
				return CWErrorRaise(CW_ERROR_INVALID_FORMAT, "Unrecognized Message Element in Configuration Update Response");

			(*vendValues)->vendorPayloadType = CWProtocolRetrieve16(msgPtr);

			switch ((*vendValues)->vendorPayloadType) {
			case CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_UCI:
				payloadSize = CWProtocolRetrieve32(msgPtr);
				if (payloadSize != 0) {
					(*vendValues)->payload = (void *) CWProtocolRetrieveStr(msgPtr, payloadSize);
				} else
					(*vendValues)->payload = NULL;
				break;
			case CW_MSG_ELEMENT_VENDOR_SPEC_PAYLOAD_WUM:
				payloadSize = CWProtocolRetrieve32(msgPtr);

				if (payloadSize <= 0) {
					/* Payload can't be zero here,
					 * at least the message type must be specified */
					return CWErrorRaise(CW_ERROR_INVALID_FORMAT, "Unrecognized Message Element in Configuration Update Response");
				}
				(*vendValues)->payload = (void *) CWProtocolRetrieveRawBytes(msgPtr, payloadSize);
				break;
			default:
				return CWErrorRaise(CW_ERROR_INVALID_FORMAT, "Unrecognized Message Element in Configuration Update Response");
				break;
			}
		}
			break;
		default:
			return CWErrorRaise(CW_ERROR_INVALID_FORMAT, "Unrecognized Message Element in Configuration Update Response");
			break;
		}
	}