static void CommandPingHandler(TCPIP_NET_HANDLE hNetIf, IPV4_ADDR * remoteIP, void * data) { char addBuff[20]; if(icmpCmdStat == TCPIP_PING_CMD_IDLE) { return; // not our reply? } uint16_t* pReply = (uint16_t*)data; uint16_t myRecvId = *pReply; uint16_t myRecvSequenceNumber = *(pReply + 1); if (myRecvSequenceNumber != icmpSequenceNo || myRecvId != icmpIdentifier) { (*pIcmpCmd->pCmdApi->msg)(icmpCmdIoParam, "Ping: wrong reply received\r\n"); } else { uint32_t pingTicks = SYS_TICK_Get() - icmpStartTick; int pingMs = (pingTicks * 1000) / SYS_TICK_ResolutionGet(); if(pingMs == 0) { pingMs = 1; } TCPIP_Helper_IPAddressToString(remoteIP, addBuff, sizeof(addBuff)); (*pIcmpCmd->pCmdApi->print)(icmpCmdIoParam, "Ping: reply from %s: time = %dms\r\n", addBuff, pingMs); icmpAckRecv++; } }
/***************************************************************************** Function: bool DNSClientInit(const TCPIP_STACK_MODULE_CTRL* const stackData, const DNS_CLIENT_MODULE_GONFIG* const dnsData); Summary: Initializes the DNS module. Description: This function perform the initialization of the DNS client module. It has to be called before any other operation with the DNS client is possible. Precondition: Stack is initialized. Parameters: stackData - stack initialization data dnsData - DNS client module specific initialization data Return Values: true - the initialization was performed OK and the module is ready to be used false - The DNS module initialization failed. Remarks: None ***************************************************************************/ bool DNSClientInit(const TCPIP_STACK_MODULE_CTRL* const stackData, const DNS_CLIENT_MODULE_GONFIG* const dnsData) { if(stackData->stackAction == TCPIP_STACK_ACTION_IF_UP) { // interface restart return true; } // stack start up if(dnsInitCount != 0) { // initialize just once dnsInitCount++; return true; } // 1st time init smDNS = DNS_IDLE; Flags.Val = 0; DNSSocket = INVALID_UDP_SOCKET; #if DNS_CLIENT_VERSION_NO >= 2 if(dnsTimerHandle == 0) { // once per service dnsTimerHandle = SYS_TICK_TimerCreate(DNSTmoHandler); if(dnsTimerHandle) { dnsTickPending = 0; SYS_TICK_TimerSetRate(dnsTimerHandle, (SYS_TICK_ResolutionGet() * DNS_CLIENT_TASK_PROCESS_RATE)/1000); } else { return false; } } #endif // DNS_CLIENT_VERSION_NO >= 2 dnsInitCount++; return true; }
void TCPIPCommandsTask(void) { ICMP_ECHO_RESULT echoRes; DNS_RESULT dnsRes; bool killIcmp = false; switch(icmpCmdStat) { case TCPIP_PING_CMD_DNS_GET: dnsRes = TCPIP_DNS_UsageBegin(0); if(dnsRes == DNS_RES_OK) { TCPIP_DNS_Resolve(icmpTargetHost, DNS_TYPE_A); icmpCmdStat = TCPIP_PING_CMD_DNS_WAIT; } else if(dnsRes != DNS_RES_BUSY) { // some other error (*pIcmpCmd->pCmdApi->print)(icmpCmdIoParam, "Ping: DNS failure for %s\r\n", icmpTargetHost); killIcmp = true; } // else wait some more break; case TCPIP_PING_CMD_DNS_WAIT: dnsRes = TCPIP_DNS_IsResolved(icmpTargetHost, &icmpTargetAddr); if(dnsRes == DNS_RES_OK || dnsRes < 0) { TCPIP_DNS_UsageEnd(0); if(dnsRes == DNS_RES_OK) { TCPIP_Helper_IPAddressToString(&icmpTargetAddr, icmpTargetAddrStr, sizeof(icmpTargetAddrStr)); icmpCmdStat = TCPIP_PING_CMD_DO_PING; } else { (*pIcmpCmd->pCmdApi->print)(icmpCmdIoParam, "Ping: DNS failure for %s\r\n", icmpTargetHost); killIcmp = true; } } // else (dnsRes > 0 ); wait some more break; case TCPIP_PING_CMD_DO_PING: if(icmpReqCount != 0 && icmpAckRecv == 0) { // no reply received; if(SYS_TICK_Get() - icmpStartTick > (SYS_TICK_ResolutionGet() * TCPIP_STACK_COMMANDS_ICMP_ECHO_TIMEOUT) / 1000) { // timeout (*pIcmpCmd->pCmdApi->print)(icmpCmdIoParam, "Ping: request timeout.\r\n"); killIcmp = true; break; } // else wait some more } if(icmpReqCount == icmpReqNo) { // no more requests to send killIcmp = true; break; } // send another request echoRes = TCPIP_ICMP_EchoRequestSend (&icmpTargetAddr, ++icmpSequenceNo, icmpIdentifier); if(echoRes >= 0 ) { icmpStartTick = SYS_TICK_Get(); if(icmpReqCount++ == 0) { (*pIcmpCmd->pCmdApi->print)(icmpCmdIoParam, "Ping: request sent to: %s [%s]\r\n", icmpTargetHost, icmpTargetAddrStr); } } else { (*pIcmpCmd->pCmdApi->print)(icmpCmdIoParam, "Ping: failed to send request to: %s\r\n", icmpTargetAddrStr); killIcmp = true; } break; default: killIcmp = true; break; } if(killIcmp) { _PingStop(pIcmpCmd, icmpCmdIoParam); } }
/***************************************************************************** Function: void ARPInitialize(const TCPIP_STACK_MODULE_CTRL* const stackCtrl, const ARP_MODULE_CONFIG* const arpData) Summary: Initializes the ARP module. Description: Initializes the ARP module. Calls can be done with the request of not tearing down the ARP cache This helps for ifup/ifdown sequences. Of course, if this is the case the memory allocated for the ARP cache has to be from a persistent heap. Precondition: None Parameters: stackCtrl - stack initialization parameters arpData - ARP specific initialization parameters Returns: true if initialization succeded, false otherwise Remarks: ***************************************************************************/ bool ARPInitialize(const TCPIP_STACK_MODULE_CTRL* const stackCtrl, const ARP_MODULE_CONFIG* const arpData) { OA_HASH_DCPT* cacheDcpt; ARP_CACHE_DCPT* pArpDcpt; size_t memSize; bool newCache; if(stackCtrl->stackAction == TCPIP_STACK_ACTION_IF_UP) { // interface going up return true; } // stack going up pArpDcpt = arpCache + stackCtrl->netIx; // store the delete option for de-initialization pArpDcpt->deleteOld = arpData->deleteOld; if(arpData->deleteOld) { // remove the old stuff, if there _ARPCleanupCache(pArpDcpt); } // else do not re-initialize if(pArpDcpt->cacheDcpt == 0) { // some initialization to be done // allocate hash + descriptor contiguously memSize = sizeof(OA_HASH_DCPT) + arpData->cacheEntries * sizeof(ARP_HASH_ENTRY); cacheDcpt = (OA_HASH_DCPT*)(*stackCtrl->mallocCallback)(stackCtrl->memH, memSize); if(cacheDcpt == 0) { // failed return false; } newCache = true; // populate the entries cacheDcpt->memBlk = cacheDcpt + 1; cacheDcpt->hEntrySize = sizeof(ARP_HASH_ENTRY); cacheDcpt->hEntries = arpData->cacheEntries; cacheDcpt->probeStep = ARP_HASH_PROBE_STEP; OAHashInit(cacheDcpt); pArpDcpt->cacheDcpt = cacheDcpt; SingleListInit(&pArpDcpt->permList); SingleListInit(&pArpDcpt->completeList); SingleListInit(&pArpDcpt->incompleteList); pArpDcpt->purgeThres = (ARP_CACHE_PURGE_THRESHOLD * pArpDcpt->cacheDcpt->hEntries)/100; pArpDcpt->purgeQuanta = ARP_CACHE_PURGE_QUANTA; } else { // didn't create anything now newCache = false; } if(arpTimerHandle == 0) { // once per service SingleListInit(&arpRegisteredUsers); // store the memory allocation handle arpMemH = stackCtrl->memH; arpTimerHandle = SYS_TICK_TimerCreate(ARPTmoHandler); if(arpTimerHandle) { arpTickPending = arpTimeSeconds = 0; SYS_TICK_TimerSetRate(arpTimerHandle, SYS_TICK_ResolutionGet() * ARP_TASK_PROCESS_RATE); } else { // failed if(newCache) { _ARPCleanupCache(pArpDcpt); } return false; } } pArpDcpt->inited = true; return true; }
/***************************************************************************** Function: void PingDemoTask (void) Summary: Handles state machine for ping demo processes. Description: This function performs state processing for the ping demo. This function can be used as a model for applications requiring Ping6 capabilities to check if a host is reachable. Precondition: None. Parameters: None Returns: None ***************************************************************************/ void PingDemoTask (void) { switch (pingState) { #if defined (TCPIP_STACK_USE_ICMP_CLIENT) case STATE_DNS_SEND_QUERY_IPV4: if (!DNSBeginUsage(pNetIf)) return; if (DNSResolve((const char *)targetHostName, DNS_TYPE_A) != DNS_RES_OK) return; pingTimer = SYS_TICK_Get() + (SYS_TICK_ResolutionGet() * TCPIP_PING_DNS_TIMEOUT); pingState = STATE_DNS_GET_RESPONSE_IPV4; break; case STATE_DNS_GET_RESPONSE_IPV4: { DNS_RESULT res; if ((long)(SYS_TICK_Get() - pingTimer) > 0) { SYS_OUT_MESSAGE_LINE("Couldn't resolve", 2); DNSEndUsage(pNetIf); pingState = STATE_IDLE; return; } res = DNSIsResolved((const char *)targetHostName, &targetAddressIPv4); switch (res) { case DNS_RES_OK: DNSEndUsage(pNetIf); pingState = STATE_RESOLVE_ARP; break; case DNS_RES_PENDING: break; default: SYS_OUT_MESSAGE_LINE ("Couldn't resolve", 1); DNSEndUsage(pNetIf); pingState = STATE_IDLE; break; } } break; case STATE_RESOLVE_ARP: if ((targetAddressIPv4.Val & pNetIf->MyMask.Val) == pNetIf->MyMask.Val) firstHopAddress.Val = targetAddressIPv4.Val; else firstHopAddress.Val = pNetIf->MyGateway.Val; ARPResolve(pNetIf, &firstHopAddress); pingTimer = SYS_TICK_Get(); pingState = STATE_ARP_RESOLVED; break; case STATE_ARP_RESOLVED: if(!ARPIsResolved(pNetIf, &firstHopAddress, &targetMACAddr)) { if(SYS_TICK_Get() - pingTimer > (TCPIP_PING_DNS_TIMEOUT * SYS_TICK_TicksPerSecondGet())) { SYS_OUT_MESSAGE_LINE ("Couldn't ARP", 1); pingState = STATE_IDLE; } break; } pingState = STATE_SEND_ECHO_REQUEST_IPV4; break; #endif #if defined (TCPIP_STACK_USE_IPV6) case STATE_DNS_SEND_QUERY_IPV6: if (!DNSBeginUsage(pNetIf)) return; if (DNSResolve((const char *)targetHostName, DNS_TYPE_AAAA) != DNS_RES_OK) return; pingTimer = SYS_TICK_Get() + (SYS_TICK_ResolutionGet() * TCPIP_PING_DNS_TIMEOUT); pingState = STATE_DNS_GET_RESPONSE_IPV6; break; case STATE_DNS_GET_RESPONSE_IPV6: { DNS_RESULT res; if ((long)(SYS_TICK_Get() - pingTimer) > 0) { SYS_OUT_MESSAGE_LINE ("Couldn't resolve", 1); DNSEndUsage(pNetIf); pingState = STATE_IDLE; return; } res = DNSIsResolved((const char *)targetHostName, &targetAddressIPv6); switch (res) { case DNS_RES_OK: DNSEndUsage(pNetIf); pingState = STATE_SEND_ECHO_REQUEST_IPV6; break; case DNS_RES_PENDING: break; default: SYS_OUT_MESSAGE_LINE ("Couldn't resolve", 1); DNSEndUsage(pNetIf); pingState = STATE_IDLE; break; } } break; #endif #if defined(TCPIP_STACK_USE_ICMP_CLIENT) case STATE_SEND_ECHO_REQUEST_IPV4: { NODE_INFO info; info.IPAddr = targetAddressIPv4; memcpy (&info.MACAddr, &targetMACAddr, sizeof (MAC_ADDR)); ICMPSendEchoRequest (&info, ++wICMPSequenceNumber, 0xBEEF); // Record the current time. This will be used as a basis for // finding the echo response time, which exludes the ARP and DNS // steps pingTimer = SYS_TICK_Get(); pingCount++; SYS_OUT_MESSAGE_LINE ("Pinging...", 1); // Echo sent, advance state pingState = STATE_GET_RESPONSE_IPV4; } break; #endif #if defined (TCPIP_STACK_USE_IPV6) case STATE_SEND_ECHO_REQUEST_IPV6: { IP_PACKET * pkt; IPV6_ADDR_STRUCT * localAddress; localAddress = TCPIP_IPV6_DAS_SelectSourceAddress (pNetIf, &targetAddressIPv6, NULL); if (localAddress == NULL) { SYS_OUT_MESSAGE_LINE ("No local addr!", 1); pingState = STATE_IDLE; break; } pkt = TCPIP_ICMPV6_PutHeaderEchoRequest (pNetIf, &localAddress->address, &targetAddressIPv6, ICMPV6_INFO_ECHO_REQUEST, 0xEFBE, ++wICMPSequenceNumber); if (TCPIP_IP_IsTxPutReady(pkt, 4) < 4) { TCPIP_IP_FreePacket (pkt); return; } TCPIP_IP_PutArray (pkt, (uint8_t *)&miscData, sizeof (uint32_t)); // Just let the IPv6 module figure out the next hop neighbor and its MAC address TCPIP_ICMPV6_Flush (pkt); // Record the current time. This will be used as a basis for // finding the echo response time, which exludes the ARP and DNS // steps pingTimer = SYS_TICK_Get(); pingCount++; SYS_OUT_MESSAGE_LINE ("Pinging...", 1); // Echo sent, advance state pingState = STATE_GET_RESPONSE_IPV6; } break; #endif #if defined (TCPIP_STACK_USE_ICMP_CLIENT) case STATE_GET_RESPONSE_IPV4: if ((long)(SYS_TICK_Get() - pingTimer) > (SYS_TICK_ResolutionGet() * TCPIP_PING_TIMEOUT)) { SYS_OUT_MESSAGE_LINE("Ping timeout", 1); pingState = STATE_IDLE; } break; #endif #if defined (TCPIP_STACK_USE_IPV6) case STATE_GET_RESPONSE_IPV6: if ((long)(SYS_TICK_Get() - pingTimer) > (SYS_TICK_ResolutionGet() * TCPIP_PING_TIMEOUT)) { SYS_OUT_MESSAGE_LINE ("Ping timeout", 1); pingState = STATE_IDLE; } break; #endif default: case STATE_IDLE: break; } }