/*********************************************************************
 * Function:        BOOL UDPGet(BYTE *v)
 *
 * PreCondition:    UDPInit() is already called     AND
 *                  UDPIsGetReady(s) == TRUE
 *
 * Input:           v       - Buffer to receive UDP data byte
 *
 * Output:          TRUE    if a data byte was read
 *                  FALSE   if no data byte was read or available
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            This function fetches data from an active UDP
 *                  socket as set by UDPIsGetReady() call.
 ********************************************************************/
BOOL UDPGet(BYTE *v)
{
    // CALLER MUST MAKE SURE THAT THERE IS ENOUGH DATA BYTE IN BUFFER
    // BEFORE CALLING THIS FUNCTION.
    // USE UDPIsGetReady() TO CONFIRM.

    if ( UDPSocketInfo[activeUDPSocket].RxCount == 0 )
        return FALSE;

    // If if this very first read to packet, set MAC Rx Pointer to
    // beginig of UDP data area.
    if ( UDPSocketInfo[activeUDPSocket].Flags.bFirstRead )
    {
        UDPSocketInfo[activeUDPSocket].Flags.bFirstRead = FALSE;
        UDPSetRxBuffer(0);
    }

    *v = MACGet();

    UDPSocketInfo[activeUDPSocket].RxCount--;

    if ( UDPSocketInfo[activeUDPSocket].RxCount == 0 )
    {
        MACDiscardRx();
    }

    return TRUE;
}
/*********************************************************************
 * Function:        void UDPDiscard(void)
 *
 * PreCondition:    UDPInit() is already called    AND
 *                  UDPIsGetReady() == TRUE with desired UDP socket.
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            This function discards an active UDP socket content.
 ********************************************************************/
void UDPDiscard(void)
{
    if ( UDPSocketInfo[activeUDPSocket].RxCount )
        MACDiscardRx();

    UDPSocketInfo[activeUDPSocket].RxCount = 0;
}
Beispiel #3
0
/**
 * Read the requested number of bytes from the active UDP socket into
 * the given buffer.
 *
 * Note: This function fetches data from an active UDP socket as set by
 * UDPIsGetReady() call.
 *
 * @preCondition    UDPInit() is already called     AND
 *                  UDPIsGetReady(s) == TRUE
 *
 * @param[in] buffer   Buffer to hold received data.
 * @param count         Buffer length
 *
 * @return          Number of bytes loaded into buffer.
 */
WORD UDPGetArray(BYTE *buffer, WORD count)
{
    WORD bytesRead;
    
    if ( UDPSocketInfo[activeUDPSocket].RxCount == 0 )
        return 0;

    // If if this very first read to packet, set MAC Rx Pointer to
    // beginig of UDP data area.
    if ( UDPSocketInfo[activeUDPSocket].Flags.bFirstRead )
    {
        UDPSocketInfo[activeUDPSocket].Flags.bFirstRead = FALSE;
        UDPSetRxBuffer(0);
    }

    //If more bytes requested then are left in the receive buffer, adjust count
    if (count > UDPSocketInfo[activeUDPSocket].RxCount) {
        count = UDPSocketInfo[activeUDPSocket].RxCount;
    }

    //Read the requested amount of data from the current MAC receive buffer
    bytesRead = MACGetArray(buffer, count);

    UDPSocketInfo[activeUDPSocket].RxCount -= bytesRead;

    if ( UDPSocketInfo[activeUDPSocket].RxCount == 0 )
    {
        MACDiscardRx(); //Discard the contents of the current RX buffer
    }

    return count;
}
Beispiel #4
0
/*********************************************************************
 * Function:        BOOL UDPProcess(NODE_INFO* remoteNode,
 *                                  WORD len)
 *
 * PreCondition:    UDPInit() is already called     AND
 *                  UDP segment is ready in MAC buffer
 *
 * Input:           remoteNode      - Remote node info
 *                  len             - Total length of UDP semgent.
 *
 * Output:          TRUE if this function has completed its task
 *                  FALSE otherwise
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
BOOL UDPProcess(NODE_INFO *remoteNode, WORD len)
{
    UDP_HEADER h;
    UDP_SOCKET s;

    /*
     * Retrieve UDP header.
     */
    MACGetArray((BYTE*)&h, sizeof(h));

    h.SourcePort        = swaps(h.SourcePort);
    h.DestinationPort   = swaps(h.DestinationPort);
    h.Length            = swaps(h.Length) - sizeof(UDP_HEADER);;
    h.Checksum          = swaps(h.Checksum);

    s = FindMatchingSocket(&h, remoteNode);
    if ( s == INVALID_UDP_SOCKET )
    {
        /*
         * If there is no matching socket, There is no one to handle
         * this data.  Discard it.
         */
        MACDiscardRx();
    }
    else
    {
        UDPSocketInfo[s].RxCount = h.Length;
        UDPSocketInfo[s].Flags.bFirstRead = TRUE;
    }


    return TRUE;
}
Beispiel #5
0
/**
 * This function discards an active UDP socket content.
 *
 * @preCondition     UDPInit() is already called    AND
 *                  UDPIsGetReady() == TRUE with desired UDP socket.
 */
