int CWWTPSendFrame(unsigned char *buf, int len){ int FRAME_80211_LEN=24; int gRawSockLocal; struct sockaddr_ll addr; if ((gRawSockLocal=socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)))<0) { CWDebugLog("THR FRAME: Error creating socket"); CWExitThread(); } memset(&addr, 0, sizeof(addr)); addr.sll_family = AF_PACKET; // addr.sll_protocol = htons(ETH_P_ALL); // addr.sll_pkttype = PACKET_HOST; addr.sll_ifindex = if_nametoindex("monitor0"); //if_nametoindex(gRadioInterfaceName_0); if ((bind(gRawSockLocal, (struct sockaddr*)&addr, sizeof(addr)))<0) { CWDebugLog("THR FRAME: Error binding socket"); CWExitThread(); } if( send(gRawSockLocal, buf + FRAME_80211_LEN, len - FRAME_80211_LEN,0) < 1 ){ CWDebugLog("Error to send frame on raw socket"); return -1; } CWDebugLog("Send (%d) bytes on raw socket",len - FRAME_80211_LEN); return 1; }
CW_THREAD_RETURN_TYPE CWWTPFreqManager(void *arg) { int recSock, rlen; struct sockaddr_in servaddr, client_addr; socklen_t slen = sizeof(client_addr); char buffer[PACKET_SIZE]; OFDMControlValues* freqValue; int current_chan=0; CWProtocolMessage *completeMsgPtr = NULL; CWThreadSetSignals(SIG_BLOCK, 1, SIGALRM); /* Create an Inet UDP socket for this thread (Receive freq/ack packets) */ if ((recSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { CWDebugLog("Thread Frequency Management: Error creating socket"); CWExitThread(); } /* Set up address structure for server socket */ servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); servaddr.sin_port = htons(SERVER_PORT); /* Binding Socket */ if (bind(recSock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr_in)) < 0) { CWDebugLog("Thread Frequency Management: Binding Socket Error"); close(recSock); CWExitThread(); } CW_REPEAT_FOREVER /* Receive data Loop */ { memset(buffer, 0, PACKET_SIZE); rlen = 0; if ( ( rlen = recvfrom(recSock, buffer, PACKET_SIZE, 0, (struct sockaddr *) &client_addr, &slen) ) > 0 ) { freqValue = (OFDMControlValues*) buffer; current_chan = freqValue->currentChan; if(!CWSetCurrentChannel(current_chan)) { CWLog("Thread Frequency Management: Failed to set current channel value."); continue; } } } CWDebugLog("Thread Frequency Management: Thread ended unexpectedly!!"); close(recSock); CWExitThread(); }
CW_THREAD_RETURN_TYPE CWWTPReceiveFreqStats(void *arg) { int recSock, rlen, k, fragmentsNum = 0; struct sockaddr_in servaddr, client_addr; socklen_t slen = sizeof(client_addr); char buffer[PACKET_SIZE]; CWProtocolMessage *completeMsgPtr = NULL; CWProtocolMessage *data = NULL; CWBindingTransportHeaderValues *bindingValuesPtr = NULL; CWThreadSetSignals(SIG_BLOCK, 1, SIGALRM); /* Create an Inet UDP socket for this thread (Receive freq/ack packets) */ if ( ( recSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) ) < 0 ) { CWDebugLog("Thread Frequency Receive Stats: Error creating socket"); CWExitThread(); } /* Set up address structure for server socket */ servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); servaddr.sin_port = htons(SERVER_PORT); /* Binding Socket */ if ( bind(recSock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr_in)) < 0 ) { CWDebugLog("Thread Frequency Receive Stats: Binding Socket Error"); close(recSock); CWExitThread(); } CW_REPEAT_FOREVER /* Receive data Loop */ { memset(buffer, 0, PACKET_SIZE); fragmentsNum = 0; k = 0; rlen = 0; if ( ( rlen = recvfrom(recSock, buffer, PACKET_SIZE, 0, (struct sockaddr *) &client_addr, &slen) ) > 0 ) { /* Creation of stats/ack message for AC */ CW_CREATE_OBJECT_ERR(data, CWProtocolMessage, return 0;); CW_CREATE_PROTOCOL_MESSAGE(*data, rlen, return 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););
void CWWTPsend_command_to_hostapd_ADD_WLAN(unsigned char *buf, int len) { CWDebugLog("CWWTPsend_command_to_hostapd_ADD_WLAN()"); WAITHOSTAPDADD: if (!connected) { sleep(0.2); goto WAITHOSTAPDADD; } buf[0] = ADD_WLAN; if (sendto(sock, buf, len, 0, (struct sockaddr *)&client, address_size) < 0) { CWDebugLog("Error to send command ADD WLAN on socket"); return; } }
/* * 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 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););
/* @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););
void CWACsend_command_to_hostapd_SET_WTPRINFO(int WTPIndex, char* buf, int len){ buf[0] = SET_WTPRINFO; if( sendto(sock, buf, len, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size)<0 ){ CWDebugLog("Error to send command frame on socket"); return; } }
int init_AC_tap_interface(int WTPIndex) { sprintf(gWTPs[WTPIndex].tap_name,"wtp%d", WTPIndex); gWTPs[WTPIndex].tap_fd = tun_alloc(gWTPs[WTPIndex].tap_name, IFF_TAP | IFF_NO_PI); CWDebugLog("gWTPs[%d].tap_name %s,tap_fd %d",WTPIndex,gWTPs[WTPIndex].tap_name,gWTPs[WTPIndex].tap_fd); return 0; }
void CWWTPsend_command_to_hostapd_SET_ADDR(unsigned char *buf, int len){ if(!connected)return; buf[0] = SET_ADDR; if( sendto(sock, buf, len, 0, (struct sockaddr *)&client, address_size)<0 ){ CWDebugLog("Error to send command frame on socket"); return; } }
// 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; }
int getMacAddr(int sock, char* interface, unsigned char* macAddr){ struct ifreq s; int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); strcpy(s.ifr_name, interface); if(!ioctl(fd, SIOCGIFHWADDR, &s)) memcpy(macAddr, s.ifr_addr.sa_data, MAC_ADDR_LEN); CWDebugLog("\n"); return 1; }
void CWACsend_command_to_hostapd_HAVE_TO_WAIT(int WTPIndex){ char buf[1]; buf[0] = HAVE_TO_WAIT; if( sendto(sock, buf, 1, 0, (struct sockaddr *)&ch[WTPIndex].client, ch[WTPIndex].address_size)<0 ){ CWDebugLog("Error to send command frame on socket"); return; } }
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 CWWTPsend_data_to_hostapd(unsigned char *buf, int len){ if(!connected)return; unsigned char tmp_buf[CW_BUFFER_SIZE]; tmp_buf[0] = DATE_TO_WTP; memcpy(tmp_buf + 1, buf, len); if( sendto(sock,tmp_buf,len+1,0,(struct sockaddr *)&client,address_size)<0 ){ CWDebugLog("Error to send data frame on Unix socket"); return; } }
void CWHandleTimer(CWTimerArg arg) { CWThreadTimerArg *a = (CWThreadTimerArg*)arg; CWThread requestedThreadPtr = *(a->requestedThreadPtr); int signalToRaise = a->signalToRaise; CWThreadSendSignal(requestedThreadPtr, signalToRaise); CWDebugLog("Timer Expired, Sent Signal(%d) to Thread: %d", signalToRaise, requestedThreadPtr); CW_FREE_OBJECT(a->requestedThreadPtr); CW_FREE_OBJECT(a); return; }
int getMacAddr(int sock, char *interface, unsigned char *macAddr) { struct ifreq ethreq; int i; memset(ðreq, 0, sizeof(ethreq)); strncpy(ethreq.ifr_name, interface, IFNAMSIZ); if (ioctl(sock, SIOCGIFHWADDR, ðreq) == -1) { return 0; } for (i = 0; i < MAC_ADDR_LEN; i++) { macAddr[i] = (unsigned char)ethreq.ifr_hwaddr.sa_data[i]; } CWDebugLog("\n"); return 1; }
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); );
int CWGetFragmentID() { static int fragID = 0; int r; if (!CWThreadMutexLock(&gCreateIDMutex)) { CWDebugLog("Error Locking a mutex"); } r = fragID; if (fragID == CW_MAX_FRAGMENT_ID) fragID = 0; else fragID++; CWThreadMutexUnlock(&gCreateIDMutex); return r; }
unsigned int CWGetSeqNum() { static unsigned int seqNum = 0; unsigned int r; if (!CWThreadMutexLock(&gCreateIDMutex)) { CWDebugLog("Error Locking a mutex"); } r = seqNum; if (seqNum == CW_MAX_SEQ_NUM) seqNum = 0; else seqNum++; CWThreadMutexUnlock(&gCreateIDMutex); return r; }
/* * 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); );
/* * Receive a message, that can be fragmented. This is useful not only for the Join State */ CWBool CWReceiveMessage(CWProtocolMessage *msgPtr) { CWList fragments = NULL; int readBytes; char buf[CW_BUFFER_SIZE]; CWBool dataFlag = CW_FALSE; CW_REPEAT_FOREVER { CW_ZERO_MEMORY(buf, CW_BUFFER_SIZE); #ifdef CW_NO_DTLS char *pkt_buffer = NULL; CWLockSafeList(gPacketReceiveList); while (CWGetCountElementFromSafeList(gPacketReceiveList) == 0) CWWaitElementFromSafeList(gPacketReceiveList); pkt_buffer = (char*)CWRemoveHeadElementFromSafeListwithDataFlag(gPacketReceiveList, &readBytes,&dataFlag); CWUnlockSafeList(gPacketReceiveList); CW_COPY_MEMORY(buf, pkt_buffer, readBytes); CW_FREE_OBJECT(pkt_buffer); #else if(!CWSecurityReceive(gWTPSession, buf, CW_BUFFER_SIZE, &readBytes)) {return CW_FALSE;} #endif if(!CWProtocolParseFragment(buf, readBytes, &fragments, msgPtr, &dataFlag, NULL)) { if(CWErrorGetLastErrorCode() == CW_ERROR_NEED_RESOURCE) { // we need at least one more fragment continue; } else { // error CWErrorCode error; error=CWErrorGetLastErrorCode(); switch(error) { case CW_ERROR_SUCCESS: {CWDebugLog("ERROR: Success"); break;} case CW_ERROR_OUT_OF_MEMORY: {CWDebugLog("ERROR: Out of Memory"); break;} case CW_ERROR_WRONG_ARG: {CWDebugLog("ERROR: Wrong Argument"); break;} case CW_ERROR_INTERRUPTED: {CWDebugLog("ERROR: Interrupted"); break;} case CW_ERROR_NEED_RESOURCE: {CWDebugLog("ERROR: Need Resource"); break;} case CW_ERROR_COMUNICATING: {CWDebugLog("ERROR: Comunicating"); break;} case CW_ERROR_CREATING: {CWDebugLog("ERROR: Creating"); break;} case CW_ERROR_GENERAL: {CWDebugLog("ERROR: General"); break;} case CW_ERROR_OPERATION_ABORTED: {CWDebugLog("ERROR: Operation Aborted"); break;} case CW_ERROR_SENDING: {CWDebugLog("ERROR: Sending"); break;} case CW_ERROR_RECEIVING: {CWDebugLog("ERROR: Receiving"); break;} case CW_ERROR_INVALID_FORMAT: {CWDebugLog("ERROR: Invalid Format"); break;} case CW_ERROR_TIME_EXPIRED: {CWDebugLog("ERROR: Time Expired"); break;} case CW_ERROR_NONE: {CWDebugLog("ERROR: None"); break;} } CWDebugLog("~~~~~~"); return CW_FALSE; } } else break; // the message is fully reassembled } 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 ){
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 CWWTPThread_read_data_from_hostapd(void *arg) { /* CWThreadMutexLock(&gRADIO_MAC_mutex); gRADIO_MAC[0]=0xAA; gRADIO_MAC[1]=0xBB; gRADIO_MAC[2]=0xCC; gRADIO_MAC[3]=0xDD; gRADIO_MAC[4]=0xEE; gRADIO_MAC[5]=0xFF; CWThreadMutexUnlock(&gRADIO_MAC_mutex); */ int len; #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[CW_BUFFER_SIZE]; int connect_ret; unsigned char cmd[10]; CWProtocolMessage *frame = NULL; CWBindingDataListElement *listElement = NULL; 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("WTP ipc HOSTAPD: Error creating socket"); EXIT_FRAME_THREAD(sock); } CWDebugLog("WTP ipc HOSTAPD: Trying to connect to hostapd (wtp)..."); #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)); client.sun_family = AF_UNIX; #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("WTP ipc HOSTAPD: Error connect/bind to socket"); EXIT_FRAME_THREAD(sock); } #if defined(LOCALUDP) #elif defined(NETUDP) #else /* 1: Only one daemon Hostapd_WTP at time */ if (listen(sock, 1) < 0) { CWDebugLog("WTP ipc HOSTAPD: Error listen "); EXIT_FRAME_THREAD(sock); } #endif #if defined(LOCALUDP) CWDebugLog("Waiting packet from Hostapd_WTP at Pipe:%s", gHostapd_unix_path); #else CWDebugLog("Waiting packet from Hostapd_WTP at Port:%d", gHostapd_port); #endif client.sin_family = AF_INET; client.sin_addr.s_addr = inet_addr("127.0.0.1"); client.sin_port = htons(6444); address_size = sizeof(client); int sig_byte = 1; #if defined(LOCALUDP) sig_byte += 5; #endif CWDebugLog("Checking if hostapd is started already"); cmd[0] = CONNECT_R; sendto(sock, cmd, 1, 0, (struct sockaddr *)&client, address_size); cmd[0] = WTPRINFO; //Next info to get sendto(sock, cmd, 1, 0, (struct sockaddr *)&client, address_size); CW_REPEAT_FOREVER { len = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&client, &address_size); #if defined(LOCALUDP) sprintf(client.sun_path, "%s%c%c%c%c%c", server.sun_path, buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); #endif if (len <= 0) { EXIT_FRAME_THREAD(sock) } if (connected == 0 && buffer[0] != CONNECT && buffer[0] != WTPRINFO_R) { CWDebugLog("IPC packet - WTP is not in RUN state"); CWWTPsend_command_to_hostapd_CLOSE(cmd, 10); continue; } if (buffer[0] == DATE_TO_AC) { if (!wtpInRunState) continue; if (!extract802_11_Frame(&frame, buffer + sig_byte, len - sig_byte)) { CWLog("THR FRAME: Error extracting a frame"); EXIT_FRAME_THREAD(sock); } CWDebugLog("Send 802.11 management(len:%d) to AC", len - 1); CW_CREATE_OBJECT_ERR(listElement, CWBindingDataListElement, EXIT_FRAME_THREAD(sock); ); listElement->frame = frame; listElement->bindingValues = NULL; listElement->frame->data_msgType = CW_IEEE_802_11_FRAME_TYPE; CWLockSafeList(gFrameList); CWAddElementToSafeListTail(gFrameList, listElement, sizeof(CWBindingDataListElement)); CWUnlockSafeList(gFrameList); } else if (buffer[0] == CONNECT) {
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; } }
int main (int argc, const char * argv[]) { /* Daemon Mode */ pid_t pid; if (argc <= 1) printf("Usage: WTP working_path\n"); if ((pid = fork()) < 0) exit(1); else if (pid != 0) exit(0); else { setsid(); if (chdir(argv[1]) != 0){ printf("chdir Faile\n"); exit(1); } fclose(stdout); } CWStateTransition nextState = CW_ENTER_DISCOVERY; CWLogInitFile(WTP_LOG_FILE_NAME); #ifndef CW_SINGLE_THREAD CWDebugLog("Use Threads"); #else CWDebugLog("Don't Use Threads"); #endif CWErrorHandlingInitLib(); if(!CWParseSettingsFile()){ CWLog("Can't start WTP"); exit(1); } /* Capwap receive packets list */ if (!CWErr(CWCreateSafeList(&gPacketReceiveList))) { CWLog("Can't start WTP"); exit(1); } /* Capwap receive frame list */ if (!CWErr(CWCreateSafeList(&gFrameList))) { CWLog("Can't start WTP"); exit(1); } CWCreateThreadMutex(&gInterfaceMutex); CWSetMutexSafeList(gPacketReceiveList, &gInterfaceMutex); CWSetMutexSafeList(gFrameList, &gInterfaceMutex); CWCreateThreadCondition(&gInterfaceWait); CWSetConditionSafeList(gPacketReceiveList, &gInterfaceWait); CWSetConditionSafeList(gFrameList, &gInterfaceWait); CWLog("Starting WTP..."); CWRandomInitLib(); CWThreadSetSignals(SIG_BLOCK, 1, SIGALRM); if (timer_init() == 0) { CWLog("Can't init timer module"); exit(1); } #ifdef CW_NO_DTLS if( !CWErr(CWWTPLoadConfiguration()) ) { #else if( !CWErr(CWSecurityInitLib()) || !CWErr(CWWTPLoadConfiguration()) ) { #endif CWLog("Can't start WTP"); exit(1); } CWDebugLog("Init WTP Radio Info"); if(!CWWTPInitConfiguration()) { CWLog("Error Init Configuration"); exit(1); } #ifdef SOFTMAC CWThread thread_ipc_with_wtp_hostapd; if(!CWErr(CWCreateThread(&thread_ipc_with_wtp_hostapd, CWWTPThread_read_data_from_hostapd, NULL))) { CWLog("Error starting Thread that receive command and 802.11 frame from hostapd (WTP side)"); exit(1); } #endif CWThread thread_receiveFrame; if(!CWErr(CWCreateThread(&thread_receiveFrame, CWWTPReceiveFrame, NULL))) { CWLog("Error starting Thread that receive binding frame"); exit(1); } CWThread thread_receiveStats; if(!CWErr(CWCreateThread(&thread_receiveStats, CWWTPReceiveStats, NULL))) { CWLog("Error starting Thread that receive stats on monitoring interface"); exit(1); } /**************************************** * 2009 Update: * * Spawn Frequency Stats * * Receiver Thread * ****************************************/ CWThread thread_receiveFreqStats; if(!CWErr(CWCreateThread(&thread_receiveFreqStats, CWWTPReceiveFreqStats, NULL))) { CWLog("Error starting Thread that receive frequency stats on monitoring interface"); exit(1); } /* if AC address is given jump Discovery and use this address for Joining */ if(gWTPForceACAddress != NULL) nextState = CW_ENTER_JOIN; /* start CAPWAP state machine */ CW_REPEAT_FOREVER { switch(nextState) { case CW_ENTER_DISCOVERY: nextState = CWWTPEnterDiscovery(); break; case CW_ENTER_SULKING: nextState = CWWTPEnterSulking(); break; case CW_ENTER_JOIN: nextState = CWWTPEnterJoin(); break; case CW_ENTER_CONFIGURE: nextState = CWWTPEnterConfigure(); break; case CW_ENTER_DATA_CHECK: nextState = CWWTPEnterDataCheck(); break; case CW_ENTER_RUN: nextState = CWWTPEnterRun(); break; case CW_ENTER_RESET: /* * CWStopHeartbeatTimer(); * CWStopNeighborDeadTimer(); * CWNetworkCloseSocket(gWTPSocket); * CWSecurityDestroySession(gWTPSession); * CWSecurityDestroyContext(gWTPSecurityContext); * gWTPSecurityContext = NULL; * gWTPSession = NULL; */ nextState = CW_ENTER_DISCOVERY; break; case CW_QUIT: CWWTPDestroy(); return 0; } } } __inline__ unsigned int CWGetSeqNum() { static unsigned int seqNum = 0; if (seqNum==CW_MAX_SEQ_NUM) seqNum=0; else seqNum++; return seqNum; } __inline__ int CWGetFragmentID() { static int fragID = 0; return fragID++; } /* * Parses config file and inits WTP configuration. */ CWBool CWWTPLoadConfiguration() { int i; CWLog("WTP Loads Configuration"); /* get saved preferences */ if(!CWErr(CWParseConfigFile())) { CWLog("Can't Read Config File"); exit(1); } if(gCWACCount == 0) return CWErrorRaise(CW_ERROR_NEED_RESOURCE, "No AC Configured"); CW_CREATE_ARRAY_ERR(gCWACList, gCWACCount, CWACDescriptor, return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);); for(i = 0; i < gCWACCount; i++) { CWDebugLog("Init Configuration for AC at %s", gCWACAddresses[i]); CW_CREATE_STRING_FROM_STRING_ERR(gCWACList[i].address, gCWACAddresses[i], return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);); }
/* * 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; }