/**************************************************************************** Function: void ChipKITEthernetBegin(const BYTE *rgbMac, const BYTE *rgbIP, const BYTE *rgbGateWay, const BYTE *rgbSubNet, const BYTE *rgbDNS1, const BYTE *rgbDNS2) Description: This routine impements the Arduino Ethernet.Begin Method. This initializes the board, start supporting tasks, builds a default application configuration data structure, overrides the configuration structure if static IPs or assigned MACs are specified, and starts the Ethernet stack. Precondition: None Parameters: rgbMac - If all 6 bytes are zero, than use the internal MCU programed MAC address as defined by Microchip. It will be a unique MAC address in the Microchip range. The range will be somewhere starting with 00:04:A3:XX:XX:XX If non-zero, the specified MAC address will be used. rgbIP - If all 4 bytes are zero, then DHCP is used and rest of the parameters are ignored If an IP is specified then DHCP is not used and the IP represents a static IP address to use. The remainng parameters have value. rgbGateWay - 4 bytes IP address of the gateway to use. Only valid if rgbIP is specified rgbSubNet - 4 byte mask representing the subnet mask.Only valid if rgbIP is specified rgbDNS1 - 4 byte IP address of the primary DNS server. Only valid if rgbIP is specified. This value may be 0s if not required rgbDNS2 - 4 byte IP address of the secondary DNS server. Only valid if rgbIP is specifed. This value may be 0s if not required Returns: None Remarks: None ***************************************************************************/ void ChipKITEthernetBegin(const BYTE *rgbMac, const BYTE *rgbIP, const BYTE *rgbGateWay, const BYTE *rgbSubNet, const BYTE *rgbDNS1, const BYTE *rgbDNS2) { DWORD t = 0; const DWORD tDHCPTimeout = 30 * TICK_SECOND; // Initialize application specific hardware InitializeBoard(); // Initialize stack-related hardware components that may be // required by the UART configuration routines TickInit(); // Initialize Stack and application related NV variables into AppConfig. InitAppConfig(); // see if we have something other than to use our MAC address if((rgbMac[0] | rgbMac[1] | rgbMac[2] | rgbMac[3] | rgbMac[4] | rgbMac[5]) != 0) { memcpy(&AppConfig.MyMACAddr, rgbMac, 6); } // if we are not to use DHCP; fill in what came in. if((rgbIP[0] | rgbIP[1] | rgbIP[2] | rgbIP[3]) != 0) { AppConfig.Flags.bIsDHCPEnabled = FALSE; // don't use dhcp memcpy(&AppConfig.MyIPAddr, rgbIP, 4); memcpy(&AppConfig.MyGateway, rgbGateWay, 4); memcpy(&AppConfig.MyMask,rgbSubNet, 4); memcpy(&AppConfig.PrimaryDNSServer, rgbDNS1, 4); memcpy(&AppConfig.SecondaryDNSServer, rgbDNS2, 4); AppConfig.DefaultIPAddr = AppConfig.MyIPAddr; AppConfig.DefaultMask = AppConfig.MyMask; } // make sure our static array is zeroed out. memset(rgUDPSocketBuffers, 0, sizeof(rgUDPSocketBuffers)); // Initialize core stack layers (MAC, ARP, TCP, UDP) and // application modules (HTTP, SNMP, etc.) StackInit(); // arp will not work right until DHCP finishes // if DHCP won't configure after the timeout; then just go with it // maybe later it will configure, but until then, things might not work right. t = TickGet(); while(AppConfig.Flags.bIsDHCPEnabled && !DHCPIsBound(0) && ((TickGet() - t) < tDHCPTimeout)) { ChipKITPeriodicTasks(); } }
void AutoIPDisable (BYTE vInterface) { LoadState (vInterface); AutoIPClient.flags.bits.gDisableAutoIP = TRUE; #if defined (STACK_USE_DHCP_CLIENT) if (!DHCPIsBound(vInterface)) { AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; } #else AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; #endif }
void AutoIPDisable (NET_CONFIG* pConfig) { LoadState(_TCPIPStackNetIx(pConfig)); AutoIPClient.flags.bits.gDisableAutoIP = true; #if defined (TCPIP_STACK_USE_DHCP_CLIENT) if (!DHCPIsBound(pConfig)) { pConfig->MyIPAddr.Val = pConfig->DefaultIPAddr.Val; pConfig->MyMask.Val = pConfig->DefaultMask.Val; } #else pConfig->MyIPAddr.Val = pConfig->DefaultIPAddr.Val; pConfig->MyMask.Val = pConfig->DefaultMask.Val; #endif }
/***************************************************************************** * * check_network_connected * * \param None * * \return TRUE if network ready, FALSE if not * * \brief Checks to see that network is still connected. * *****************************************************************************/ unsigned char check_network_connected(void) { int network_connected = 0; if (WFisConnected() != TRUE) { LED1_IO = 0; LED2_IO = 0; network_connected = 0; if (CFGCXT.type != WF_SOFT_AP && AppConfig.networkType == WF_INFRASTRUCTURE && network_connected == 0) { if (task_delay(TICK_MINUTE, 1)) wifi_fail_count++; } } if (DHCPIsBound(0)) network_connected = 1; else network_connected = 0; if (tcp_fail_count > 5 || unknown_status > 5) { LED1_IO = 0; LED2_IO = 0; } if (wifi_fail_count > 2) { wifi_fail_count = 0; // Reset(); } if (tcp_fail_count > 50 || unknown_status > 50) { tcp_fail_count = 0; unknown_status = 0; wifi_fail_count = 0; network_connected = 0; // Reset(); } return network_connected; }
void Command() { switch (Cmd_Read_Switch) { case 0 : if(UDPIsGetReady(socket2)) { SuccesFull_Read = UDPGetArray(Cmd, 0x3); if (Cmd[0] == Enter || Cmd[0] == 0 || SuccesFull_Read < 3) { Cmd_Read_Switch = 0; Cmd[0] = 0; break; } else if (Cmd[2] == Enter) { Cmd_Read_Switch = 0; Command_Exe(Cmd); } Cmd_Read_Switch = 0; Cmd[0] = 0; Cmd[1] = 0; Cmd[2] = 0; break; } break; case 20 : if(!MACIsLinked()) { return; } #if defined(STACK_USE_DHCP_CLIENT) { static DWORD dwTimer = 0; // Wait until DHCP module is finished if(!DHCPIsBound(0)) { dwTimer = TickGet(); return; } // Wait an additional half second after DHCP is finished to let the announce module and any other stack state machines to reach normal operation if(TickGet() - dwTimer < TICK_SECOND/2) return; } #endif Cmd_Read_Switch = 21; break; case 21 : socket2 = UDPOpen(0x6FFF, NULL, 0x6FFF); //open the socket if(socket2 == 0xFF) //Invalid socket { break; } else{Cmd_Read_Switch = 0;} Led1=1; Output_Enable = 1; break; default : break; } }
/********************************************************************* * Function: void StackTask(void) * * PreCondition: StackInit() is already called. * * Input: None * * Output: Stack FSM is executed. * * Side Effects: None * * Note: This FSM checks for new incoming packets, * and routes it to appropriate stack components. * It also performs timed operations. * * This function must be called periodically to * ensure timely responses. * ********************************************************************/ void StackTask(void) { WORD dataCount; IP_ADDR tempLocalIP; BYTE cFrameType; BYTE cIPFrameType; #if defined( WF_CS_TRIS ) // This task performs low-level MAC processing specific to the MRF24WB0M MACProcess(); #if defined( STACK_USE_EZ_CONFIG ) && !defined(__18CXX) WFEasyConfigMgr(); #endif #if defined(STACK_USE_DHCP_CLIENT) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if(AppConfig.Flags.bIsDHCPEnabled) { if(g_DhcpRenew == TRUE) { g_DhcpRenew = FALSE; AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; AppConfig.Flags.bInConfigMode = TRUE; DHCPInit(0); } // DHCP must be called all the time even after IP configuration is // discovered. // DHCP has to account lease expiration time and renew the configuration // time. DHCPTask(); if(DHCPIsBound(0)) AppConfig.Flags.bInConfigMode = FALSE; } #endif // STACK_USE_DHCP_CLIENT #endif #if defined(STACK_USE_DHCP_CLIENT) && !defined(WF_CS_TRIS) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if(AppConfig.Flags.bIsDHCPEnabled) { static BOOL bLastLinkState = FALSE; BOOL bCurrentLinkState; bCurrentLinkState = MACIsLinked(); if(bCurrentLinkState != bLastLinkState) { bLastLinkState = bCurrentLinkState; if(!bCurrentLinkState) { AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; AppConfig.Flags.bInConfigMode = TRUE; DHCPInit(0); } } // DHCP must be called all the time even after IP configuration is // discovered. // DHCP has to account lease expiration time and renew the configuration // time. DHCPTask(); if(DHCPIsBound(0)) AppConfig.Flags.bInConfigMode = FALSE; } #endif #if defined (STACK_USE_AUTO_IP) AutoIPTasks(); #endif #if defined(STACK_USE_TCP) // Perform all TCP time related tasks (retransmit, send acknowledge, close connection, etc) TCPTick(); #endif #if defined(STACK_USE_UDP) UDPTask(); #endif // Process as many incomming packets as we can while(1) { //if using the random module, generate entropy #if defined(STACK_USE_RANDOM) RandomAdd(remoteNode.MACAddr.v[5]); #endif // We are about to fetch a new packet, make sure that the // UDP module knows that any old RX data it has laying // around will now be gone. #if defined(STACK_USE_UDP) UDPDiscard(); #endif // Fetch a packet (throws old one away, if not thrown away // yet) if(!MACGetHeader(&remoteNode.MACAddr, &cFrameType)) break; // When using a WiFi module, filter out all incoming packets that have // the same source MAC address as our own MAC address. This is to // prevent receiving and passing our own broadcast packets up to other // layers and avoid, for example, having our own gratuitous ARPs get // answered by ourself. #if defined(WF_CS_TRIS) if(memcmp((void*)&remoteNode.MACAddr, (void*)&AppConfig.MyMACAddr, 6) == 0u) continue; #endif // Dispatch the packet to the appropriate handler switch(cFrameType) { case MAC_ARP: ARPProcess(); break; case MAC_IP: if(!IPGetHeader(&tempLocalIP, &remoteNode, &cIPFrameType, &dataCount)) break; #if defined(STACK_USE_ICMP_SERVER) || defined(STACK_USE_ICMP_CLIENT) if(cIPFrameType == IP_PROT_ICMP) { #if defined(STACK_USE_IP_GLEANING) if(AppConfig.Flags.bInConfigMode && AppConfig.Flags.bIsDHCPEnabled) { // According to "IP Gleaning" procedure, // when we receive an ICMP packet with a valid // IP address while we are still in configuration // mode, accept that address as ours and conclude // configuration mode. if(tempLocalIP.Val != 0xffffffff) { AppConfig.Flags.bInConfigMode = FALSE; AppConfig.MyIPAddr = tempLocalIP; } } #endif // Process this ICMP packet if it the destination IP address matches our address or one of the broadcast IP addressees if( (tempLocalIP.Val == AppConfig.MyIPAddr.Val) || (tempLocalIP.Val == 0xFFFFFFFF) || #if defined(STACK_USE_ZEROCONF_LINK_LOCAL) || defined(STACK_USE_ZEROCONF_MDNS_SD) (tempLocalIP.Val == 0xFB0000E0) || #endif (tempLocalIP.Val == ((AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val) | ~AppConfig.MyMask.Val))) { ICMPProcess(&remoteNode, dataCount); } break; } #endif #if defined(STACK_USE_TCP) if(cIPFrameType == IP_PROT_TCP) { TCPProcess(&remoteNode, &tempLocalIP, dataCount); break; } #endif #if defined(STACK_USE_UDP) if(cIPFrameType == IP_PROT_UDP) { // Stop processing packets if we came upon a UDP frame with application data in it if(UDPProcess(&remoteNode, &tempLocalIP, dataCount)) return; } #endif break; } } }
/***************************************************************************** Function: void UDPPerformanceTask(void) Summary: Tests the transmit performance of the UDP module. Description: This function tests the transmit performance of the UDP module. At boot, this module will transmit 1024 large UDP broadcast packets of 1024 bytes each. Using a packet sniffer, one can determine how long this process takes and calculate the transmit rate of the stack. This function tests true UDP performance in that it will open a socket, transmit one packet, and close the socket for each loop. After this initial transmission, the module can be re-enabled by holding button 3. This function is particularly useful after development to determine the impact of your application code on the stack's performance. A before and after comparison will indicate if your application is unacceptably blocking the processor or taking too long to execute. Precondition: UDP is initialized. Parameters: None Returns: None ***************************************************************************/ void UDPPerformanceTask(void) { UDP_SOCKET MySocket; NODE_INFO Remote; WORD wTemp; static DWORD dwCounter = 1; if((BUTTON3_IO) && (dwCounter > 1024u)) return; // Suppress transmissions if we don't have an Ethernet link so our counter starts correctly at 0x00000001 if(!MACIsLinked()) return; #if defined(STACK_USE_DHCP_CLIENT) && defined(DELAY_UDP_PERFORMANCE_TEST) { static DWORD dwTimer = 0; // Wait until DHCP module is finished if(!DHCPIsBound(0)) { dwTimer = TickGet(); return; } // Wait an additional half second after DHCP is finished to let the announce module and any other stack state machines to reach normal operation if(TickGet() - dwTimer < TICK_SECOND/2) return; } #endif // Set the socket's destination to be a broadcast over our IP // subnet // Set the MAC destination to be a broadcast memset(&Remote, 0xFF, sizeof(Remote)); // Open a UDP socket for outbound transmission MySocket = UDPOpen(0, &Remote, PERFORMANCE_PORT); // Abort operation if no UDP sockets are available // If this ever happens, incrementing MAX_UDP_SOCKETS in // StackTsk.h may help (at the expense of more global memory // resources). if(MySocket == INVALID_UDP_SOCKET) return; // Make certain the socket can be written to if(!UDPIsPutReady(MySocket)) { UDPClose(MySocket); return; } // Put counter value into first 4 bytes of the packet UDPPutArray((BYTE*)&dwCounter, sizeof(dwCounter)); dwCounter++; wTemp = UDPPutROMArray((ROM BYTE*) "The quick brown fox tried to jump over the yellow dog. Unfortunately, the yellow dog stood up while the fox was in mid-jump. As a result, the two collided. Then, the dog, being the omnivore that it is, ate the quick brown fox. This line is 256 bytes.\r\n" "The quick brown fox tried to jump over the yellow dog. Unfortunately, the yellow dog stood up while the fox was in mid-jump. As a result, the two collided. Then, the dog, being the omnivore that it is, ate the quick brown fox. This line is 256 bytes.\r\n" "The quick brown fox tried to jump over the yellow dog. Unfortunately, the yellow dog stood up while the fox was in mid-jump. As a result, the two collided. Then, the dog, being the omnivore that it is, ate the quick brown fox. This line is 256 bytes.\r\n" "The quick brown fox tried to jump over the yellow dog. Unfortunately, the yellow dog stood up while the fox was in mid-jump. As a result, the two collided. Then, the dog, being the omnivore that it is, ate the quick brown fox. This line is 252b. \r\n", 1020); // Send the packet UDPFlush(); // Close the socket so it can be used by other modules UDPClose(MySocket); }
/** * This FSM checks for new incoming packets, and routes it to appropriate * stack components. It also performs timed operations. * * This function must be called periodically called * to make sure that timely response. * * @preCondition StackInit() is already called. * * side affect: Stack FSM is executed. */ void StackTask(void) { static WORD dataCount; #if defined(STACK_USE_ICMP) static BYTE data[MAX_ICMP_DATA_LEN]; static WORD ICMPId; static WORD ICMPSeq; #endif IP_ADDR destIP; //Is filled with the Destination IP address contained in the IP header union { BYTE MACFrameType; BYTE IPFrameType; ICMP_CODE ICMPCode; } type; BOOL lbContinue; do { lbContinue = FALSE; switch(smStack) { case SM_STACK_IDLE: case SM_STACK_MAC: //debugPutGenRomStr(2, (ROM char*)"1"); //@mxd:2:%s //Check if the MAC RX Buffer has any data, and if it does, read the header. //Get the next header from the NIC. The node who sent it's address will be copied to //'remoteNode.MACAddr'. //Header was NOT read if MACGetHeader returned FALSE if ( !MACGetHeader(&remoteNode.MACAddr, &type.MACFrameType) ) { //debugPutGenRomStr(2, (ROM char*)"2"); //@mxd:2:%s //MODIFIED DHCP BEGIN // ADDED #if defined(STACK_USE_DHCP) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if(STACK_IS_DHCP_ENABLED) { if(!MACIsLinked()) { AppConfig.MyIPAddr.v[0] = MY_DEFAULT_IP_ADDR_BYTE1; AppConfig.MyIPAddr.v[1] = MY_DEFAULT_IP_ADDR_BYTE2; AppConfig.MyIPAddr.v[2] = MY_DEFAULT_IP_ADDR_BYTE3; AppConfig.MyIPAddr.v[3] = MY_DEFAULT_IP_ADDR_BYTE4; AppConfig.MyMask.v[0] = MY_DEFAULT_MASK_BYTE1; AppConfig.MyMask.v[1] = MY_DEFAULT_MASK_BYTE2; AppConfig.MyMask.v[2] = MY_DEFAULT_MASK_BYTE3; AppConfig.MyMask.v[3] = MY_DEFAULT_MASK_BYTE4; DHCPFlags.bits.bDHCPServerDetected = FALSE; stackFlags.bits.bInConfigMode = TRUE; DHCPReset(); } // DHCP must be called all the time even after IP configuration is // discovered. // DHCP has to account lease expiration time and renew the configuration // time. DHCPTask(); if(DHCPIsBound()) stackFlags.bits.bInConfigMode = FALSE; } #endif //MODIFIED DHCP END //MODIFIED DHCP BEGIN // Removed /* #if defined(STACK_USE_DHCP) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. //Set our IP to 0.0.0.0 if all the following are TRUE: // - DHCP is enabled // - MAC is not linked yet (or cable is unplugged) if (STACK_IS_DHCP_ENABLED) { if ( !MACIsLinked() ) { //debugPutGenRomStr(2, (ROM char*)"3"); //@mxd:2:%s #if (DEBUG_STACKTSK >= LOG_INFO) //debugPutMsg(1); //@mxd:1:DHCP Enabled but MAC not linked yet - set IP to 0.0.0.0 #endif //if (stackFlags.bits.bInConfigMode) { //IP address must be 0.0.0.0 before DHCP has obtained a valid IP address MY_IP_BYTE1 = 0; MY_IP_BYTE2 = 0; MY_IP_BYTE3 = 0; MY_IP_BYTE4 = 0; //} stackFlags.bits.bInConfigMode = TRUE; DHCPReset(); } } #endif */ //MODIFIED DHCP END break; //case SM_STACK_IDLE: AND case SM_STACK_MAC: } //debugPutGenRomStr(2, (ROM char*)"4"); //@mxd:2:%s lbContinue = TRUE; if ( type.MACFrameType == MAC_IP ) { smStack = SM_STACK_IP; #if (DEBUG_STACKTSK >= LOG_DEBUG) debugPutMsg(2); //@mxd:2:Reading MAC IP header #endif } else if ( type.MACFrameType == MAC_ARP ) { smStack = SM_STACK_ARP; #if (DEBUG_STACKTSK >= LOG_DEBUG) debugPutMsg(3); //@mxd:3:Reading MAC ARP header #endif } else { MACDiscardRx(); //Discard the contents of the current RX buffer #if (DEBUG_STACKTSK >= LOG_WARN) debugPutMsg(4); //@mxd:4:Unknown MAC header read, MAC Frame Type = 0x%x debugPutByteHex(type.MACFrameType); #endif } break; //case SM_STACK_IDLE: AND case SM_STACK_MAC: case SM_STACK_ARP: if ( ARPProcess() ) smStack = SM_STACK_IDLE; //lbContinue = FALSE; //Removed in latest Microchip TCP/IP stack break; case SM_STACK_IP: if ( IPGetHeader(&destIP, /* Get Destination IP Address as received in IP header */ &remoteNode, &type.IPFrameType, &dataCount) ) { lbContinue = TRUE; if ( type.IPFrameType == IP_PROT_ICMP ) { smStack = SM_STACK_ICMP; #if defined(STACK_USE_IP_GLEANING) if(stackFlags.bits.bInConfigMode && STACK_IS_DHCP_ENABLED) { // Accoriding to "IP Gleaning" procedure, // when we receive an ICMP packet with a valid // IP address while we are still in configuration // mode, accept that address as ours and conclude // configuration mode. if ( destIP.Val != 0xffffffff ) { stackFlags.bits.bInConfigMode = FALSE; MY_IP_BYTE1 = destIP.v[0]; MY_IP_BYTE2 = destIP.v[1]; MY_IP_BYTE3 = destIP.v[2]; MY_IP_BYTE4 = destIP.v[3]; myDHCPBindCount--; } } #endif } #if defined(STACK_USE_TCP) else if ( type.IPFrameType == IP_PROT_TCP ) smStack = SM_STACK_TCP; #endif #if defined(STACK_USE_UDP) else if ( type.IPFrameType == IP_PROT_UDP ) smStack = SM_STACK_UDP; #endif else // Unknown/unsupported higher level protocol { lbContinue = FALSE; MACDiscardRx(); //Discard the contents of the current RX buffer smStack = SM_STACK_IDLE; } } else // Improper IP header version or checksum { MACDiscardRx(); //Discard the contents of the current RX buffer smStack = SM_STACK_IDLE; } break; //case SM_STACK_IP: #if defined(STACK_USE_UDP) case SM_STACK_UDP: if ( UDPProcess(&remoteNode, &destIP, dataCount) ) smStack = SM_STACK_IDLE; //lbContinue = FALSE; //Removed in latest Microchip TCP/IP stack break; //case SM_STACK_UDP: #endif #if defined(STACK_USE_TCP) case SM_STACK_TCP: if ( TCPProcess(&remoteNode, &destIP, dataCount) ) //Will return TRUE if TCPProcess finished it's task, else FALSE smStack = SM_STACK_IDLE; //lbContinue = FALSE; //Removed in latest Microchip TCP/IP stack break; //case SM_STACK_TCP: #endif case SM_STACK_ICMP: smStack = SM_STACK_IDLE; #if defined(STACK_USE_ICMP) if ( dataCount <= (MAX_ICMP_DATA_LEN+9) ) { if ( ICMPGet(&type.ICMPCode, data, (BYTE*)&dataCount, &ICMPId, &ICMPSeq) ) { if ( type.ICMPCode == ICMP_ECHO_REQUEST ) { lbContinue = TRUE; smStack = SM_STACK_ICMP_REPLY; } } } #endif MACDiscardRx(); //Discard the contents of the current RX buffer break; //case SM_STACK_ICMP: #if defined(STACK_USE_ICMP) case SM_STACK_ICMP_REPLY: if ( ICMPIsTxReady() ) { ICMPPut(&remoteNode, ICMP_ECHO_REPLY, data, (BYTE)dataCount, ICMPId, ICMPSeq); smStack = SM_STACK_IDLE; } break; //case SM_STACK_ICMP_REPLY: #endif } //switch(smStack) FAST_USER_PROCESS(); } while(lbContinue); #if defined(STACK_USE_TCP) // Perform timed TCP FSM. TCPTick(); #endif //MODIFIED DHCP BEGIN // Removed this //#if defined(STACK_USE_DHCP) /* * DHCP must be called all the time even after IP configuration is * discovered. * DHCP has to account lease expiration time and renew the configuration * time. */ // DHCPTask(); // if(DHCPIsBound()) // stackFlags.bits.bInConfigMode = FALSE; //#endif //debugPutGenRomStr(2, (ROM char*)"MACTask"); //@mxd:2:%s //Perform routine MAC tasks MACTask(); }
/** * This FSM checks for new incoming packets, and routes it to appropriate * stack components. It also performs timed operations. * * This function must be called periodically called * to make sure that timely response. * * @preCondition StackInit() is already called. * * side affect: Stack FSM is executed. */ void StackTask(void) { static NODE_INFO remoteNode; static WORD dataCount; #if defined(STACK_USE_ICMP) static BYTE data[MAX_ICMP_DATA_LEN]; static WORD ICMPId; static WORD ICMPSeq; #endif IP_ADDR destIP; //Is filled with the Destination IP address contained in the IP header union { BYTE MACFrameType; BYTE IPFrameType; ICMP_CODE ICMPCode; } type; BOOL lbContinue; lbContinue = TRUE; while( lbContinue ) { lbContinue = FALSE; switch(smStack) { case SM_STACK_IDLE: case SM_STACK_MAC: //Check if the MAC RX Buffer has any data, and if it does, read the header. //Get the next header from the NIC. The node who sent it's address will be copied to //'remoteNode.MACAddr'. if ( !MACRxbufGetHdr(&remoteNode.MACAddr, &type.MACFrameType) ) { //Header was NOT read if MACRxbufGetHdr returned FALSE #if defined(STACK_USE_DHCP) //If DHCP is enabled AND MAC is not linked yet, set our IP to 0 if (STACK_IS_DHCP_ENABLED) { if ( !MACIsLinked() ) { #if (DEBUG_STACKTSK >= LOG_INFO) debugPutMsg(1); //@mxd:1:DHCP Enabled but MAC not linked yet - set IP to 0.0.0.0 #endif //IP address must be 0.0.0.0 before DHCP has obtained a valid IP address MY_IP_BYTE1 = 0; MY_IP_BYTE2 = 0; MY_IP_BYTE3 = 0; MY_IP_BYTE4 = 0; stackFlags.bits.bInConfigMode = TRUE; DHCPReset(); } } #endif break; } lbContinue = TRUE; if ( type.MACFrameType == MAC_IP ) { smStack = SM_STACK_IP; #if (DEBUG_STACKTSK >= LOG_DEBUG) debugPutMsg(2); //@mxd:2:Reading MAC IP header #endif } else if ( type.MACFrameType == MAC_ARP ) { smStack = SM_STACK_ARP; #if (DEBUG_STACKTSK >= LOG_DEBUG) debugPutMsg(3); //@mxd:3:Reading MAC ARP header #endif } else { MACRxbufDiscard(); #if (DEBUG_STACKTSK >= LOG_WARN) debugPutMsg(4); //@mxd:4:Unknown MAC header read, MAC Frame Type = 0x%x debugPutByteHex(type.MACFrameType); #endif } break; case SM_STACK_ARP: lbContinue = FALSE; if ( ARPProcess() ) smStack = SM_STACK_IDLE; break; case SM_STACK_IP: if ( IPGetHeader(&destIP, /* Get Destination IP Address as received in IP header */ &remoteNode, &type.IPFrameType, &dataCount) ) { lbContinue = TRUE; if ( type.IPFrameType == IP_PROT_ICMP ) { smStack = SM_STACK_ICMP; #if defined(STACK_USE_IP_GLEANING) if ( stackFlags.bits.bInConfigMode ) { /* * Accoriding to "IP Gleaning" procedure, when we receive an ICMP packet * with a valid IP address while we are still in configuration mode, * accept that address as ours and conclude configuration mode. */ if ( destIP.Val != 0xffffffff ) { stackFlags.bits.bInConfigMode = FALSE; MY_IP_BYTE1 = destIP.v[0]; MY_IP_BYTE2 = destIP.v[1]; MY_IP_BYTE3 = destIP.v[2]; MY_IP_BYTE4 = destIP.v[3]; #if defined(STACK_USE_DHCP) /* * If DHCP and IP gleaning is enabled at the * same time, we must ensuer that once we have * IP address through IP gleaning, we abort * any pending DHCP requests and do not renew * any new DHCP configuration. */ DHCPAbort(); #endif } } #endif } #if defined(STACK_USE_TCP) else if ( type.IPFrameType == IP_PROT_TCP ) smStack = SM_STACK_TCP; #endif #if defined(STACK_USE_UDP) else if ( type.IPFrameType == IP_PROT_UDP ) smStack = SM_STACK_UDP; #endif else { lbContinue = FALSE; MACRxbufDiscard(); smStack = SM_STACK_IDLE; } } else { MACRxbufDiscard(); smStack = SM_STACK_IDLE; } break; #if defined(STACK_USE_UDP) case SM_STACK_UDP: //tempLocalIP.v[0] = MY_IP_BYTE1; //tempLocalIP.v[1] = MY_IP_BYTE2; //tempLocalIP.v[2] = MY_IP_BYTE3; //tempLocalIP.v[3] = MY_IP_BYTE4; if ( UDPProcess(&remoteNode, &destIP, dataCount) ) smStack = SM_STACK_IDLE; lbContinue = FALSE; break; #endif #if defined(STACK_USE_TCP) case SM_STACK_TCP: //tempLocalIP.v[0] = MY_IP_BYTE1; //tempLocalIP.v[1] = MY_IP_BYTE2; //tempLocalIP.v[2] = MY_IP_BYTE3; //tempLocalIP.v[3] = MY_IP_BYTE4; //Will return TRUE if TCPProcess finished it's task, else FALSE if ( TCPProcess(&remoteNode, &destIP, dataCount) ) smStack = SM_STACK_IDLE; lbContinue = FALSE; break; #endif case SM_STACK_ICMP: smStack = SM_STACK_IDLE; #if defined(STACK_USE_ICMP) if ( dataCount <= (MAX_ICMP_DATA_LEN+9) ) { if ( ICMPGet(&type.ICMPCode, data, (BYTE*)&dataCount, &ICMPId, &ICMPSeq) ) { if ( type.ICMPCode == ICMP_ECHO_REQUEST ) { lbContinue = TRUE; smStack = SM_STACK_ICMP_REPLY; } else { smStack = SM_STACK_IDLE; } } else { smStack = SM_STACK_IDLE; } } #endif MACRxbufDiscard(); break; #if defined(STACK_USE_ICMP) case SM_STACK_ICMP_REPLY: if ( ICMPIsTxReady() ) { ICMPPut(&remoteNode, ICMP_ECHO_REPLY, data, (BYTE)dataCount, ICMPId, ICMPSeq); smStack = SM_STACK_IDLE; } break; #endif } } #if defined(STACK_USE_TCP) // Perform timed TCP FSM. TCPTick(); #endif #if defined(STACK_USE_DHCP) /* * DHCP must be called all the time even after IP configuration is discovered. * DHCP has to account lease expiration time and renew the configuration time. */ DHCPTask(); if ( DHCPIsBound() ) stackFlags.bits.bInConfigMode = FALSE; #endif //Perform routine MAC tasks MACTask(); }
void AutoIPTasks(void) { BYTE i; for (i = 0; i < NETWORK_INTERFACES; i++) { LoadState (i); AutoIPClient.flags.bits.bCurrentLinkState = MACIsLinked(); if(AutoIPClient.flags.bits.bCurrentLinkState != AutoIPClient.flags.bits.bLastLinkState) { AutoIPClient.flags.bits.bLastLinkState = AutoIPClient.flags.bits.bCurrentLinkState; if(!AutoIPClient.flags.bits.bCurrentLinkState) { AutoIPClient.flags.bits.bConfigureAutoIP = FALSE; AutoIPClient.smAUTOIPState = SM_AUTOIP_DISABLED; AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; } else { AutoIPClient.smAUTOIPState = SM_AUTOIP_INIT_RNG; } } #if defined (STACK_USE_DHCP_CLIENT) if (DHCPIsBound(i)) { AutoIPClient.flags.bits.bConfigureAutoIP = FALSE; AutoIPClient.smAUTOIPState = SM_AUTOIP_DISABLED; AutoIPClient.flags.bits.bLastDHCPState = TRUE; } else { if (AutoIPClient.flags.bits.bLastDHCPState == TRUE) { if (AutoIPClient.flags.bits.bCurrentLinkState) AutoIPClient.smAUTOIPState = SM_AUTOIP_INIT_RNG; } AutoIPClient.flags.bits.bLastDHCPState = FALSE; } #endif if (AutoIPClient.flags.bits.gDisableAutoIP == TRUE) { AutoIPClient.flags.bits.bConfigureAutoIP = FALSE; AutoIPClient.smAUTOIPState = SM_AUTOIP_DISABLED; } switch (AutoIPClient.smAUTOIPState) { // Default no-AutoIP case case SM_AUTOIP_DISABLED: break; // Initializes the random number generator with a seed based on the MAC address case SM_AUTOIP_INIT_RNG: AutoIPRandSeed (((DWORD)AppConfig.MyMACAddr.v[0] + ((DWORD)AppConfig.MyMACAddr.v[1] << 8) + \ ((DWORD)AppConfig.MyMACAddr.v[2] << 16) + ((DWORD)AppConfig.MyMACAddr.v[3] << 24) + \ ((DWORD)AppConfig.MyMACAddr.v[4]) + ((DWORD)AppConfig.MyMACAddr.v[5] << 8)), i); AutoIPClient.smAUTOIPState = SM_AUTOIP_CHECK_ADDRESS; // Check the address to see if it's in use before we write it into AppConfig case SM_AUTOIP_CHECK_ADDRESS: if (AutoIPClient.flags.bits.checkAddress == FALSE) { AutoIPClient.flags.bits.checkAddress = TRUE; AppConfig.MyMask.Val = 0x00000000; // Generate a random IP address (based on the MAC address) to try and claim. // Dynamic link-local addresses can fall within the range: // 169.254.1.0 - 169.254.254.255 AutoIPClient.packet.TargetIPAddr.byte.MB = AutoIPRand(i) % 256; AutoIPClient.packet.TargetIPAddr.byte.UB = (AutoIPRand(i) % 254) + 1; AutoIPClient.packet.TargetIPAddr.word.LW = 0xFEA9; ARPResolve (&AutoIPClient.packet.TargetIPAddr); AutoIPClient.eventTime = TickGet(); } if (!ARPIsResolved (&AutoIPClient.packet.TargetIPAddr, &AutoIPClient.packet.TargetMACAddr)) { if (TickGet() - AutoIPClient.eventTime > TICK_SECOND) { AutoIPClient.smAUTOIPState = SM_AUTOIP_SETUP_MESSAGE; } } else { AutoIPClient.flags.bits.checkAddress = FALSE; } break; // Set up an ARP packet case SM_AUTOIP_SETUP_MESSAGE: AutoIPClient.flags.bits.checkAddress = FALSE; // Set the bConfigureAutoIP flag- This flag will cause an AutoIP conflict // if a response packet is received from the address we're trying to claim. AutoIPClient.flags.bits.bConfigureAutoIP = TRUE; // Configure the fields for a gratuitous ARP packet AutoIPClient.packet.Operation = ARP_OPERATION_REQ; AutoIPClient.packet.TargetMACAddr.v[0] = 0xff; AutoIPClient.packet.TargetMACAddr.v[1] = 0xff; AutoIPClient.packet.TargetMACAddr.v[2] = 0xff; AutoIPClient.packet.TargetMACAddr.v[3] = 0xff; AutoIPClient.packet.TargetMACAddr.v[4] = 0xff; AutoIPClient.packet.TargetMACAddr.v[5] = 0xff; AppConfig.MyIPAddr = AutoIPClient.packet.TargetIPAddr; AppConfig.MyMask.Val = 0x0000FFFF; memcpy(&AutoIPClient.packet.SenderMACAddr, (void*)&AppConfig.MyMACAddr, sizeof(AutoIPClient.packet.SenderMACAddr)); AutoIPClient.packet.HardwareType = HW_ETHERNET; AutoIPClient.packet.Protocol = ARP_IP; AutoIPClient.packet.MACAddrLen = sizeof(MAC_ADDR); AutoIPClient.packet.ProtocolLen = sizeof(IP_ADDR); AutoIPClient.packet.SenderIPAddr.Val = AutoIPClient.packet.TargetIPAddr.Val; SwapARPPacket(&AutoIPClient.packet); // Generate a random delay between 0 and 1 second AutoIPClient.randomDelay = ((rand() % 20) * TICK_SECOND) / 20; // Store the current time AutoIPClient.eventTime = TickGet(); // Set the state to send the ARP packet AutoIPClient.smAUTOIPState = SM_AUTOIP_GRATUITOUS_ARP1; break; // Send a gratuitous ARP packet to try and claim our address case SM_AUTOIP_GRATUITOUS_ARP1: case SM_AUTOIP_GRATUITOUS_ARP2: case SM_AUTOIP_GRATUITOUS_ARP3: // Check to ensure we've passed the delay time if (TickGet() - AutoIPClient.eventTime > AutoIPClient.randomDelay) { // Store the new event time AutoIPClient.eventTime = TickGet(); // Generate a new random delay between 1 and 2 seconds AutoIPClient.randomDelay = TICK_SECOND + (((rand() % 20) * TICK_SECOND) / 20); // Transmit the packet while(!MACIsTxReady()); MACSetWritePtr(BASE_TX_ADDR); MACPutHeader(&AutoIPClient.packet.TargetMACAddr, MAC_ARP, sizeof(AutoIPClient.packet)); MACPutArray((BYTE*)&AutoIPClient.packet, sizeof(AutoIPClient.packet)); MACFlush(); // Increment the probe iteration or increment to the delay state AutoIPClient.smAUTOIPState++; } break; // Delay for 1-2 seconds after sending the third ARP request before // entering the configured state case SM_AUTOIP_DELAY: if (TickGet() - AutoIPClient.eventTime > AutoIPClient.randomDelay) AutoIPClient.smAUTOIPState = SM_AUTOIP_CONFIGURED; break; // Configure the module to limit the rate at which packets are sent case SM_AUTOIP_RATE_LIMIT_SET: AutoIPClient.eventTime = TickGet(); AppConfig.MyIPAddr.v[0] = MY_DEFAULT_IP_ADDR_BYTE1; AppConfig.MyIPAddr.v[1] = MY_DEFAULT_IP_ADDR_BYTE2; AppConfig.MyIPAddr.v[2] = MY_DEFAULT_IP_ADDR_BYTE3; AppConfig.MyIPAddr.v[3] = MY_DEFAULT_IP_ADDR_BYTE4; AutoIPClient.smAUTOIPState = SM_AUTOIP_RATE_LIMIT_WAIT; break; // Ensure that we don't try more than one address every 60 seconds case SM_AUTOIP_RATE_LIMIT_WAIT: if (TickGet() - AutoIPClient.eventTime > TICK_SECOND * 60) AutoIPClient.smAUTOIPState = SM_AUTOIP_CHECK_ADDRESS; break; // Configured state case SM_AUTOIP_CONFIGURED: AutoIPClient.flags.bits.bConfigureAutoIP = FALSE; break; // Address defense state case SM_AUTOIP_DEFEND: // Prepare and send an ARP response AutoIPClient.packet.Operation = ARP_OPERATION_RESP; AutoIPClient.packet.HardwareType = HW_ETHERNET; AutoIPClient.packet.Protocol = ARP_IP; SwapARPPacket(&AutoIPClient.packet); while(!MACIsTxReady()); MACSetWritePtr(BASE_TX_ADDR); MACPutHeader(&AutoIPClient.packet.TargetMACAddr, MAC_ARP, sizeof(AutoIPClient.packet)); MACPutArray((BYTE*)&AutoIPClient.packet, sizeof(AutoIPClient.packet)); MACFlush(); AutoIPClient.smAUTOIPState = SM_AUTOIP_CONFIGURED; break; } } }
void Diagnostic(void) { switch (Diag_Comm2) { case 0 : Pcomm_List = &Comm_List[0][0]; //Init pointers 1 time Pcomm_List2 = &Comm_List[0][0]; Diag_Comm2 = 20; break; case 1 : Pcomm_List2 = &Comm_List[0][0]; if (Pcomm_List2 != Pcomm_List) { if(UDPIsPutReady(socket1)) { UDPPutString(Comm_List[0]); UDPFlush(); Pcomm_List2+=4; Diag_Comm2 = 2; break; } } break; case 2 : if (Pcomm_List2 != Pcomm_List) { if(UDPIsPutReady(socket1)) { UDPPutString(Comm_List[1]); UDPFlush(); Pcomm_List2+=4; Diag_Comm2 = 3; break; } } break; case 3 : if (Pcomm_List2 != Pcomm_List) { if(UDPIsPutReady(socket1)) { UDPPutString(Comm_List[2]); UDPFlush(); Pcomm_List2+=4; Diag_Comm2 = 4; break; } } break; case 4 : if (Pcomm_List2 != Pcomm_List) { if(UDPIsPutReady(socket1)) { UDPPutString(Comm_List[3]); UDPFlush(); Pcomm_List2+=4; Diag_Comm2 = 5; break; } } break; case 5 : if (Pcomm_List2 != Pcomm_List) { if(UDPIsPutReady(socket1)) { UDPPutString(Comm_List[4]); UDPFlush(); Pcomm_List2+=4; Diag_Comm2 = 6; break; } } break; case 6 : if (Pcomm_List2 != Pcomm_List) { if(UDPIsPutReady(socket1)) { UDPPutString(Comm_List[5]); UDPFlush(); Pcomm_List2+=4; Diag_Comm2 = 7; break; } } break; case 7 : if (Pcomm_List2 != Pcomm_List) { if(UDPIsPutReady(socket1)) { UDPPutString(Comm_List[6]); UDPFlush(); Pcomm_List2+=4; Diag_Comm2 = 8; break; } } break; case 8 : if (Pcomm_List2 != Pcomm_List) { if(UDPIsPutReady(socket1)) { UDPPutString(Comm_List[7]); UDPFlush(); Pcomm_List2 = &Comm_List[0][0]; // point to Comm_List[0] Diag_Comm2 = 1; } } break; case 20 : if(!MACIsLinked()) { return; } #if defined(STACK_USE_DHCP_CLIENT) { static DWORD dwTimer = 0; // Wait until DHCP module is finished if(!DHCPIsBound(0)) { dwTimer = TickGet(); return; } // Wait an additional half second after DHCP is finished to let the announce module and any other stack state machines to reach normal operation if(TickGet() - dwTimer < TICK_SECOND/2) return; } #endif Diag_Comm2 = 21; break; case 21 : if (MAC_IP_READY == True) { TestTarget.MACAddr.v[0] = MACPC[0];//0x00; TestTarget.MACAddr.v[1] = MACPC[1];//0x0E; TestTarget.MACAddr.v[2] = MACPC[2];//0x0C; TestTarget.MACAddr.v[3] = MACPC[3];//0x74; TestTarget.MACAddr.v[4] = MACPC[4];//0xCC; TestTarget.MACAddr.v[5] = MACPC[5];//0x08; TestTarget.IPAddr.v[0] = IPPC[0];//192; TestTarget.IPAddr.v[1] = IPPC[1];//168; TestTarget.IPAddr.v[2] = IPPC[2];//1; TestTarget.IPAddr.v[3] = IPPC[3];//24; socket1 = UDPOpen(0x7000, &TestTarget, 0x7000); //open the socket if(socket1 == 0xFF) //Invalid socket { break; } else{Diag_Comm2 = 1;} } break; case 22 : break; default : break; } }
/****************************************************************************** * Function: void StackTask(void) * PreCondition: StackInit() is already called. * Input: None * Output: Stack FSM is executed. * Side Effects: None * Note: This FSM checks for new incoming packets, * and routes it to appropriate stack components. * It also performs timed operations. * This function must be called periodically to * ensure timely responses. ******************************************************************************/ void StackTask(void) { static WORD dataCount; IP_ADDR tempLocalIP; BOOL lbContinue; #if defined(STACK_USE_ICMP) static BYTE data[MAX_ICMP_DATA_LEN]; static WORD ICMPId, ICMPSeq; #endif union { BYTE MACFrameType; BYTE IPFrameType; ICMP_CODE ICMPCode; } type; do { lbContinue = FALSE; switch(smStack) { case SM_STACK_IDLE: case SM_STACK_MAC: if ( !MACGetHeader(&remoteNode.MACAddr, &type.MACFrameType) ) { #if defined(STACK_USE_DHCP) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if ( AppConfig.Flags.bIsDHCPEnabled ) { if ( !MACIsLinked() ) { AppConfig.MyIPAddr.Val = 0x00000000ul; AppConfig.Flags.bInConfigMode = TRUE; DHCPReset(); } } #endif break; } lbContinue = TRUE; if ( type.MACFrameType == MAC_IP ) smStack = SM_STACK_IP; else if ( type.MACFrameType == MAC_ARP ) smStack = SM_STACK_ARP; else MACDiscardRx(); break; case SM_STACK_ARP: if ( ARPProcess() ) smStack = SM_STACK_IDLE; break; case SM_STACK_IP: if ( IPGetHeader(&tempLocalIP,&remoteNode,&type.IPFrameType,&dataCount) ) { lbContinue = TRUE; if ( type.IPFrameType == IP_PROT_ICMP ) { smStack = SM_STACK_ICMP; #if defined(STACK_USE_IP_GLEANING) if(AppConfig.Flags.bInConfigMode && AppConfig.Flags.bIsDHCPEnabled) { /* * Accoriding to "IP Gleaning" procedure, * when we receive an ICMP packet with a valid * IP address while we are still in configuration * mode, accept that address as ours and conclude * configuration mode. */ if( tempLocalIP.Val != 0xffffffff ) { AppConfig.Flags.bInConfigMode = FALSE; AppConfig.MyIPAddr = tempLocalIP; myDHCPBindCount--; } } #endif } #if defined(STACK_USE_TCP) else if ( type.IPFrameType == IP_PROT_TCP ) smStack = SM_STACK_TCP; #endif #if defined(STACK_USE_UDP) else if ( type.IPFrameType == IP_PROT_UDP ) smStack = SM_STACK_UDP; #endif else // Unknown/unsupported higher level protocol { lbContinue = FALSE; MACDiscardRx(); smStack = SM_STACK_IDLE; } } else // Improper IP header version or checksum { MACDiscardRx(); smStack = SM_STACK_IDLE; } break; #if defined(STACK_USE_UDP) case SM_STACK_UDP: if ( UDPProcess(&remoteNode, &tempLocalIP, dataCount) ) smStack = SM_STACK_IDLE; break; #endif #if defined(STACK_USE_TCP) case SM_STACK_TCP: if ( TCPProcess(&remoteNode, &tempLocalIP, dataCount) ) smStack = SM_STACK_IDLE; break; #endif case SM_STACK_ICMP: smStack = SM_STACK_IDLE; #if defined(STACK_USE_ICMP) if ( dataCount <= (MAX_ICMP_DATA_LEN+8) ) { if ( ICMPGet(&type.ICMPCode,data,(BYTE*)&dataCount,&ICMPId,&ICMPSeq) ) { if ( type.ICMPCode == ICMP_ECHO_REQUEST ) { lbContinue = TRUE; smStack = SM_STACK_ICMP_REPLY; } } } #endif MACDiscardRx(); break; #if defined(STACK_USE_ICMP) case SM_STACK_ICMP_REPLY: if ( ICMPIsTxReady() ) { ICMPPut(&remoteNode,ICMP_ECHO_REPLY,data,(BYTE)dataCount,ICMPId,ICMPSeq); smStack = SM_STACK_IDLE; } break; #endif } } while(lbContinue); #if defined(STACK_USE_TCP) TCPTick(); // Perform timed TCP FSM. #endif #if defined(STACK_USE_DHCP) /* * DHCP must be called all the time even after IP configuration is * discovered. * DHCP has to account lease expiration time and renew the configuration * time. */ DHCPTask(); if(DHCPIsBound()) AppConfig.Flags.bInConfigMode = FALSE; #endif #if defined(STACK_USE_SNTP) SNTPTask(); // Execute SNTP client FSM #endif #if defined(STACK_USE_NBNS) NBNSTask(); // Execute NetBIOS name service task #endif }
/********************************************************************* * Function: void StackTask(void) * * PreCondition: StackInit() is already called. * * Input: None * * Output: Stack FSM is executed. * * Side Effects: None * * Note: This FSM checks for new incoming packets, * and routes it to appropriate stack components. * It also performs timed operations. * * This function must be called periodically to * ensure timely responses. * ********************************************************************/ void StackTask(void) { WORD dataCount; IP_ADDR tempLocalIP; BYTE cFrameType; BYTE cIPFrameType; #if defined(STACK_USE_DHCP_CLIENT) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if(AppConfig.Flags.bIsDHCPEnabled) { if(!MACIsLinked()) { AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; DHCPFlags.bits.bDHCPServerDetected = FALSE; AppConfig.Flags.bInConfigMode = TRUE; DHCPReset(); } // DHCP must be called all the time even after IP configuration is // discovered. // DHCP has to account lease expiration time and renew the configuration // time. DHCPTask(); if(DHCPIsBound()) AppConfig.Flags.bInConfigMode = FALSE; } #endif #if defined(STACK_USE_TCP) // Perform all TCP time related tasks (retransmit, send acknowledge, close connection, etc) TCPTick(); #endif // Process as many incomming packets as we can while(MACGetHeader(&remoteNode.MACAddr, &cFrameType)) { switch(cFrameType) { case MAC_ARP: ARPProcess(); break; case MAC_IP: if(!IPGetHeader(&tempLocalIP, &remoteNode, &cIPFrameType, &dataCount)) break; #if defined(STACK_USE_ICMP_SERVER) || defined(STACK_USE_ICMP_CLIENT) if(cIPFrameType == IP_PROT_ICMP) { ICMPProcess(&remoteNode, dataCount); #if defined(STACK_USE_IP_GLEANING) if(AppConfig.Flags.bInConfigMode && AppConfig.Flags.bIsDHCPEnabled) { // Accoriding to "IP Gleaning" procedure, // when we receive an ICMP packet with a valid // IP address while we are still in configuration // mode, accept that address as ours and conclude // configuration mode. if(tempLocalIP.Val != 0xffffffff) { AppConfig.Flags.bInConfigMode = FALSE; AppConfig.MyIPAddr = tempLocalIP; myDHCPBindCount--; } } #endif break; } #endif #if defined(STACK_USE_TCP) if(cIPFrameType == IP_PROT_TCP) { TCPProcess(&remoteNode, &tempLocalIP, dataCount); break; } #endif #if defined(STACK_USE_UDP) if(cIPFrameType == IP_PROT_UDP) { UDPProcess(&remoteNode, &tempLocalIP, dataCount); break; } #endif break; } } }
/********************************************************************* * Function: void StackTask(void) * * PreCondition: StackInit() is already called. * * Input: None * * Output: Stack FSM is executed. * * Side Effects: None * * Note: This FSM checks for new incoming packets, * and routes it to appropriate stack components. * It also performs timed operations. * * This function must be called periodically to * ensure timely responses. * ********************************************************************/ void StackTask(void) { WORD dataCount; IP_ADDR tempLocalIP; BYTE cFrameType; BYTE cIPFrameType; #if defined(STACK_USE_DHCP_CLIENT) // Normally, an application would not include DHCP module // if it is not enabled. But in case some one wants to disable // DHCP module at run-time, remember to not clear our IP // address if link is removed. if(AppConfig.Flags.bIsDHCPEnabled) { if(!MACIsLinked()) { AppConfig.MyIPAddr.Val = AppConfig.DefaultIPAddr.Val; AppConfig.MyMask.Val = AppConfig.DefaultMask.Val; DHCPFlags.bits.bDHCPServerDetected = FALSE; AppConfig.Flags.bInConfigMode = TRUE; DHCPReset(); } // DHCP must be called all the time even after IP configuration is // discovered. // DHCP has to account lease expiration time and renew the configuration // time. DHCPTask(); if(DHCPIsBound()) AppConfig.Flags.bInConfigMode = FALSE; } #endif #if defined(STACK_USE_TCP) // Perform all TCP time related tasks (retransmit, send acknowledge, close connection, etc) TCPTick(); #endif #if defined(STACK_USE_UDP) UDPTask(); #endif // Process as many incomming packets as we can while(1) { //if using the random module, generate entropy #if defined(STACK_USE_RANDOM) RandomAdd(remoteNode.MACAddr.v[5]); #endif // We are about to fetch a new packet, make sure that the // UDP module knows that any old RX data it has laying // around will now be gone. #if defined(STACK_USE_UDP) UDPDiscard(); #endif // Fetch a packet (throws old one away, if not thrown away // yet) if(!MACGetHeader(&remoteNode.MACAddr, &cFrameType)) break; // Dispatch the packet to the appropriate handler switch(cFrameType) { case MAC_ARP: ARPProcess(); break; case MAC_IP: if(!IPGetHeader(&tempLocalIP, &remoteNode, &cIPFrameType, &dataCount)) break; #if defined(STACK_USE_ICMP_SERVER) || defined(STACK_USE_ICMP_CLIENT) if(cIPFrameType == IP_PROT_ICMP) { #if defined(STACK_USE_IP_GLEANING) if(AppConfig.Flags.bInConfigMode && AppConfig.Flags.bIsDHCPEnabled) { // Accoriding to "IP Gleaning" procedure, // when we receive an ICMP packet with a valid // IP address while we are still in configuration // mode, accept that address as ours and conclude // configuration mode. if(tempLocalIP.Val != 0xffffffff) { AppConfig.Flags.bInConfigMode = FALSE; AppConfig.MyIPAddr = tempLocalIP; myDHCPBindCount--; } } #endif // Process this ICMP packet if it the destination IP address matches our address or one of the broadcast IP addressees if( (tempLocalIP.Val == AppConfig.MyIPAddr.Val) || (tempLocalIP.Val == 0xFFFFFFFF) || (tempLocalIP.Val == ((AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val) | ~AppConfig.MyMask.Val))) { ICMPProcess(&remoteNode, dataCount); } break; } #endif #if defined(STACK_USE_TCP) if(cIPFrameType == IP_PROT_TCP) { TCPProcess(&remoteNode, &tempLocalIP, dataCount); break; } #endif #if defined(STACK_USE_UDP) if(cIPFrameType == IP_PROT_UDP) { // Stop processing packets if we came upon a UDP frame with application data in it if(UDPProcess(&remoteNode, &tempLocalIP, dataCount)) return; } #endif break; } } }
void AutoIPTasks(NET_CONFIG* pConfig) { // uint8_t i; TCPIP_MAC_HANDLE hMac; // for (i = 0; i < NETWORK_INTERFACES; i++) { LoadState(_TCPIPStackNetIx(pConfig)); hMac = _TCPIPStackNetToMac(pConfig); AutoIPClient.flags.bits.bCurrentLinkState = MACIsLinked(hMac); if(AutoIPClient.flags.bits.bCurrentLinkState != AutoIPClient.flags.bits.bLastLinkState) { AutoIPClient.flags.bits.bLastLinkState = AutoIPClient.flags.bits.bCurrentLinkState; if(!AutoIPClient.flags.bits.bCurrentLinkState) { AutoIPClient.flags.bits.bConfigureAutoIP = false; AutoIPClient.smAUTOIPState = SM_AUTOIP_DISABLED; pConfig->MyIPAddr.Val = pConfig->DefaultIPAddr.Val; pConfig->MyMask.Val = pConfig->DefaultMask.Val; } else { AutoIPClient.smAUTOIPState = SM_AUTOIP_INIT_RNG; } } #if defined (TCPIP_STACK_USE_DHCP_CLIENT) if (DHCPIsBound(pConfig)) { AutoIPClient.flags.bits.bConfigureAutoIP = false; AutoIPClient.smAUTOIPState = SM_AUTOIP_DISABLED; AutoIPClient.flags.bits.bLastDHCPState = true; } else { if (AutoIPClient.flags.bits.bLastDHCPState == true) { if (AutoIPClient.flags.bits.bCurrentLinkState) AutoIPClient.smAUTOIPState = SM_AUTOIP_INIT_RNG; } AutoIPClient.flags.bits.bLastDHCPState = false; } #endif if (AutoIPClient.flags.bits.gDisableAutoIP == true) { AutoIPClient.flags.bits.bConfigureAutoIP = false; AutoIPClient.smAUTOIPState = SM_AUTOIP_DISABLED; } switch (AutoIPClient.smAUTOIPState) { // Default no-AutoIP case case SM_AUTOIP_DISABLED: break; // Initializes the random number generator with a seed based on the MAC address case SM_AUTOIP_INIT_RNG: AutoIPRandSeed (((uint32_t)pConfig->MyMACAddr.v[0] + ((uint32_t)pConfig->MyMACAddr.v[1] << 8) + \ ((uint32_t)pConfig->MyMACAddr.v[2] << 16) + ((uint32_t)pConfig->MyMACAddr.v[3] << 24) + \ ((uint32_t)pConfig->MyMACAddr.v[4]) + ((uint32_t)pConfig->MyMACAddr.v[5] << 8)), pConfig); AutoIPClient.smAUTOIPState = SM_AUTOIP_CHECK_ADDRESS; // Check the address to see if it's in use before we write it into NetConfig case SM_AUTOIP_CHECK_ADDRESS: if (AutoIPClient.flags.bits.checkAddress == false) { AutoIPClient.flags.bits.checkAddress = true; pConfig->MyMask.Val = 0x00000000; // Generate a random IP address (based on the MAC address) to try and claim. // Dynamic link-local addresses can fall within the range: // 169.254.1.0 - 169.254.254.255 AutoIPClient.packet.TargetIPAddr.byte.MB = AutoIPRand(pConfig) % 256; AutoIPClient.packet.TargetIPAddr.byte.UB = (AutoIPRand(pConfig) % 254) + 1; AutoIPClient.packet.TargetIPAddr.word.LW = 0xFEA9; ARPResolve (pConfig, &AutoIPClient.packet.TargetIPAddr); AutoIPClient.eventTime = SYS_TICK_Get(); } if (!ARPIsResolved (pConfig, &AutoIPClient.packet.TargetIPAddr, &AutoIPClient.packet.TargetMACAddr)) { if (SYS_TICK_Get() - AutoIPClient.eventTime > SYS_TICK_TicksPerSecondGet()) { AutoIPClient.smAUTOIPState = SM_AUTOIP_SETUP_MESSAGE; } } else { AutoIPClient.flags.bits.checkAddress = false; } break; // Set up an ARP packet case SM_AUTOIP_SETUP_MESSAGE: AutoIPClient.flags.bits.checkAddress = false; // Set the bConfigureAutoIP flag- This flag will cause an AutoIP conflict // if a response packet is received from the address we're trying to claim. AutoIPClient.flags.bits.bConfigureAutoIP = true; // Configure the fields for a gratuitous ARP packet AutoIPClient.packet.Operation = ARP_OPERATION_REQ; AutoIPClient.packet.TargetMACAddr.v[0] = 0xff; AutoIPClient.packet.TargetMACAddr.v[1] = 0xff; AutoIPClient.packet.TargetMACAddr.v[2] = 0xff; AutoIPClient.packet.TargetMACAddr.v[3] = 0xff; AutoIPClient.packet.TargetMACAddr.v[4] = 0xff; AutoIPClient.packet.TargetMACAddr.v[5] = 0xff; pConfig->MyIPAddr = AutoIPClient.packet.TargetIPAddr; pConfig->MyMask.Val = 0x0000FFFF; memcpy(&AutoIPClient.packet.SenderMACAddr, (void*)&pConfig->MyMACAddr, sizeof(AutoIPClient.packet.SenderMACAddr)); AutoIPClient.packet.HardwareType = HW_ETHERNET; AutoIPClient.packet.Protocol = ARP_IP; AutoIPClient.packet.MACAddrLen = sizeof(MAC_ADDR); AutoIPClient.packet.ProtocolLen = sizeof(IP_ADDR); AutoIPClient.packet.SenderIPAddr.Val = AutoIPClient.packet.TargetIPAddr.Val; SwapARPPacket(&AutoIPClient.packet); // Generate a random delay between 0 and 1 second AutoIPClient.randomDelay = ((LFSRRand() % 20) * SYS_TICK_TicksPerSecondGet()) / 20; // Store the current time AutoIPClient.eventTime = SYS_TICK_Get(); // Set the state to send the ARP packet AutoIPClient.smAUTOIPState = SM_AUTOIP_GRATUITOUS_ARP1; break; // Send a gratuitous ARP packet to try and claim our address case SM_AUTOIP_GRATUITOUS_ARP1: case SM_AUTOIP_GRATUITOUS_ARP2: case SM_AUTOIP_GRATUITOUS_ARP3: // Check to ensure we've passed the delay time if (SYS_TICK_Get() - AutoIPClient.eventTime > AutoIPClient.randomDelay) { if(!MACIsTxReady(hMac)) { break; } // Store the new event time AutoIPClient.eventTime = SYS_TICK_Get(); // Generate a new random delay between 1 and 2 seconds AutoIPClient.randomDelay = SYS_TICK_TicksPerSecondGet() + (((LFSRRand() % 20) * SYS_TICK_TicksPerSecondGet()) / 20); // Transmit the packet MACSetWritePtr(hMac, MACGetTxBaseAddr(hMac)); MACPutHeader(hMac, &AutoIPClient.packet.TargetMACAddr, ETHERTYPE_ARP, sizeof(AutoIPClient.packet)); MACPutArray(hMac, (uint8_t*)&AutoIPClient.packet, sizeof(AutoIPClient.packet)); MACFlush(hMac); // Increment the probe iteration or increment to the delay state AutoIPClient.smAUTOIPState++; } break; // Delay for 1-2 seconds after sending the third ARP request before // entering the configured state case SM_AUTOIP_DELAY: if (SYS_TICK_Get() - AutoIPClient.eventTime > AutoIPClient.randomDelay) AutoIPClient.smAUTOIPState = SM_AUTOIP_CONFIGURED; break; // Configure the module to limit the rate at which packets are sent case SM_AUTOIP_RATE_LIMIT_SET: AutoIPClient.eventTime = SYS_TICK_Get(); pConfig->MyIPAddr.Val = pConfig->DefaultIPAddr.Val; AutoIPClient.smAUTOIPState = SM_AUTOIP_RATE_LIMIT_WAIT; break; // Ensure that we don't try more than one address every 60 seconds case SM_AUTOIP_RATE_LIMIT_WAIT: if (SYS_TICK_Get() - AutoIPClient.eventTime > SYS_TICK_TicksPerSecondGet() * 60) AutoIPClient.smAUTOIPState = SM_AUTOIP_CHECK_ADDRESS; break; // Configured state case SM_AUTOIP_CONFIGURED: AutoIPClient.flags.bits.bConfigureAutoIP = false; break; // Address defense state case SM_AUTOIP_DEFEND: // Prepare and send an ARP response if(!MACIsTxReady(hMac)) { break; } AutoIPClient.packet.Operation = ARP_OPERATION_RESP; AutoIPClient.packet.HardwareType = HW_ETHERNET; AutoIPClient.packet.Protocol = ARP_IP; SwapARPPacket(&AutoIPClient.packet); MACSetWritePtr(hMac, MACGetTxBaseAddr(hMac)); MACPutHeader(hMac, &AutoIPClient.packet.TargetMACAddr, ETHERTYPE_ARP, sizeof(AutoIPClient.packet)); MACPutArray(hMac, (uint8_t*)&AutoIPClient.packet, sizeof(AutoIPClient.packet)); MACFlush(hMac); AutoIPClient.smAUTOIPState = SM_AUTOIP_CONFIGURED; break; } } }