void UDPDiscard(void)
{
    if ( UDPSocketInfo[activeUDPSocket].RxCount )
        MACDiscardRx(); //Discard the contents of the current RX buffer

    UDPSocketInfo[activeUDPSocket].RxCount = 0;
}
Beispiel #6
0
/******************************************************************************
 * Function:        BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
 *
 * PreCondition:    None
 *
 * Input:           *remote: Location to store the Source MAC address of the
 *							 received frame.
 *					*type: Location of a BYTE to store the constant
 *						   MAC_UNKNOWN, ETHER_IP, or ETHER_ARP, representing
 *						   the contents of the Ethernet type field.
 *
 * Output:          TRUE: If a packet was waiting in the RX buffer.  The
 *						  remote, and type values are updated.
 *					FALSE: If a packet was not pending.  remote and type are
 *						   not changed.
 *
 * Side Effects:    Last packet is discarded if MACDiscardRx() hasn't already
 *					been called.
 *
 * Overview:        None
 *
 * Note:            None
 *****************************************************************************/
BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type) {
    ENC_PREAMBLE header;

    // Test if at least one packet has been received and is waiting
    if (EPKTCNT == 0u) {

        return FALSE;
    }

    // Flag that we have received a packet so that we don't swap the RX polarity
    // anymore.
    flags.bits.bRXPolarityValid = 1;

    // Make absolutely certain that any previous packet was discarded
    if (flags.bits.bWasDiscarded == 0u) {
        MACDiscardRx();
        return FALSE;
    }
    // Save the location of this packet
    CurrentPacketLocation.Val = NextPacketLocation.Val;

    // Set the read pointer to the beginning of the next unprocessed packet
    ERDPT = CurrentPacketLocation.Val;

    // Obtain the MAC header from the Ethernet buffer
    MACGetArray((BYTE*) & header, sizeof (header));

    // The EtherType field, like most items transmitted on the Ethernet medium
    // are in big endian.
    header.Type.Val = swaps(header.Type.Val);

    // Do a sanity check.  There might be a bug in code someplace if this
    // Reset() ever happens.  Check for potential errors in array/pointer writing code.
    if (header.NextPacketPointer > RXSTOP || ((BYTE_VAL*) (&header.NextPacketPointer))->bits.b0 ||
            header.StatusVector.bits.Zero ||
            header.StatusVector.bits.CRCError ||
            header.StatusVector.bits.ByteCount > 1518u ||
            !header.StatusVector.bits.ReceiveOk) {
        Reset();
    }

    // Save the location where the hardware will write the next packet to
    NextPacketLocation.Val = header.NextPacketPointer;

    // Return the Ethernet frame's Source MAC address field to the caller
    // This parameter is useful for replying to requests without requiring an
    // ARP cycle.
    memcpy((void*) remote->v, (void*) header.SourceMACAddr.v, sizeof (*remote));

    // Return a simplified version of the EtherType field to the caller
    *type = MAC_UNKNOWN;
    if ((header.Type.v[1] == 0x08u) &&
            ((header.Type.v[0] == ETHER_IP) || (header.Type.v[0] == ETHER_ARP))) {
        *type = header.Type.v[0];
    }

    // Mark this packet as discardable
    flags.bits.bWasDiscarded = 0;
    return TRUE;
}
Beispiel #7
0
/*****************************************************************************
  Function:
	void UDPDiscard(void)

  Summary:
	Discards any remaining RX data from a UDP socket.
	
  Description:
	This function discards any remaining received data in the currently 
	active UDP socket.

  Precondition:
	UDPIsGetReady() was previously called to select the currently active
	socket.

  Parameters:
	None
	
  Returns:
  	None

  Remarks:
	It is safe to call this function more than is necessary.  If no data is
	available, this function does nothing.
  ***************************************************************************/
