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); );
// 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; }
// 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; }
// 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; }
// 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););
// 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; }
/* * 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); );
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;);
/* @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););
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););
/*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); );
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); );
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;});
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););
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; }
// 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););
// 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); );
// 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; }
CWBool CWWTPInitBinding(int radioIndex){ bindingValues* aux; int i; CW_CREATE_OBJECT_ERR(aux, bindingValues, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL););
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; } }