// 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););
void CWACStopRetransmission(int WTPIndex) { if (gWTPs[WTPIndex].isRetransmitting) { int i; CWDebugLog("Stop Retransmission"); gWTPs[WTPIndex].isRetransmitting = CW_FALSE; CWThreadSetSignals(SIG_BLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL); if (!CWTimerCancel(&(gWTPs[WTPIndex].currentPacketTimer))) { CWDebugLog("Error Cancelling a Timer... possible error!"); } CWThreadSetSignals(SIG_UNBLOCK, 1, CW_SOFT_TIMER_EXPIRED_SIGNAL); gWTPs[WTPIndex].responseType = UNUSED_MSG_TYPE; gWTPs[WTPIndex].responseSeqNum = 0; for (i = 0; i < gWTPs[WTPIndex].messagesCount; i++) { CW_FREE_PROTOCOL_MESSAGE(gWTPs[WTPIndex].messages[i]); } CW_FREE_OBJECT(gWTPs[WTPIndex].messages); // CWDebugLog("~~~~~~ End of Stop Retransmission"); } }
void CWResetPendingMsgBox(CWPendingRequestMessage *pendingRequestMsgs) { pendingRequestMsgs->msgType = UNUSED_MSG_TYPE; pendingRequestMsgs->seqNum = 0; pendingRequestMsgs->retransmission = 0; pendingRequestMsgs->timer_sec = 0; pendingRequestMsgs->timer_hdl = NULL; CW_FREE_OBJECT(pendingRequestMsgs->timer_arg); pendingRequestMsgs->timer_arg = NULL; timer_rem(pendingRequestMsgs->timer, NULL); int i; for(i=0; i<(pendingRequestMsgs->fragmentsNum); i++){ CW_FREE_PROTOCOL_MESSAGE((pendingRequestMsgs->msgElems)[i]); } CW_FREE_OBJECT(pendingRequestMsgs->msgElems); pendingRequestMsgs->fragmentsNum = 0; return; }
/* * Manage Discovery State */ CWStateTransition CWWTPEnterDiscovery() { int i; CWBool j; CWLog("\n"); CWLog("######### Discovery State #########"); /* reset Discovery state */ gCWDiscoveryCount = 0; CWNetworkCloseSocket(gWTPSocket); if (!CWErr(CWNetworkInitSocketClient(&gWTPSocket, NULL))) { return CW_QUIT; } /* * note: gCWACList can be freed and reallocated (reading from config file) * at each transition to the discovery state to save memory space */ for (i = 0; i < gCWACCount; i++) gCWACList[i].received = CW_FALSE; /* wait a random time */ sleep(CWRandomIntInRange(gCWDiscoveryInterval, gCWMaxDiscoveryInterval)); CW_REPEAT_FOREVER { CWBool sentSomething = CW_FALSE; /* we get no responses for a very long time */ if (gCWDiscoveryCount == gCWMaxDiscoveries) return CW_ENTER_SULKING; /* send Requests to one or more ACs */ for (i = 0; i < gCWACCount; i++) { /* if this AC hasn't responded to us... */ if (!(gCWACList[i].received)) { /* ...send a Discovery Request */ CWProtocolMessage *msgPtr = NULL; /* get sequence number (and increase it) */ gCWACList[i].seqNum = CWGetSeqNum(); if (!CWErr(CWAssembleDiscoveryRequest(&msgPtr, gCWACList[i].seqNum))) { exit(1); } CW_CREATE_OBJECT_ERR(gACInfoPtr, CWACInfoValues, return CW_QUIT; ); CWNetworkGetAddressForHost(gCWACList[i].address, &(gACInfoPtr->preferredAddress)); CWUseSockNtop(&(gACInfoPtr->preferredAddress), CWDebugLog(str); ); j = CWErr(CWNetworkSendUnsafeUnconnected(gWTPSocket, &(gACInfoPtr->preferredAddress), (*msgPtr).msg, (*msgPtr).offset)); /* * log eventual error and continue * CWUseSockNtop(&(gACInfoPtr->preferredAddress), * CWLog("WTP sends Discovery Request to: %s", str);); */ CW_FREE_PROTOCOL_MESSAGE(*msgPtr); CW_FREE_OBJECT(msgPtr); CW_FREE_OBJECT(gACInfoPtr); /* * we sent at least one Request in this loop * (even if we got an error sending it) */ sentSomething = CW_TRUE; }
CWBool CWWTPSendAcknowledgedPacket(int seqNum, CWList msgElemlist, CWBool (assembleFunc)(CWProtocolMessage **, int *, int, int, CWList), CWBool (parseFunc)(char*, int, int, void*), CWBool (saveFunc)(void*), void *valuesPtr) { CWProtocolMessage *messages = NULL; CWProtocolMessage msg; int fragmentsNum = 0, i; struct timespec timewait; int gTimeToSleep = gCWRetransmitTimer; int gMaxTimeToSleep = CW_ECHO_INTERVAL_DEFAULT/2; msg.msg = NULL; if(!(assembleFunc(&messages, &fragmentsNum, gWTPPathMTU, seqNum, msgElemlist))) { goto cw_failure; } gWTPRetransmissionCount= 0; while(gWTPRetransmissionCount < gCWMaxRetransmit) { CWDebugLog("Transmission Num:%d", gWTPRetransmissionCount); for(i = 0; i < fragmentsNum; i++) { #ifdef CW_NO_DTLS if(!CWNetworkSendUnsafeConnected(gWTPSocket, messages[i].msg, messages[i].offset)) #else if(!CWSecuritySend(gWTPSession, messages[i].msg, messages[i].offset)) #endif { CWDebugLog("Failure sending Request"); goto cw_failure; } } timewait.tv_sec = time(0) + gTimeToSleep; timewait.tv_nsec = 0; CW_REPEAT_FOREVER { CWThreadMutexLock(&gInterfaceMutex); if (CWGetCountElementFromSafeList(gPacketReceiveList) > 0) CWErrorRaise(CW_ERROR_SUCCESS, NULL); else { if (CWErr(CWWaitThreadConditionTimeout(&gInterfaceWait, &gInterfaceMutex, &timewait))) CWErrorRaise(CW_ERROR_SUCCESS, NULL); } CWThreadMutexUnlock(&gInterfaceMutex); switch(CWErrorGetLastErrorCode()) { case CW_ERROR_TIME_EXPIRED: { gWTPRetransmissionCount++; goto cw_continue_external_loop; break; } case CW_ERROR_SUCCESS: { /* there's something to read */ if(!(CWReceiveMessage(&msg))) { CW_FREE_PROTOCOL_MESSAGE(msg); CWDebugLog("Failure Receiving Response"); goto cw_failure; } if(!(parseFunc(msg.msg, msg.offset, seqNum, valuesPtr))) { if(CWErrorGetLastErrorCode() != CW_ERROR_INVALID_FORMAT) { CW_FREE_PROTOCOL_MESSAGE(msg); CWDebugLog("Failure Parsing Response"); goto cw_failure; } else { CWErrorHandleLast(); { gWTPRetransmissionCount++; goto cw_continue_external_loop; } break; } } if((saveFunc(valuesPtr))) { goto cw_success; } else { if(CWErrorGetLastErrorCode() != CW_ERROR_INVALID_FORMAT) { CW_FREE_PROTOCOL_MESSAGE(msg); CWDebugLog("Failure Saving Response"); goto cw_failure; } } break; } case CW_ERROR_INTERRUPTED: { gWTPRetransmissionCount++; goto cw_continue_external_loop; break; } default: { CWErrorHandleLast(); CWDebugLog("Failure"); goto cw_failure; break; } } } cw_continue_external_loop: CWDebugLog("Retransmission time is over"); gTimeToSleep<<=1; if ( gTimeToSleep > gMaxTimeToSleep ) gTimeToSleep = gMaxTimeToSleep; } /* too many retransmissions */ return CWErrorRaise(CW_ERROR_NEED_RESOURCE, "Peer Dead"); cw_success: for(i = 0; i < fragmentsNum; i++) { CW_FREE_PROTOCOL_MESSAGE(messages[i]); } CW_FREE_OBJECT(messages); CW_FREE_PROTOCOL_MESSAGE(msg); return CW_TRUE; cw_failure: if(messages != NULL) { for(i = 0; i < fragmentsNum; i++) { CW_FREE_PROTOCOL_MESSAGE(messages[i]); } CW_FREE_OBJECT(messages); } CWDebugLog("Failure"); return CW_FALSE; }
CWBool CWWTPCheckForBindingFrame() { // CWLockSafeList(gFrameList); while (CWGetCountElementFromSafeList(gFrameList) > 0) { CWBindingDataListElement* dataFirstElem = CWRemoveHeadElementFromSafeList(gFrameList, NULL); if (dataFirstElem) { int k; int fragmentsNum = 0; CWProtocolMessage *completeMsgPtr = NULL; if (!CWAssembleDataMessage(&completeMsgPtr, &fragmentsNum, gWTPPathMTU, dataFirstElem->frame, dataFirstElem->bindingValues, #ifdef CW_NO_DTLS CW_PACKET_PLAIN #else (gDtlsSecurity == 1)?CW_PACKET_CRYPT:CW_PACKET_PLAIN /* 0-CW_PACKET_PLAIN, 1-CW_PACKET_CRYPT */ #endif )) { for(k = 0; k < fragmentsNum; k++) { CW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]); } CW_FREE_OBJECT(completeMsgPtr); CW_FREE_PROTOCOL_MESSAGE(*(dataFirstElem->frame)); CW_FREE_OBJECT(dataFirstElem->frame); CW_FREE_OBJECT(dataFirstElem->bindingValues); CW_FREE_OBJECT(dataFirstElem); continue; } for (k = 0; k < fragmentsNum; k++) { #ifndef CW_NO_DTLS if(gDtlsSecurity == 1) { if (!CWSecuritySend(gWTPSession, completeMsgPtr[k].msg, completeMsgPtr[k].offset)) { CWDebugLog("Failure sending Request"); break; //gzm break don't unlockSafeList ??? } } else #endif { if (!CWNetworkSendUnsafeUnconnected(gWTPSocket, &(gACInfoPtr->preferredAddress), completeMsgPtr[k].msg, completeMsgPtr[k].offset)) { CWDebugLog("Failure sending Request"); break; //gzm break don't unlockSafeList ??? } } } for (k = 0; k < fragmentsNum; k++) { CW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]); } CW_FREE_OBJECT(completeMsgPtr); CW_FREE_PROTOCOL_MESSAGE(*(dataFirstElem->frame)); CW_FREE_OBJECT(dataFirstElem->frame); CW_FREE_OBJECT(dataFirstElem->bindingValues); CW_FREE_OBJECT(dataFirstElem); } } CWUnlockSafeList(gFrameList); return CW_TRUE; }
CW_THREAD_RETURN_TYPE CWACipc_with_ac_hostapd(void *arg){ int tmp_WTPIndex = -1; int len; int k; #if defined(LOCALUDP) struct sockaddr_un server; #else #if defined(USEIPV6) struct sockaddr_in6 server; #else struct sockaddr_in server; #endif #endif unsigned char buffer[2048]; int connect_ret; char cmd[10]; CWProtocolMessage* frame=NULL; CWNetworkLev4Address address; CWThreadSetSignals(SIG_BLOCK, 1, SIGALRM); #if defined(LOCALUDP) sock = socket(AF_UNIX, SOCK_DGRAM, 0); #elif defined(NETUDP) #if defined(USEIPV6) bzero(&server, sizeof(server)); sock = socket(AF_INET6,SOCK_DGRAM,IPPROTO_UDP); #else memset(&server, 0, sizeof(server)); sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); #endif #else #if defined(USEIPV6) bzero(&server, sizeof(server)); sock = socket(AF_INET6,SOCK_SEQPACKET,IPPROTO_SCTP); #else memset(&server, 0, sizeof(server)); sock = socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP); #endif #endif if (sock < 0) { CWDebugLog("AC ipc HOSTAPD: Error creating socket"); EXIT_FRAME_THREAD(sock); } CWDebugLog("AC ipc HOSTAPD: Trying to connect to hostapd (AC)..."); #if defined(LOCALUDP) server.sun_family = AF_UNIX; strcpy(server.sun_path, gHostapd_unix_path); unlink(server.sun_path); connect_ret = bind(sock, (struct sockaddr *)&server, strlen(server.sun_path) + sizeof(server.sun_family)); #else #if defined(USEIPV6) server.sin6_family = AF_INET6; server.sin6_port = gHostapd_port; server.sin6_addr = in6addr_any; #else server.sin_family = AF_INET; server.sin_port = gHostapd_port; server.sin_addr.s_addr = INADDR_ANY; #endif connect_ret = bind(sock,(struct sockaddr *)&server,sizeof(server)); #endif if ( connect_ret == -1) { CWDebugLog("AC ipc HOSTAPD: Error connect to socket"); EXIT_FRAME_THREAD(sock); } #if defined(LOCALUDP) #elif defined(NETUDP) #else if (listen(sock, CW_MAX_WTP) < 0){ CWDebugLog("AC ipc HOSTAPD: Error listen "); EXIT_FRAME_THREAD(sock); } #endif int i=0; CWProtocolMessage *completeMsgPtr = NULL; int fragmentsNum = 0; CWMultiHomedSocket *sockPtr = &gACSocket; int dataSocket=0; #if defined(LOCALUDP) struct sockaddr_un client_tmp; client_tmp.sun_family = AF_UNIX; #else #if defined(USEIPV6) struct sockaddr_in6 client_tmp; #else struct sockaddr_in client_tmp; #endif #endif int address_size_tmp = sizeof(client_tmp); for(i=0; i<CW_MAX_WTP; i++){ ch[i].associated = 0; #if defined(LOCALUDP) ch[i].client.sun_family = AF_UNIX; ch[i].address_size = sizeof(struct sockaddr_un); #else #if defined(USEIPV6) ch[i].client.sin6_port = 0; #else ch[i].client.sin_port = 0; #endif #endif } #if defined(LOCALUDP) CWLog("Accept Packet at pipe: %s",gHostapd_unix_path); #elif defined(NETUDP) #if defined(USEIPV6) CWLog("Accept UDP v6 Packet at Port: %d",server.sin6_port); #else CWLog("Accept UDP v4 Packet at Port: %d",server.sin_port); #endif #else #if defined(USEIPV6) CWLog("Accept SCTP v6 Packet at Port: %d",server.sin6_port); #else CWLog("Accept SCTP v4 Packet at Port: %d",server.sin_port); #endif #endif CW_REPEAT_FOREVER { tmp_WTPIndex = -1; len = recvfrom(sock, buffer, 3000, 0, (struct sockaddr *)&client_tmp, &address_size_tmp); #if defined(LOCALUDP) sprintf(client_tmp.sun_path, "%s%c%c%c%c%c",server.sun_path, buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]); #endif if(Exist_WTPs()==0){ send_close_cmd(client_tmp,sizeof(client_tmp)); continue; } if(len <= 0 ) { continue; /* EXIT_FRAME_THREAD(sock) */ } for( i=0; i<CW_MAX_WTP; i++){ #if defined(LOCALUDP) if( strcmp(client_tmp.sun_path,ch[i].client.sun_path)==0 ){ tmp_WTPIndex = i; break; } #else #if defined(USEIPV6) if( (client_tmp.sin6_port == ch[i].client.sin6_port) && (strncmp(client_tmp.sin6_addr.s6_addr,ch[i].client.sin6_addr.s6_addr,16)==0 )){ tmp_WTPIndex = i; } #else if( (client_tmp.sin_port == ch[i].client.sin_port) && (strcmp(inet_ntoa(client_tmp.sin_addr),inet_ntoa(ch[i].client.sin_addr))==0 )){ tmp_WTPIndex = i; } #endif #endif } if( tmp_WTPIndex<0 ){// Client not recognized int wtp_non_associated = GetWTP_not_associated_to_Hostapd (); if( wtp_non_associated >= 0){ if( buffer[0]==CONNECT ){ ch[wtp_non_associated].live = 0; ch[wtp_non_associated].start_set_fase = 0; ch[wtp_non_associated].associated = 1; ch[wtp_non_associated].client = client_tmp; ch[wtp_non_associated].address_size = address_size_tmp; cmd[0] = CONNECT_R; sendto(sock, cmd, 1, 0, (struct sockaddr *)&ch[wtp_non_associated].client, ch[wtp_non_associated].address_size); CWLog("wtp_non_associated:%d",wtp_non_associated); #if defined(LOCALUDP) CWLog("Hostapd_AC Connect: %s", ch[wtp_non_associated].client.sun_path); #else #if defined(USEIPV6) CWLog("Hostapd_AC (v6) Connect: %d", ch[wtp_non_associated].client.sin6_port); #else CWLog("Hostapd_AC (v4) Connect: %s:%d",inet_ntoa(ch[wtp_non_associated].client.sin_addr), ch[wtp_non_associated].client.sin_port); #endif #endif continue; }else{ send_close_cmd(client_tmp,sizeof(client_tmp)); continue; } }else{ send_close_cmd(client_tmp,sizeof(client_tmp)); continue; } }else{ // Client recognized int sig_byte = 1; #if defined(LOCALUDP) sig_byte = 6; //Code #endif if( buffer[0]==DATE_TO_WTP ){ if (gWTPs[tmp_WTPIndex].currentState != CW_ENTER_RUN){ CWDebugLog("AC %d is not in RUN State. The packet was dropped.",i); continue; }else if (len > (gWTPs[tmp_WTPIndex].pathMTU-20)){ CWDebugLog("802.11 data length(%d) > MTU(%d)",len, gWTPs[tmp_WTPIndex].pathMTU); continue; }else{ len = len - sig_byte; CW_CREATE_OBJECT_ERR(frame, CWProtocolMessage, return 0;); CW_CREATE_PROTOCOL_MESSAGE(*frame, len, return 0;); memcpy(frame->msg, buffer + sig_byte , len); frame->offset=len; frame->data_msgType = CW_IEEE_802_11_FRAME_TYPE; if (!CWAssembleDataMessage(&completeMsgPtr, &fragmentsNum, gWTPs[tmp_WTPIndex].pathMTU, frame, NULL, CW_PACKET_PLAIN, 0)){ for(k = 0; k < fragmentsNum; k++){ CW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]); } CW_FREE_OBJECT(completeMsgPtr); CW_FREE_PROTOCOL_MESSAGE(*frame); CW_FREE_OBJECT(frame); continue; } for(k = 0; k < sockPtr->count; k++) { if (sockPtr->interfaces[k].sock == gWTPs[tmp_WTPIndex].socket){ dataSocket = sockPtr->interfaces[k].dataSock; CW_COPY_NET_ADDR_PTR(&address,&(gWTPs[tmp_WTPIndex].dataaddress)); break; } } if (dataSocket == 0){ CWDebugLog("data socket of WTP %d isn't ready."); continue; } for (k = 0; k < fragmentsNum; k++){ if(!CWNetworkSendUnsafeUnconnected( dataSocket, &(address),completeMsgPtr[k].msg,completeMsgPtr[k].offset)){ CWDebugLog("Failure sending Request"); break; } } for (k = 0; k < fragmentsNum; k++){ CW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]); } CW_FREE_OBJECT(completeMsgPtr); CW_FREE_PROTOCOL_MESSAGE(*(frame)); CW_FREE_OBJECT(frame); } }else if( buffer[0]==SET_ADDR ){