void UDPDiscard(void)
{
	if(!Flags.bWasDiscarded)
	{
		MACDiscardRx();
		UDPRxCount = 0;
		SocketWithRxData = INVALID_UDP_SOCKET;
		Flags.bWasDiscarded = 1;
	}
}
Beispiel #8
0
/*********************************************************************
 * Function:        BOOL ARPGet(NODE_INFO* remote, BYTE* opCode)
 *
 * PreCondition:    ARP packet is ready in MAC buffer.
 *
 * Input:           remote  - Remote node info
 *                  opCode  - Buffer to hold ARP op code.
 *
 * Output:          TRUE if a valid ARP packet was received.
 *                  FALSE otherwise.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
int1 ARPGet(NODE_INFO *remote, int8 *opCode)
{
    ARP_PACKET packet;

    //MACGetArray((int8*)&packet, sizeof(packet));
    MACGetArray(&packet, sizeof(ARP_PACKET));

    MACDiscardRx();

    SwapARPPacket(&packet);

   debug_arp("\r\nARP: HW:%LX PR:%LX ML:%U PL:%U O:%LX TI:%U.%U.%U.%U FI:%U.%U.%U.%U",
      packet.HardwareType, packet.Protocol, packet.MACAddrLen, packet.ProtocolLen,
      packet.Operation, packet.TargetIPAddr.v[0],packet.TargetIPAddr.v[1],
      packet.TargetIPAddr.v[2],packet.TargetIPAddr.v[3],
      packet.SenderIPAddr.v[0],packet.SenderIPAddr.v[1],packet.SenderIPAddr.v[2],packet.SenderIPAddr.v[3]);

    if ( packet.HardwareType != HW_ETHERNET     ||
         packet.MACAddrLen != sizeof(MAC_ADDR)  ||
         packet.ProtocolLen != sizeof(IP_ADDR) )
         return FALSE;

    if ( packet.Operation == ARP_OPERATION_RESP )
        *opCode = ARP_REPLY;
    else if ( packet.Operation == ARP_OPERATION_REQ )
        *opCode = ARP_REQUEST;
    else
    {
        *opCode = ARP_UNKNOWN;
        return FALSE;
    }

    if(packet.TargetIPAddr.Val == AppConfig.MyIPAddr.Val)
    {
        remote->MACAddr     = packet.SenderMACAddr;
        remote->IPAddr      = packet.SenderIPAddr;
        return TRUE;
    }
    else
        return FALSE;
}
Beispiel #9
0
/*********************************************************************
 * Function:        BOOL ARPGet(NODE_INFO* remote, BYTE* opCode)
 *
 * PreCondition:    ARP packet is ready in MAC buffer.
 *
 * Input:           remote  - Remote node info
 *                  opCode  - Buffer to hold ARP op code.
 *
 * Output:          TRUE if a valid ARP packet was received.
 *                  FALSE otherwise.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
BOOL ARPGet(NODE_INFO *remote, BYTE *opCode)
{
    ARP_PACKET packet;

    MACGetArray((BYTE*)&packet, sizeof(packet));

    MACDiscardRx();

    SwapARPPacket(&packet);

    if ( packet.HardwareType != HW_ETHERNET     ||
         packet.MACAddrLen != sizeof(MAC_ADDR)  ||
         packet.ProtocolLen != sizeof(IP_ADDR) )
    {
         return FALSE;
    }

    if ( packet.Operation == ARP_OPERATION_RESP )
    {   
        *opCode = ARP_REPLY;
    }
    else if ( packet.Operation == ARP_OPERATION_REQ )
        *opCode = ARP_REQUEST;
    else
    {
        *opCode = ARP_UNKNOWN;
        return FALSE;
    }

    if(packet.TargetIPAddr.Val == AppConfig.MyIPAddr.Val)
    {
        remote->MACAddr     = packet.SenderMACAddr;
        remote->IPAddr      = packet.SenderIPAddr;
        return TRUE;
    }
    else
        return FALSE;
}
BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len)
{
    UDP_HEADER h;
    UDP_SOCKET s;
    UDP_PSEUDO_HEADER pseudoHeader;
    WORD_VAL   checksum;

    /*
     * Retrieve UDP header.
     */
    //MACGetArray((BYTE*)&h, sizeof(h));
    MACGetArray(&h, sizeof(UDP_HEADER));

    h.SourcePort        = swaps(h.SourcePort);
    h.DestinationPort   = swaps(h.DestinationPort);
    h.Length            = swaps(h.Length) - sizeof(UDP_HEADER);

      debug_udp("\r\nUDP PROCESS SP=%LX DP=%LX PAYLOAD=%LX ",
            h.SourcePort,
            h.DestinationPort,
            h.Length
         );

   // See if we need to validate the checksum field (0x0000 is disabled)
   if(h.Checksum)
   {
       h.Checksum          = swaps(h.Checksum);

       // Calculate IP pseudoheader checksum.
       pseudoHeader.SourceAddress      = remoteNode->IPAddr;
       pseudoHeader.DestAddress.v[0]   = localIP->v[0];
       pseudoHeader.DestAddress.v[1]   = localIP->v[1];
       pseudoHeader.DestAddress.v[2]   = localIP->v[2];
       pseudoHeader.DestAddress.v[3]   = localIP->v[3];
       pseudoHeader.Zero               = 0x0;
       pseudoHeader.Protocol           = IP_PROT_UDP;
       pseudoHeader.Length             = len;

       SwapPseudoHeader(pseudoHeader);

       checksum.Val = ~CalcIPChecksum(&pseudoHeader,
                                       sizeof(pseudoHeader));


       // Set UDP packet checksum = pseudo header checksum in MAC RAM.
       IPSetRxBuffer(6);
       MACPut(checksum.v[0]);
      // In case if the end of the RX buffer is reached and a wraparound is needed, set the next address to prevent writing to the wrong address.
       IPSetRxBuffer(7);
       MACPut(checksum.v[1]);
       IPSetRxBuffer(0);

       // Now calculate UDP packet checksum in NIC RAM - including
       // pesudo header.
       checksum.Val = CalcIPBufferChecksum(len);

       if ( checksum.Val != h.Checksum )
       {
           debug_udp("INVALID-CS ");
           MACDiscardRx();
           return TRUE;
       }
   }

    s = FindMatching_UDP_Socket(&h, remoteNode, localIP);
    if ( s == INVALID_UDP_SOCKET )
    {
        /*
         * If there is no matching socket, There is no one to handle
         * this data.  Discard it.
         */
        debug_udp("INVALID-SOCKET ");
        MACDiscardRx();
    }
    else {
        UDPSocketInfo[s].RxCount = h.Length;
        UDPSocketInfo[s].Flags.bFirstRead = TRUE;

    debug_udp("MATCH AS:%U ", s);
    /*debug_udp("MAC-%X:%X:%X:%X:%X:%X",
         remoteNode->MACAddr.v[0],
         remoteNode->MACAddr.v[1],
         remoteNode->MACAddr.v[2],
         remoteNode->MACAddr.v[3],
         remoteNode->MACAddr.v[4],
         remoteNode->MACAddr.v[5]
      );*/
    }

    return TRUE;
}
Beispiel #11
0
/*****************************************************************************
  Function:
	BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len)

  Summary:
	Handles an incoming UDP segment.
	
  Description:
	This function handles an incoming UDP segment to determine if it is 
	acceptable and should be handed to one of the stack applications for
	processing.

  Precondition:
	UDPInit() has been called an a UDP segment is ready in the MAC buffer.

  Parameters:
	remoteNode - The remote node that sent this segment.
	localIP - The destination IP address for this segment.
	len - Total length of the UDP segment.
	
  Return Values:
  	TRUE - A valid packet is waiting and the stack applications should be
  		called to handle it.
  	FALSE - The packet was discarded.
  ***************************************************************************/
BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len)
{
    UDP_HEADER		h;
    UDP_SOCKET		s;
    PSEUDO_HEADER	pseudoHeader;
    DWORD_VAL		checksums;

	UDPRxCount = 0;

    // Retrieve UDP header.
    MACGetArray((BYTE*)&h, sizeof(h));

    h.SourcePort        = swaps(h.SourcePort);
    h.DestinationPort   = swaps(h.DestinationPort);
    h.Length            = swaps(h.Length) - sizeof(UDP_HEADER);

	// See if we need to validate the checksum field (0x0000 is disabled)
	if(h.Checksum)
	{
	    // Calculate IP pseudoheader checksum.
	    pseudoHeader.SourceAddress		= remoteNode->IPAddr;
	    pseudoHeader.DestAddress.Val	= localIP->Val;
	    pseudoHeader.Zero				= 0x0;
	    pseudoHeader.Protocol			= IP_PROT_UDP;
	    pseudoHeader.Length				= len;

	    SwapPseudoHeader(pseudoHeader);
	
	    checksums.w[0] = ~CalcIPChecksum((BYTE*)&pseudoHeader,
	                                    sizeof(pseudoHeader));
	
	
	    // Now calculate UDP packet checksum in NIC RAM -- should match pseudoHeader
	    IPSetRxBuffer(0);
	    checksums.w[1] = CalcIPBufferChecksum(len);
	
	    if(checksums.w[0] != checksums.w[1])
	    {
	        MACDiscardRx();
	        return FALSE;
	    }
	}

    s = FindMatchingSocket(&h, remoteNode, localIP);
    if(s == INVALID_UDP_SOCKET)
    {
        // If there is no matching socket, There is no one to handle
        // this data.  Discard it.
        MACDiscardRx();
		return FALSE;
    }
    else
    {
		SocketWithRxData = s;
        UDPRxCount = h.Length;
        Flags.bFirstRead = 1;
		Flags.bWasDiscarded = 0;
    }


    return TRUE;
}
/**
 * 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();
}
Beispiel #13
0
/******************************************************************************
 * 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
}
Beispiel #14
0
/**
 * Performs UDP related tasks. Must continuesly be called.
 *
 * @preCondition    UDPInit() is already called AND <br>
 *                  UDP segment is ready in MAC buffer
 *
 * @param remoteNode    Remote node info
 * @param len           Total length of UDP semgent
 * @param destIP        The Destination IP Address of the currently received packet
 *
 * @return          TRUE if this function has completed its task <br>
 *                  FALSE otherwise
 */
BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *destIP, WORD len)
{
    UDP_HEADER h;
    UDP_SOCKET s;
    PSEUDO_HEADER   pseudoHeader;
    WORD_VAL        checksum;
    #if defined(UDP_SPEED_OPTIMIZE)
    BYTE temp;
    #endif

    //Retrieve UDP header. The data is read from the current MAC RX Buffer
    MACGetArray((BYTE*)&h, sizeof(h));

    #if defined(UDP_SPEED_OPTIMIZE)
        temp                    = h.SourcePort.v[0];
        h.SourcePort.v[0]       = h.SourcePort.v[1];
        h.SourcePort.v[1]       = temp;

        temp                    = h.DestinationPort.v[0];
        h.DestinationPort.v[0]  = h.DestinationPort.v[1];
        h.DestinationPort.v[1]  = temp;

        //Will an overflow occur after the subtraction?
        if ((BYTE)sizeof(UDP_HEADER) > h.Length.v[1]) {
            temp                = h.Length.v[0] - 1;
        }
        else {
            temp                = h.Length.v[0];
        }
        h.Length.v[0]           = h.Length.v[1] - (BYTE)sizeof(UDP_HEADER);
        h.Length.v[1]           = temp;
    #else
        h.SourcePort.Val        = swaps(h.SourcePort.Val);
        h.DestinationPort.Val   = swaps(h.DestinationPort.Val);
        h.Length.Val            = swaps(h.Length.Val) - sizeof(UDP_HEADER);
    #endif

    // See if we need to validate the checksum field (0x0000 is disabled)
    if(h.Checksum.Val)
    {
        #if defined(UDP_SPEED_OPTIMIZE)
            temp                    = h.Checksum.v[0];
            h.Checksum.v[0]         = h.Checksum.v[1];
            h.Checksum.v[1]         = temp;
        #else
            h.Checksum.Val          = swaps(h.Checksum.Val);
        #endif

        // Calculate IP pseudoheader checksum.
        pseudoHeader.SourceAddress      = remoteNode->IPAddr;
        pseudoHeader.DestAddress.v[0]   = destIP->v[0];
        pseudoHeader.DestAddress.v[1]   = destIP->v[1];
        pseudoHeader.DestAddress.v[2]   = destIP->v[2];
        pseudoHeader.DestAddress.v[3]   = destIP->v[3];
        pseudoHeader.Zero               = 0x0;
        pseudoHeader.Protocol           = IP_PROT_UDP;
        pseudoHeader.Length             = len;

        SwapPseudoHeader(pseudoHeader);

        checksum.Val = ~CalcIPChecksum((BYTE*)&pseudoHeader,
                                        sizeof(pseudoHeader));


        // Set UCP packet checksum = pseudo header checksum in MAC RAM.
        IPSetRxBuffer(6);
        MACPut(checksum.v[0]);
        // In case if the end of the RX buffer is reached and a wraparound is needed, set the next address to prevent writing to the wrong address.
        IPSetRxBuffer(7);
        MACPut(checksum.v[1]);
        IPSetRxBuffer(0);   //Set current receive buffer access pointer to first byte of IP data = first byte of TCP header

        // Now calculate UDP packet checksum in NIC RAM - including
        // pesudo header.
        checksum.Val = CalcIPBufferChecksum(len);

        if ( checksum.Val != h.Checksum.Val )
        {
            MACDiscardRx(); //Discard the contents of the current RX buffer
            return TRUE;
        }
    }

    s = FindMatchingSocket(&h, remoteNode, destIP);
    if ( s == INVALID_UDP_SOCKET )
    {
         // If there is no matching socket, There is no one to handle
         // this data.  Discard it.
        MACDiscardRx(); //Discard the contents of the current RX buffer
    }
    else
    {
        UDPSocketInfo[s].RxCount = h.Length.Val;
        UDPSocketInfo[s].Flags.bFirstRead = TRUE;
    }

    return TRUE;
}
Beispiel #15
0
/*****************************************************************************
  Function:
    bool ARPProcess(void)

  Summary:
    Processes an incoming ARP packet.

  Description:
    Retrieves an ARP packet from the MAC buffer and determines if it is a
    response to our request (in which case the ARP is resolved) or if it
    is a request requiring our response (in which case we transmit one.)

  Precondition:
    ARP packet is ready in the MAC buffer.

  Parameters:
    None

  Return Values:
    true - All processing of this ARP packet is complete.  Do not call
            again until a new ARP packet is waiting in the RX buffer.
    false - This function must be called again.  More time is needed to
            send an ARP response.
  ***************************************************************************/
bool ARPProcess(void)
{
    ARP_PACKET packet;
    static NODE_INFO Target;
    #if defined(STACK_USE_AUTO_IP)
        uint8_t i;
    #endif
    static enum
    {
        SM_ARP_IDLE = 0,
        SM_ARP_REPLY
    } smARP = SM_ARP_IDLE;

    switch(smARP)
    {
        case SM_ARP_IDLE:
            // Obtain the incoming ARP packet
            MACGetArray((uint8_t*)&packet, sizeof(packet));
            MACDiscardRx();
            SwapARPPacket(&packet);

            // Validate the ARP packet
            if ( packet.HardwareType != HW_ETHERNET     ||
                 packet.MACAddrLen != sizeof(MAC_ADDR)  ||
                 packet.ProtocolLen != sizeof(IP_ADDR) )
            {
                 return true;
            }
#ifdef STACK_USE_ZEROCONF_LINK_LOCAL
            ARPProcessRxPkt(&packet);
#endif

#ifdef STACK_USE_AUTO_IP
            if (packet.SenderIPAddr.Val == AppConfig.MyIPAddr.Val)
            {
                AutoIPConflict(0);
                return true;
            }
#endif

            // Handle incoming ARP responses
#ifdef STACK_CLIENT_MODE
            if(packet.Operation == ARP_OPERATION_RESP)
            {
/*                #if defined(STACK_USE_AUTO_IP)
                for (i = 0; i < NETWORK_INTERFACES; i++)
                    if (AutoIPConfigIsInProgress(i))
                        AutoIPConflict(i);
                #endif*/
                Cache.MACAddr = packet.SenderMACAddr;
                Cache.IPAddr = packet.SenderIPAddr;

                //putsUART("ARPProcess: SM_ARP_IDLE: ARP_OPERATION_RESP  \r\n");
                return true;
            }
#endif

            // Handle incoming ARP requests for our MAC address
            if(packet.Operation == ARP_OPERATION_REQ)
            {
                if(packet.TargetIPAddr.Val != AppConfig.MyIPAddr.Val)
                {
                    return true;
                }
#ifdef STACK_USE_ZEROCONF_LINK_LOCAL
                               /* Fix for Loop-Back suppression:
                                * For ZCLL-Claim packets, host should not respond.
                                * Check Sender's MAC-address with own MAC-address and
                                * if it is matched, response will not be sent back. This
                                * was leading to flooding of ARP-answeres */
                                if(!memcmp (&packet.SenderMACAddr, &AppConfig.MyMACAddr, 6))
                                {
                                     putsUART("Loopback answer suppressed \r\n");
                                     return true;
                                }
#endif
                #if defined(STACK_USE_AUTO_IP)
                for (i = 0; i < NETWORK_INTERFACES; i++)
                    if (AutoIPConfigIsInProgress(i))
                    {
                        AutoIPConflict(i);
                        return true;
                    }
                #endif
                Target.IPAddr = packet.SenderIPAddr;
                Target.MACAddr = packet.SenderMACAddr;

                //putsUART("ARPProcess: SM_ARP_IDLE: ARP_OPERATION_REQ  \r\n");

                smARP = SM_ARP_REPLY;
            }
            // Do not break.  If we get down here, we need to send a reply.

        case SM_ARP_REPLY:
            packet.Operation        = ARP_OPERATION_RESP;
            #if defined(STACK_USE_AUTO_IP)
            if (AutoIPIsConfigured(0))
            {
                packet.TargetMACAddr.v[0] = 0xFF;
                packet.TargetMACAddr.v[1] = 0xFF;
                packet.TargetMACAddr.v[2] = 0xFF;
                packet.TargetMACAddr.v[3] = 0xFF;
                packet.TargetMACAddr.v[4] = 0xFF;
                packet.TargetMACAddr.v[5] = 0xFF;
            }
            else
            #endif
                packet.TargetMACAddr    = Target.MACAddr;
            packet.TargetIPAddr     = Target.IPAddr;
#ifdef STACK_USE_ZEROCONF_LINK_LOCAL
            packet.SenderIPAddr     = AppConfig.MyIPAddr;
#endif
            //putsUART("ARPProcess: SM_ARP_REPLY  \r\n");

            // Send an ARP response to a previously received request
            if(!ARPPut(&packet))
            {
               return false;
            }

            // Begin listening for ARP requests again
            smARP = SM_ARP_IDLE;
            break;
    }

    return true;
}
int1 MACGetHeader(MAC_ADDR *remote, int8* type)
{
    NE_PREAMBLE     header;
    int8 NICWritePtr;
    WORD_VAL temp;

    *type = MAC_UNKNOWN;

    // Reset NIC if overrun has occured.
    if ( NICGet(ISR) & 0x10 )
    {
#if 1
        NICPut(CMDR, 0x21);
        Delay(0xff);
        NICPut(RBCR0, 0);
        NICPut(RBCR1, 0);
        NICPut(TCR, 0x02);
        NICPut(CMDR, 0x20);
        MACDiscardRx();
        NICPut(ISR, 0xff);
        NICPut(TCR, 0x00);
        return FALSE;
#else
        MACInit();
        return FALSE;
#endif
    }

    NICPut(CMDR, 0x60);
    NICWritePtr = NICGet(CURRP);
    NICPut(CMDR, 0x20);

    if ( NICWritePtr != NICReadPtr )
    {
        temp.v[1] = NICReadPtr;
        temp.v[0] = 0;
        NICSetAddr(temp.Val);

        //MACGetArray((int8*)&header, sizeof(header));

        debug("\r\n***************************************\r\n");

         MACGetArray(&header, sizeof(NE_PREAMBLE));

        debug(debug_putc,"\r\n\r\nGOT HDR = ST:%X NPP:%X LEN:%LU",
          (int8)header.Status,header.NextPacketPointer,header.ReceivedBytes);
        debug(debug_putc,"\r\n  DEST: %X.%X.%X.%X.%X.%X  SRC: %X.%X.%X.%X.%X.%X  TYPE:%LX",
            header.DestMACAddr.v[0],header.DestMACAddr.v[1],header.DestMACAddr.v[2],
            header.DestMACAddr.v[3],header.DestMACAddr.v[4],header.DestMACAddr.v[5],
            header.SourceMACAddr.v[0],header.SourceMACAddr.v[1],header.SourceMACAddr.v[2],
            header.SourceMACAddr.v[3],header.SourceMACAddr.v[4],header.SourceMACAddr.v[5],
            header.Type.Val);


        // Validate packet length and status.
        if ( header.Status.PRX && (header.ReceivedBytes >= MINFRAMEC) && (header.ReceivedBytes <= MAXFRAMEC) )
        {
            debug(debug_putc," VALID");
            header.Type.Val = swaps(header.Type.Val);

            //memcpy((char*)remote->v, (char*)header.SourceMACAddr.v, sizeof(*remote));
            memcpy(&remote->v[0], &header.SourceMACAddr.v[0], sizeof(MAC_ADDR));

            if ( (header.Type.v[1] == 0x08) && ((header.Type.v[0] == ETHER_IP) || (header.Type.v[0] == ETHER_ARP)) )
                *type = header.Type.v[0];

        }

        NICCurrentRdPtr = NICReadPtr;
        NICReadPtr = header.NextPacketPointer;

        return TRUE;
    }
    return FALSE;

}
Beispiel #17
0
BOOL    MACGetHeader(MAC_ADDR *remote, BYTE* type)
{
    /*
     * This marks that all future accesses to MACGet and MACPut
     * be applied to Receive buffer.
     */
    bIsRxActive = TRUE;

    if ( RxBuffer.PacketCount )
    {

        /*
         * Set up packet access index.
         */
        RxBuffer.CallerAccess = RxBuffer.CurrentPacket;

        RxBuffer.CallerAccess++;
        if ( RxBuffer.CallerAccess >= MAX_SLIP_BUFFER_SIZE )
            RxBuffer.CallerAccess = 0;


        /*
         * Handle modem commands differently.
         */
        if ( RxBuffer.Data[RxBuffer.CallerAccess] == 'A' )
        {
            /*
             * Once a modem command is detected, we are not interested
             * in detail.
             */
            MACDiscardRx(); //Discard the contents of the current RX buffer

            /*
             * Mark TxBuffer for Modem String.
             * This will make sure that Transmit ISR does nottransmit END
             * at the end.
             */
            TxBuffer.Flags.bits.bIsModemString = TRUE;

            /*
             * Since this special handling does not follow standard
             * SLIP buffer logic, we will setup all required variables
             * manually.
             */
            TxBuffer.Length = 4;
            TxBuffer.CallerAccess = 0;

            /*
             * Remember to use transmit buffer for MACPut
             */
            bIsRxActive = FALSE;

            /*
             * Now load modem response.
             */
            MACPut('O');
            MACPut('K');
            MACPut('\r');
            MACPut('\n');

            /*
             * Transmit it.
             */
            MACFlush();
        }
        else
        {
            /*
             * This was not a modem command.
             * It must be IP packet.  Mark it accordingly and return.
             */
            *type = MAC_IP;

            return TRUE;
        }
    }
    return FALSE;
}
Beispiel #18
0
/*****************************************************************************
  Function:
    ARP_RESULT ARPProcess(NET_CONFIG* pIf)

  Summary:
    Processes an incoming ARP packet.

  Description:
    Retrieves an ARP packet from the MAC buffer and determines if it is a
    response to our request (in which case the ARP is resolved) or if it
    is a request requiring our response (in which case we transmit one.)

  Precondition:
    ARP packet is ready in the MAC buffer.

  Parameters:
    None

  Return Values:
    ARP_RES_OK      - processing OK.
    ARP_RES_error   - some error occurred
  ***************************************************************************/
ARP_RESULT ARPProcess(NET_CONFIG* pIf)
{
    ARP_PACKET      packet;
    MAC_ADDR        *dstMAC;
    OA_HASH_ENTRY   *hE;
    ARP_CACHE_DCPT  *pArpDcpt;
    int              netIx;
    TCPIP_MAC_HANDLE hMac;
    ARP_RESULT       arpReqRes;

    netIx = _TCPIPStackNetIx(pIf);
    pArpDcpt = arpCache + netIx;
    hMac = _TCPIPStackNetToMac(pIf);

    // Obtain the incoming ARP packet and process
    MACGetArray(hMac, (uint8_t*)&packet, sizeof(packet));
    MACDiscardRx(hMac);
    SwapARPPacket(&packet);

    // Validate the ARP packet
    if ( packet.HardwareType != HW_ETHERNET     ||
            packet.MACAddrLen != sizeof(MAC_ADDR)  ||
            packet.ProtocolLen != sizeof(IP_ADDR) )
    {
        return ARP_RES_OK;
    }
#ifdef TCPIP_STACK_USE_ZEROCONF_LINK_LOCAL
    ARPProcessRxPkt(pIf, &packet);
#endif

    arpReqRes = ARP_RES_OK;
    // Handle incoming ARP packet
    hE = OAHashLookUp(pArpDcpt->cacheDcpt, &packet.SenderIPAddr.Val);
    if(hE != 0)
    {   // we already have this sender and we should update it
        _ARPUpdateEntry(pIf, (ARP_HASH_ENTRY*)hE, &packet.SenderMACAddr);
    }

    while(packet.TargetIPAddr.Val == pIf->MyIPAddr.Val)
    {   // we are the target and we should add to cache anyway
        if(hE == 0)
        {   // not there yet
            arpReqRes = _ARPAddCompleteEntry(pIf, &packet.SenderIPAddr, &packet.SenderMACAddr);
        }

        // Handle incoming ARP operation
        if(packet.Operation == ARP_OPERATION_REQ)
        {
            // ARP packet asking for this host IP address
#ifdef TCPIP_STACK_USE_ZEROCONF_LINK_LOCAL
            /* Fix for Loop-Back suppression:
             * For ZCLL-Claim packets, host should not respond.
             * Check Sender's MAC-address with own MAC-address and
             * if it is matched, response will not be sent back. This
             * was leading to flooding of ARP-answeres */
            if(!memcmp (&packet.SenderMACAddr, &pIf->MyMACAddr, 6))
            {
                SYS_CONSOLE_MESSAGE("Loopback answer suppressed \r\n");
                break;
            }
#endif
#if defined(TCPIP_STACK_USE_AUTO_IP)
            if ((packet.SenderIPAddr.Val == pIf->MyIPAddr.Val) || AutoIPConfigIsInProgress(pIf))
            {
                AutoIPConflict(pIf);
                break;
            }
#endif

            // Need to send a reply to the requestor
#if defined(TCPIP_STACK_USE_AUTO_IP)
            if (AutoIPIsConfigured(pIf))
            {
                dstMAC = &arpBcastAdd;
            }
            else
#endif
            {
                dstMAC = &packet.SenderMACAddr;
            }
            // Send an ARP response to the received request
            if(!ARP_SendIfPkt(pIf, ARP_OPERATION_RESP, (uint32_t)pIf->MyIPAddr.Val, (uint32_t)packet.SenderIPAddr.Val, dstMAC))
            {
                arpReqRes =  ARP_RES_TX_FAILED;
            }
        }
        break;
    }

    return arpReqRes;
}