Example #1
0
/*********************************************************************
 * Function:        BYTE TFTPGet(void)
 *
 * PreCondition:    TFTPOpenFile() is called with TFTP_FILE_MODE_READ
 *                  and TFTPIsGetReady() = TRUE
 *
 * Input:           None
 *
 * Output:          data byte as received from remote server.
 *
 * Side Effects:    None
 *
 * Overview:        Fetches next data byte from TFTP socket.
 *                  If end of data block is reached, it issues
 *                  ack to server so that next data block can be
 *                  received.
 *
 * Note:            Use this function to read file from server.
 ********************************************************************/
BYTE TFTPGet(void)
{
    BYTE v;

    // Read byte from UDP
    UDPGet(&v);

    // Update block length
    MutExVar.group2._tftpBlockLength.Val++;

    // Check to see if entire data block is fetched.
    // To reduce code, MSB is compared for 0x02 (of 0x200 = 512).
    if ( MutExVar.group2._tftpBlockLength.byte.MSB == TFTP_BLOCK_SIZE_MSB )
    {
        // Entire block was fetched.  Discard everything else.
        UDPDiscard();

        // Remember that we have flushed this block.
        _tftpFlags.bits.bIsFlushed = TRUE;

        // Reset block length.
        MutExVar.group2._tftpBlockLength.Val = 0;

        // Must send ACK to receive next block.
        _tftpState = SM_TFTP_SEND_ACK;
    }

    return v;
}
Example #2
0
/*********************************************************************
 * Function:        void RebootTask(void)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Checks for incomming traffic on port 69.  
 *					Resets the PIC if a 'R' is received.
 *
 * Note:            This module is primarily for use with the 
 *					Ethernet bootloader.  By resetting, the Ethernet 
 *					bootloader can take control for a second and let
 *					a firmware upgrade take place.
 ********************************************************************/
void RebootTask(void)
{
	static UDP_SOCKET	MySocket = INVALID_UDP_SOCKET;
	struct
	{
		BYTE vMACAddress[6];
		DWORD dwIPAddress;
		WORD wChecksum;
	} BootloaderAddress;
	
	if(MySocket == INVALID_UDP_SOCKET)
		MySocket = UDPOpenEx(0,UDP_OPEN_SERVER,REBOOT_PORT,INVALID_UDP_PORT);
//		MySocket = UDPOpen(REBOOT_PORT, NULL, INVALID_UDP_PORT);

	if(MySocket == INVALID_UDP_SOCKET)
		return;

	// Do nothing if no data is waiting
	if(!UDPIsGetReady(MySocket))
		return;

	#if defined(REBOOT_SAME_SUBNET_ONLY)
		// Respond only to name requests sent to us from nodes on the same subnet
     	if((remoteNode.IPAddr.Val & AppConfig.MyMask.Val) != (AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val))
		{
			UDPDiscard();
			return;
		}
	#endif

	// Get our MAC address, IP address, and compute a checksum of them 
	memcpy((void*)&BootloaderAddress.vMACAddress[0], (void*)&AppConfig.MyMACAddr.v[0], sizeof(AppConfig.MyMACAddr));
	BootloaderAddress.dwIPAddress = AppConfig.MyIPAddr.Val;
	BootloaderAddress.wChecksum = CalcIPChecksum((BYTE*)&BootloaderAddress, sizeof(BootloaderAddress) - sizeof(BootloaderAddress.wChecksum));
	
	// To enter the bootloader, we need to clear the /POR bit in RCON.
	// Otherwise, the bootloader will immediately hand off execution 
	// to us.
	#if defined(USE_LCD)
		strcpypgm2ram((char*)LCDText, "Bootloader Reset");
		LCDUpdate();
	#endif

#if !defined(__STM32F10X__)
	RCONbits.POR = 0;
	#if defined(__18CXX)
	{
		WORD_VAL wvPROD;

		wvPROD.Val = ((WORD)&BootloaderAddress);
		PRODH = wvPROD.v[1];
		PRODL = wvPROD.v[0];
	}
	#endif
#endif
	Reset();
}
Example #3
0
/*********************************************************************
 * Function:        void TFTPCloseFile(void)
 *
 * Summary:         Sends file closing messages.
 *
 * PreCondition:    TFTPOpenFile() was called and TFTPIsFileOpened()
 *                  had returned with TFTP_OK.
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        If file is opened in read mode, it makes sure
 *                  that last ACK is sent to server
 *                  If file is opened in write mode, it makes sure
 *                  that last block is sent out to server and
 *                  waits for server to respond with ACK.
 *
 * Note:            TFTPIsFileClosed() must be called to confirm
 *                  if file was really closed.
 ********************************************************************/
void TFTPCloseFile(void)
{
    // If a file was opened for read, we can close it immediately.
    if ( _tftpFlags.bits.bIsReading )
    {
        // If this was premature close, make sure that we discard
        // current block.
        if ( !_tftpFlags.bits.bIsFlushed )
        {
            _tftpFlags.bits.bIsFlushed = TRUE;
            UDPIsGetReady(_tftpSocket);
            UDPDiscard();
        }

        if ( _tftpFlags.bits.bIsAcked )
        {
            _tftpFlags.bits.bIsClosed = TRUE;
            _tftpFlags.bits.bIsClosing = FALSE;
            return;
        }

        else
        {
            _tftpState = SM_TFTP_SEND_LAST_ACK;
            _tftpFlags.bits.bIsClosing = TRUE;
        }
        return;
    }

    // For write mode, if we have not flushed last block, do it now.
    if ( !_tftpFlags.bits.bIsFlushed )
    {
        _tftpFlags.bits.bIsFlushed = TRUE;
        UDPIsPutReady(_tftpSocket);
        UDPFlush();
    }

    // For write mode, if our last block was ack'ed by remote server,
    // file is said to be closed.
    if ( _tftpFlags.bits.bIsAcked )
    {
        _tftpFlags.bits.bIsClosed = TRUE;
        _tftpFlags.bits.bIsClosing = FALSE;
        return;
    }

    _tftpState = SM_TFTP_WAIT_FOR_ACK;
    _tftpFlags.bits.bIsClosing =  TRUE;

}
Example #4
0
/****************************************************************************
  Function:
   void ChipKITUDPClose(UDP_SOCKET hUDP)

  Description:
    reads the available bytes out of the UDP cache
 
  Parameters:
    hUDP        - the UDP socket to clsoe

 
  Returns:
    None
  Remarks:
    The socket is closed and the resources returned to the UDP stack. Also the cache buffers are released and freed.

  ***************************************************************************/
void ChipKITUDPClose(UDP_SOCKET hUDP)
{
    if(UDPIsGetReady(hUDP) > 0)
    {
        UDPDiscard();
    }

    UDPClose(hUDP);

	// delete our cache buffer
	if(rgUDPSocketBuffers[hUDP] != NULL)
	{
		free(rgUDPSocketBuffers[hUDP]);
		rgUDPSocketBuffers[hUDP] = NULL;
	}
}
Example #5
0
/*********************************************************************
 * Function:        void RebootTask(NET_CONFIG* pConfig)
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           pConfig   - interface 
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Checks for incomming traffic on port 69.  
 *					Resets the PIC if a 'R' is received.
 *
 * Note:            This module is primarily for use with the 
 *					Ethernet bootloader.  By resetting, the Ethernet 
 *					bootloader can take control for a second and let
 *					a firmware upgrade take place.
 ********************************************************************/
void RebootTask(NET_CONFIG* pConfig)
{
	struct
	{
		uint8_t vMACAddress[6];
		uint32_t dwIPAddress;
		uint16_t wChecksum;
	} BootloaderAddress;
    int netIx;

    netIx = _TCPIPStackNetIx(pConfig);

	
	if(MySocket[netIx] == INVALID_UDP_SOCKET)
    {
        MySocket[netIx] = UDPOpen(0,UDP_OPEN_SERVER,REBOOT_PORT,INVALID_UDP_PORT);

        if(MySocket[netIx] == INVALID_UDP_SOCKET)
        {
            return;
        }
        UDPSocketSetNet(MySocket[netIx], pConfig);
    }

	// Do nothing if no data is waiting
	if(!UDPIsGetReady(MySocket[netIx]))
		return;
    
	#if defined(REBOOT_SAME_SUBNET_ONLY)
		// Respond only to name requests sent to us from nodes on the same subnet
     	if((remoteNode.IPAddr.Val & pConfig->MyMask.Val) != (pConfig->MyIPAddr.Val & pConfig->MyMask.Val))
		{
			UDPDiscard(pConfig);
			return;
		}
	#endif

	// Get our MAC address, IP address, and compute a checksum of them 
	memcpy((void*)&BootloaderAddress.vMACAddress[0], (void*)&pConfig->MyMACAddr.v[0], sizeof(pConfig->MyMACAddr));
	BootloaderAddress.dwIPAddress = pConfig->MyIPAddr.Val;
	BootloaderAddress.wChecksum = CalcIPChecksum((uint8_t*)&BootloaderAddress, sizeof(BootloaderAddress) - sizeof(BootloaderAddress.wChecksum));
	
	// To enter the bootloader, we reset the system
	SYS_OUT_MESSAGE("Bootloader Reset");

	SYS_Reboot();
}
Example #6
0
/***	void UdpServer::close(void)
**
**	Synopsis:   
**      Stops Listening and closes all unaccepted sockets
**      and clears everything back to it's originally constructed state.
**      The datagram cache buffers remain in use as this is specified on the constuctor
**
**	Parameters:
**      None
**
**	Return Values:
**      None
**
**	Errors:
**      None
**
**  Notes:
**
**      Returns the UdpServer instance to 
**      a state just as if the instance had just been
**      constructed. It also, Close all connections
**      and releases all resources (sockets).
**
*/
void UdpServer::close(void)
{
    stopListening();

    for(int i = 0; i < _cMaxPendingAllowed; i++)
    {
        if(_rghUDP[i] < INVALID_UDP_SOCKET)
        {
            // clean out the buffer
            UDPIsGetReady(_rghUDP[i]);
            UDPDiscard();
            UDPClose(_rghUDP[i]);
            ExchangeCacheBuffer(_rghUDP[i], NULL, 0);
            _rghUDP[i] = INVALID_UDP_SOCKET;
        }
    }

    clear();
}
Example #7
0
/***	void UdpServer::stopListening(void)
**
**	Synopsis:   
**      This stops listening on the server port, but does not shutdown UdpServer
**
**	Parameters:
**     None
**
**	Return Values:
**      None
**
**	Errors:
**      None
**
**  Notes:
**      To resume listening, just call ResumeListening
**      This is a soft stop listening in that only the server stops listening on the port
**      however the instance is still valid and you can continue to accept pending client.
**      and you can resume the listening.
**
*/
void UdpServer::stopListening(void)
{
   // DO NOT blow away pending clients.
   // that will be done on a close()
   // update the pending count so we have them all.
    availableClients();

   // blow away any listening socket
   if(_cPending < _cPendingMax && _rghUDP[_cPending] < INVALID_UDP_SOCKET)
    {
        UDPIsGetReady(_rghUDP[_cPending]);
        UDPDiscard();
        UDPClose(_rghUDP[_cPending]);
        ExchangeCacheBuffer(_rghUDP[_cPending], NULL, 0);
        _rghUDP[_cPending] = INVALID_UDP_SOCKET;
    }

    // no longer listening
    _fListening = false;
}
Example #8
0
/**
 * Must be called every couple of ms
 *
 */
void busTask(void) {
    BYTE c;
    BYTE bytesRead;
    BYTE busId;
    BYTE linkedMask;

    /////////////////////////////////////////////////
    //UDP 1
    
    //Get bus to link to UDP 1
    busId = appcfgGetc(BUSCFG_UDP1_LINK);

    #if defined(BRD_SBC65EC)    
    //Currently UDP 1 can only be linked to Serial 1, Serial 2 and I2C for SBC65EC
    if ((busId >= BUSID_SER1) && (busId <= BUSID_I2C1) && (udpBus1 != INVALID_UDP_SOCKET)) {
    #else
    //Currently UDP 1 can only be linked to Serial 1 and I2C for SBC68EC
    if ( ((busId == BUSID_SER1) || (busId == BUSID_I2C1)) && (udpBus1 != INVALID_UDP_SOCKET)) {
    #endif
    
        //Is there any data waiting for us on this UDP port?
        if (UDPIsGetReady(udpBus1)) {

            if (busIsEnabled(busId)) {

                //Read bytes
                while (UDPGet(&c)) {

                    //Wait until a byte is transmitted by the interrupt routine and buffer has place again.
                    while (busIsTxBufFull(busId)) {

                        busService(busId);
                        FAST_USER_PROCESS();
                    }
                    //Add byte to TX buffer, and update buffer pointers
                    busPutByteTxBuf(busId, c);
                }

                //Initiate transmitting if not already transmitting
                if (!busIsTxing(busId)) {

                    busService(busId);
                }
            }

            //Discard the socket buffer.
            UDPDiscard();
        }

        //Is there any data to send on UDP port
        if(busRxBufHasData(busId)) {

            if (UDPIsPutReady(udpBus1)) {

                while(busRxBufHasData(busId)) {
                
                    //Read and remove byte from buffer
                    c = busPeekByteRxBuf(busId);
                    busRemoveByteRxBuf(busId);
                    
                    UDPPut(c);
                }
            
                // Now transmit it.
                UDPFlush();
            }
        }
    }


    /////////////////////////////////////////////////
    //UDP 2
    
    //Get bus to link to UDP 2
    busId = appcfgGetc(BUSCFG_UDP2_LINK);

    #if defined(BRD_SBC65EC)    
    //Currently UDP 1 can only be linked to Serial 1, Serial 2 and I2C for SBC65EC
    if ((busId >= BUSID_SER1) && (busId <= BUSID_I2C1) && (udpBus1 != INVALID_UDP_SOCKET)) {
    #else
    //Currently UDP 1 can only be linked to Serial 1 and I2C for SBC68EC
    if ( ((busId == BUSID_SER1) || (busId == BUSID_I2C1)) && (udpBus1 != INVALID_UDP_SOCKET)) {
    #endif
        //Is there any data waiting for us on this UDP port?
        if (UDPIsGetReady(udpBus2)) {

            if (busIsEnabled(busId)) {
                //Read bytes
                while (UDPGet(&c)) {
                    //Wait until a byte is transmitted by the interrupt routine and buffer has place again.
                    while (busIsTxBufFull(busId)) {
                        busService(busId);
                        FAST_USER_PROCESS();
                    }
                    //Add byte to TX buffer, and update buffer pointers
                    busPutByteTxBuf(busId, c);
                }

                //Initiate transmitting if not already transmitting
                if (!busIsTxing(busId)) {
                    busService(busId);
                }
            }

            //Discard the socket buffer.
            UDPDiscard();
        }

        //Is there any data to send on UDP port
        if(busRxBufHasData(busId)) {
            if (UDPIsPutReady(udpBus2)) {

                while(busRxBufHasData(busId)) {
                    //Read and remove byte from buffer
                    c = busPeekByteRxBuf(busId);
                    busRemoveByteRxBuf(busId);
            
                    UDPPut(c);
                }
            
                // Now transmit it.
                UDPFlush();
            }
        }
    }


    /////////////////////////////////////////////////
    //Service all serial buses
    for (busId=0; busId<BUS_COUNT; busId++) {
        busService(busId);
    }
}


/**
 * Service the given bus. If our code has a section where it has to wait for the transmit
 * buffer of a bus to be empties, it should call this function while waiting.
 *
 * @param busId The bus ID of the requested bus. Is a BUSID_XXX variable
 *
 */
void busService(BYTE busId) {
    switch(busId) {
        case BUSID_SER1:
            serService();
        break;
        
        #if defined(BRD_SBC65EC)
        case BUSID_SER2:
            ser2Service();
        break;
        #endif
        
        case BUSID_I2C1:
            i2cBusService();
        break;
        
        case BUSID_SPI1:
            NOP();
        break;
    }
}


/**
 * Gets a byte at the given offset from the Transmit Buffer, without removing it.
 * The byte is NOT removed from the buffer, and the buffer pointers are NOT updated! 
 * The byte at the given offset it returned. The offset is how deep the byte is in
 * the buffer. For example, 0 will return first byte in buffer, 5 will return the 6th
 * byte in the buffer.
 *
 * @preCondition Ensure offset parameter is not larger than current number of bytes
 * contained in buffer. Call busGetTxBufCount() to get current number of bytes in buffer.
 *
 * @param busId The bus ID of the requested bus. Is a BUSID_XXX variable
 * @param offset Offset of byte to return. Is a value from 0-n, where n = (busGetTxBufCount() - 1)
 *
 * @return Returns the byte at the given offset in the given bus's Transmit buffer.
 */
BYTE busPeekByteTxBufAt(BYTE busId, BYTE offset) {
	BYTE ofst;

	ofst = busInfo.buf[busId].getTx + offset;

	//Check if offset wrap around
	if (ofst >= busInfo.buf[busId].txBufSize) {
		ofst = ofst - busInfo.buf[busId].txBufSize;
	}

	return *(busInfo.buf[busId].txBuf + ofst);

}


/**
 * Gets a byte at the given offset from the Receive Buffer, without removing it.
 * The byte is NOT removed from the buffer, and the buffer pointers are NOT updated! 
 * The byte at the given offset it returned. The offset is how deep the byte is in
 * the buffer. For example, 0 will return first byte in buffer, 5 will return the 6th
 * byte in the buffer.
 *
 * @preCondition Ensure offset parameter is not larger than current number of bytes
 * contained in buffer. Call busGetRxBufCount() to get current number of bytes in buffer.
 *
 * @param busId The bus ID of the requested bus. Is a BUSID_XXX variable
 * @param offset Offset of byte to return. Is a value from 0-n, where n = (busGetRxBufCount() - 1)
 *
 * @return Returns the byte at the given offset in the given bus's Receive buffer.
 */
BYTE busPeekByteRxBufAt(BYTE busId, BYTE offset) {
	BYTE ofst;

	ofst = busInfo.buf[busId].getRx + offset;

	//Check if offset wrap around
	if (ofst >= busInfo.buf[busId].rxBufSize) {
		ofst = ofst - busInfo.buf[busId].rxBufSize;
	}

	return *(busInfo.buf[busId].rxBuf + ofst);
}
Example #9
0
/**************************************************************************
  Function:
 	void SNMPSendTrap(void)
 
  Summary:	
  	 Prepare, validate remote node which will receive trap and send trap pdu.
 	 	  
  Description:		
     This function is used to send trap notification to previously 
     configured ip address if trap notification is enabled. There are
     different trap notification code. The current implementation
     sends trap for authentication failure (4).
  
  PreCondition:
 	 If application defined event occurs to send the trap.
 
  parameters:
     None.
 
  Returns:          
 	 None.
 
  Remarks:
     This is a callback function called by the application on certain 
     predefined events. This routine only implemented to send a 
     authentication failure Notification-type macro with PUSH_BUTTON
     oid stored in MPFS. If the ARP is no resolved i.e. if 
     SNMPIsNotifyReady() returns FALSE, this routine times 
     out in 5 seconds. This routine should be modified according to 
     event occured and should update corrsponding OID and notification
     type to the trap pdu.
 *************************************************************************/
void SNMPSendTrap(void)
{
	static BYTE timeLock=FALSE;
	static BYTE receiverIndex=0; ///is application specific
	IP_ADDR remHostIPAddress,* remHostIpAddrPtr;
	SNMP_VAL val;
	static DWORD TimerRead;

	static enum 
	{
		SM_PREPARE,
		SM_NOTIFY_WAIT 
	} smState = SM_PREPARE;



	if(trapInfo.table[receiverIndex].Flags.bEnabled)
	{
		remHostIPAddress.v[0] = trapInfo.table[receiverIndex].IPAddress.v[3];
		remHostIPAddress.v[1] = trapInfo.table[receiverIndex].IPAddress.v[2];
		remHostIPAddress.v[2] = trapInfo.table[receiverIndex].IPAddress.v[1];
		remHostIPAddress.v[3] = trapInfo.table[receiverIndex].IPAddress.v[0];
		remHostIpAddrPtr = &remHostIPAddress;
		if(timeLock==(BYTE)FALSE)
		{
			TimerRead=TickGet();
			timeLock=TRUE;
		}
	}	
	else
	{
		receiverIndex++;
		if((receiverIndex == (BYTE)TRAP_TABLE_SIZE))
		{
			receiverIndex=0;
			timeLock=FALSE;
			gSendTrapFlag=FALSE;	
			UDPDiscard();
		}
		return;
		
	}
		
	switch(smState)
	{
	
		case SM_PREPARE:

			SNMPNotifyPrepare(remHostIpAddrPtr,trapInfo.table[receiverIndex].community,
						trapInfo.table[receiverIndex].communityLen,
						MICROCHIP,			  // Agent ID Var
						gSpecificTrapNotification,					  // Notification code.
						SNMPGetTimeStamp());
			smState++;
			break;
			
		case SM_NOTIFY_WAIT:
			if(SNMPIsNotifyReady(remHostIpAddrPtr))
			{
				smState = SM_PREPARE;
		 		val.byte = 0;
				receiverIndex++;

				//application has to decide on which SNMP var OID to send. Ex. PUSH_BUTTON	
				SNMPNotify(gOIDCorrespondingSnmpMibID, val, 0);
            	smState = SM_PREPARE;
				UDPDiscard();
				break;
			}
	}	
		
	//Try for max 5 seconds to send TRAP, do not get block in while()
	if((TickGet()-TimerRead)>(5*TICK_SECOND)|| (receiverIndex == (BYTE)TRAP_TABLE_SIZE))
	{
		UDPDiscard();
		smState = SM_PREPARE;
		receiverIndex=0;
		timeLock=FALSE;
		gSendTrapFlag=FALSE;
		return;
	}

}
Example #10
0
/**************************************************************************
  Function:
 	void SNMPSendTrap(void)
 
  Summary:	
  	 Prepare, validate remote node which will receive trap and send trap pdu.
 	 	  
  Description:		
     This function is used to send trap notification to previously 
     configured ip address if trap notification is enabled. There are
     different trap notification code. The current implementation
     sends trap for authentication failure (4).
  
  PreCondition:
 	 If application defined event occurs to send the trap.
 
  parameters:
     None.
 
  Returns:          
 	 None.
 
  Remarks:
     This is a callback function called by the application on certain 
     predefined events. This routine only implemented to send a 
     authentication failure Notification-type macro with PUSH_BUTTON
     oid stored in MPFS. If the ARP is no resolved i.e. if 
     SNMPIsNotifyReady() returns false, this routine times 
     out in 5 seconds. This routine should be modified according to 
     event occured and should update corrsponding OID and notification
     type to the trap pdu.
 *************************************************************************/
void SNMPSendTrap(void)
{
	static uint8_t timeLock=false;
	static uint8_t receiverIndex=0; ///is application specific
	IP_ADDR remHostIPAddress,* remHostIpAddrPtr;
	SNMP_VAL val;
	static SYS_TICK TimerRead;
    
	static enum 
	{
		SM_PREPARE,
		SM_NOTIFY_WAIT 
	} smState = SM_PREPARE;

    gpSnmpIf = TCPIP_STACK_GetDefaultNet();

	if(trapInfo.table[receiverIndex].Flags.bEnabled)
	{
		remHostIPAddress.v[0] = trapInfo.table[receiverIndex].IPAddress.v[3];
		remHostIPAddress.v[1] = trapInfo.table[receiverIndex].IPAddress.v[2];
		remHostIPAddress.v[2] = trapInfo.table[receiverIndex].IPAddress.v[1];
		remHostIPAddress.v[3] = trapInfo.table[receiverIndex].IPAddress.v[0];
		remHostIpAddrPtr = &remHostIPAddress;
		if(timeLock==(uint8_t)false)
		{
			TimerRead=SYS_TICK_Get();
			timeLock=true;
		}
	}	
	else
	{
		receiverIndex++;
		if((receiverIndex == (uint8_t)TRAP_TABLE_SIZE))
		{
			receiverIndex=0;
			timeLock=false;
			gSendTrapFlag=false;	
			UDPDiscard(s, gpSnmpIf);
		}
		return;
		
	}
		
	switch(smState)
	{
	
		case SM_PREPARE:

			SNMPNotifyPrepare(remHostIpAddrPtr,trapInfo.table[receiverIndex].community,
						trapInfo.table[receiverIndex].communityLen,
						MICROCHIP,			  // Agent ID Var
						gSpecificTrapNotification,					  // Notification code.
						SNMPGetTimeStamp());
			smState++;
			break;
			
		case SM_NOTIFY_WAIT:
			if(SNMPIsNotifyReady(remHostIpAddrPtr))
			{
				smState = SM_PREPARE;
		 		val.byte = 0;
				receiverIndex++;

				//application has to decide on which SNMP var OID to send. Ex. PUSH_BUTTON	
				SNMPNotify(gOIDCorrespondingSnmpMibID, val, 0);
            	smState = SM_PREPARE;
				UDPDiscard(s, gpSnmpIf);
				break;
			}
	}	
		
	//Try for max 5 seconds to send TRAP, do not get block in while()
	if((SYS_TICK_Get()-TimerRead)>(5*SYS_TICK_TicksPerSecondGet())|| (receiverIndex == (uint8_t)TRAP_TABLE_SIZE))
	{
		UDPDiscard(s, gpSnmpIf);
		smState = SM_PREPARE;
		receiverIndex=0;
		timeLock=false;
		gSendTrapFlag=false;
		return;
	}

}
Example #11
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)
{
    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;
		}
	}
}
Example #12
0
/*********************************************************************
 * Function:        void NBNSTask(NET_CONFIG* pConfig)
 *
 * PreCondition:    None
 *
 * Input:           pConfig   - interface 
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Sends responses to NetBIOS name requests
 *
 * Note:            None
 ********************************************************************/
void NBNSTask(NET_CONFIG* pConfig)
{
	uint8_t 			i;
	TCPIP_UINT16_VAL    Type, Class;
	NBNS_HEADER			NBNSHeader;
	uint8_t				NameString[16];
    int                 netIx;
    UDP_SOCKET          s;
   
    netIx = _TCPIPStackNetIx(pConfig);
    s = MySocket[netIx];
    
	switch(smNBNS[netIx])
	{
		case NBNS_HOME:
			smNBNS[netIx]++;
			break;

		case NBNS_OPEN_SOCKET:
			MySocket[netIx] = UDPOpen(0,UDP_OPEN_SERVER,NBNS_PORT,NBNS_PORT);
			if(MySocket[netIx] == INVALID_UDP_SOCKET)
				break;

            UDPSocketSetNet(MySocket[netIx], pConfig);
			smNBNS[netIx]++;

		case NBNS_LISTEN:
			if(!UDPIsGetReady(s))
            {
				break;
            }


			// Respond only to name requests sent to us from nodes on the same subnet
			// This prevents us from sending out the wrong IP address information if 
			// we haven't gotten a DHCP lease yet.
        	if((remoteNode.IPAddr.Val & pConfig->MyMask.Val) != (pConfig->MyIPAddr.Val & pConfig->MyMask.Val))
			{
				UDPDiscard(s);
				break;
			}

			// Retrieve the NBNS header and de-big-endian it
			UDPGet(s, &NBNSHeader.TransactionID.v[1]);
			UDPGet(s, &NBNSHeader.TransactionID.v[0]);
			UDPGet(s, &NBNSHeader.Flags.v[1]);
			UDPGet(s, &NBNSHeader.Flags.v[0]);
			UDPGet(s, &NBNSHeader.Questions.v[1]);
			UDPGet(s, &NBNSHeader.Questions.v[0]);
			UDPGet(s, &NBNSHeader.Answers.v[1]);
			UDPGet(s, &NBNSHeader.Answers.v[0]);
			UDPGet(s, &NBNSHeader.AuthoritativeRecords.v[1]);
			UDPGet(s, &NBNSHeader.AuthoritativeRecords.v[0]);
			UDPGet(s, &NBNSHeader.AdditionalRecords.v[1]);
			UDPGet(s, &NBNSHeader.AdditionalRecords.v[0]);

			// Remove all questions
			while(NBNSHeader.Questions.Val--)
			{
				NBNSGetName(s, NameString);
				UDPGet(s, &i);				// <??> Trailing character on string
				UDPGet(s, &Type.v[1]);		// Question type
				UDPGet(s, &Type.v[0]);
				UDPGet(s, &Class.v[1]);	// Question class
				UDPGet(s, &Class.v[0]);
				
				if(Type.Val == 0x0020u && Class.Val == 0x0001u && memcmp((void*)NameString, (void*)pConfig->NetBIOSName, sizeof(pConfig->NetBIOSName)) == 0)
				{
					if(UDPIsTxPutReady(s, 64))
                    {   
                        NBNSHeader.Flags.Val = 0x8400;

                        UDPPut(s, NBNSHeader.TransactionID.v[1]);
                        UDPPut(s, NBNSHeader.TransactionID.v[0]);
                        UDPPut(s, NBNSHeader.Flags.v[1]);
                        UDPPut(s, NBNSHeader.Flags.v[0]);
                        UDPPut(s, 0x00);	// 0x0000 Questions
                        UDPPut(s, 0x00);
                        UDPPut(s, 0x00);	// 0x0001 Answers
                        UDPPut(s, 0x01);
                        UDPPut(s, 0x00);	// 0x0000 Athoritative records
                        UDPPut(s, 0x00);
                        UDPPut(s, 0x00);	// 0x0000 Additional records
                        UDPPut(s, 0x00);

                        NBNSPutName(s, pConfig->NetBIOSName);
                        UDPPut(s, 0x00);	// 0x0020 Type: NetBIOS
                        UDPPut(s, 0x20);
                        UDPPut(s, 0x00);	// 0x0001 Class: Internet
                        UDPPut(s, 0x01);
                        UDPPut(s, 0x00);	// 0x00000000 Time To Live
                        UDPPut(s, 0x00);
                        UDPPut(s, 0x00);
                        UDPPut(s, 0x00);

                        UDPPut(s, 0x00);	// 0x0006 Data length
                        UDPPut(s, 0x06);	
                        UDPPut(s, 0x60);	// 0x6000 Flags: H-node, Unique
                        UDPPut(s, 0x00);
                        UDPPut(s, pConfig->MyIPAddr.v[0]);	// Put out IP address
                        UDPPut(s, pConfig->MyIPAddr.v[1]);
                        UDPPut(s, pConfig->MyIPAddr.v[2]);
                        UDPPut(s, pConfig->MyIPAddr.v[3]);

                        // Change the destination address to the unicast address of the last received packet
                        TCPIP_IPV4_SetDestAddress(UDPSocketDcpt[s].pTxPkt,remoteNode.IPAddr.Val);
                        memcpy((void*)&UDPSocketDcpt[s].pTxPkt->remoteMACAddr, (const void*)&remoteNode.MACAddr, sizeof(remoteNode.MACAddr));
                        UDPFlush(s);				
                    }
				}
			}
			
			UDPDiscard(s);

			break;
	}
}
Example #13
0
File: DNS.c Project: CEIT-UQ/RGB
/*****************************************************************************
  Function:
	BOOL DNSIsResolved(IP_ADDR* HostIP)

  Summary:
	Determines if the DNS resolution is complete and provides the IP.
	
  Description:
	Call this function to determine if the DNS resolution of an address has
	been completed.  If so, the resolved address will be provided in HostIP.

  Precondition:
	DNSResolve or DNSResolveROM has been called.

  Parameters:
	HostIP - A pointer to an IP_ADDR structure in which to store the 
		resolved IP address once resolution is complete.

  Return Values:
  	TRUE - The DNS client has obtained an IP, or the DNS process
  		has encountered an error.  HostIP will be 0.0.0.0 on error.  Possible 
  		errors include server timeout (i.e. DNS server not available), hostname 
  		not in the DNS, or DNS server errors.
  	FALSE - The resolution process is still in progress.
  ***************************************************************************/
BOOL DNSIsResolved(IP_ADDR* HostIP)
{
	static DWORD		StartTime;
	static WORD_VAL		SentTransactionID __attribute__((persistent));
	static BYTE			vARPAttemptCount;
	static BYTE			vDNSAttemptCount;
	BYTE 				i;
	WORD_VAL			w;
	DNS_HEADER			DNSHeader;
	DNS_ANSWER_HEADER	DNSAnswerHeader;

	switch(smDNS)
	{
		case DNS_START:
			vARPAttemptCount = 0;
			vDNSAttemptCount = 0;
			// No break;

		case DNS_ARP_START_RESOLVE:
			ARPResolve(&AppConfig.PrimaryDNSServer);
			vARPAttemptCount++;
			StartTime = TickGet();
			smDNS = DNS_ARP_RESOLVE;
			break;

		case DNS_ARP_RESOLVE:
			if(!ARPIsResolved(&AppConfig.PrimaryDNSServer, &ResolvedInfo.MACAddr))
			{
				if(TickGet() - StartTime > DNS_TIMEOUT)
					smDNS = (vARPAttemptCount >= 3u) ? DNS_FAIL : DNS_ARP_START_RESOLVE;
				break;
			}
			ResolvedInfo.IPAddr.Val = AppConfig.PrimaryDNSServer.Val;
			smDNS = DNS_OPEN_SOCKET;
			// No break: DNS_OPEN_SOCKET is the correct next state
		
		case DNS_OPEN_SOCKET:
			MySocket = UDPOpen(0, &ResolvedInfo, DNS_PORT);
			if(MySocket == INVALID_UDP_SOCKET)
				break;

			smDNS = DNS_QUERY;
			// No need to break, we can immediately start resolution
			
		case DNS_QUERY:
			if(!UDPIsPutReady(MySocket))
				break;
			
			// Put DNS query here
			SentTransactionID.Val++;
			UDPPut(SentTransactionID.v[1]);// User chosen transaction ID
			UDPPut(SentTransactionID.v[0]);
			UDPPut(0x01);		// Standard query with recursion
			UDPPut(0x00);	
			UDPPut(0x00);		// 0x0001 questions
			UDPPut(0x01);
			UDPPut(0x00);		// 0x0000 answers
			UDPPut(0x00);
			UDPPut(0x00);		// 0x0000 name server resource records
			UDPPut(0x00);
			UDPPut(0x00);		// 0x0000 additional records
			UDPPut(0x00);

			// Put hostname string to resolve
			if(DNSHostName)
				DNSPutString(DNSHostName);
			else
				DNSPutROMString(DNSHostNameROM);

			UDPPut(0x00);		// Type: DNS_TYPE_A A (host address) or DNS_TYPE_MX for mail exchange
			UDPPut(RecordType);
			UDPPut(0x00);		// Class: IN (Internet)
			UDPPut(0x01);

			UDPFlush();
			StartTime = TickGet();
			smDNS = DNS_GET_RESULT;
			break;

		case DNS_GET_RESULT:
			if(!UDPIsGetReady(MySocket))
			{
				if(TickGet() - StartTime > DNS_TIMEOUT)
					smDNS = DNS_FAIL;
				break;
			}

			// Retrieve the DNS header and de-big-endian it
			UDPGet(&DNSHeader.TransactionID.v[1]);
			UDPGet(&DNSHeader.TransactionID.v[0]);

			// Throw this packet away if it isn't in response to our last query
			if(DNSHeader.TransactionID.Val != SentTransactionID.Val)
			{
				UDPDiscard();
				break;
			}

			UDPGet(&DNSHeader.Flags.v[1]);
			UDPGet(&DNSHeader.Flags.v[0]);
			UDPGet(&DNSHeader.Questions.v[1]);
			UDPGet(&DNSHeader.Questions.v[0]);
			UDPGet(&DNSHeader.Answers.v[1]);
			UDPGet(&DNSHeader.Answers.v[0]);
			UDPGet(&DNSHeader.AuthoritativeRecords.v[1]);
			UDPGet(&DNSHeader.AuthoritativeRecords.v[0]);
			UDPGet(&DNSHeader.AdditionalRecords.v[1]);
			UDPGet(&DNSHeader.AdditionalRecords.v[0]);

			// Remove all questions (queries)
			while(DNSHeader.Questions.Val--)
			{
				DNSDiscardName();
				UDPGet(&w.v[1]);		// Question type
				UDPGet(&w.v[0]);
				UDPGet(&w.v[1]);		// Question class
				UDPGet(&w.v[0]);
			}
			
			// Scan through answers
			while(DNSHeader.Answers.Val--)
			{				
				DNSDiscardName();					// Throw away response name
				UDPGet(&DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A or MX
				if( DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
					DNSAnswerHeader.ResponseClass.Val	== 0x0001u && // Internet class
					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
				{
					Flags.bits.AddressValid = TRUE;
					UDPGet(&ResolvedInfo.IPAddr.v[0]);
					UDPGet(&ResolvedInfo.IPAddr.v[1]);
					UDPGet(&ResolvedInfo.IPAddr.v[2]);
					UDPGet(&ResolvedInfo.IPAddr.v[3]);
					goto DoneSearchingRecords;
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(&i);
					}
				}
			}

			// Remove all Authoritative Records
			while(DNSHeader.AuthoritativeRecords.Val--)
			{
				DNSDiscardName();					// Throw away response name
				UDPGet(&DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A
				if( DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
					DNSAnswerHeader.ResponseClass.Val	== 0x0001u && // Internet class
					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
				{
					Flags.bits.AddressValid = TRUE;
					UDPGet(&ResolvedInfo.IPAddr.v[0]);
					UDPGet(&ResolvedInfo.IPAddr.v[1]);
					UDPGet(&ResolvedInfo.IPAddr.v[2]);
					UDPGet(&ResolvedInfo.IPAddr.v[3]);
					goto DoneSearchingRecords;
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(&i);
					}
				}
			}

			// Remove all Additional Records
			while(DNSHeader.AdditionalRecords.Val--)
			{
				DNSDiscardName();					// Throw away response name
				UDPGet(&DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(&DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A
				if( DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
					DNSAnswerHeader.ResponseClass.Val	== 0x0001u && // Internet class
					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
				{
					Flags.bits.AddressValid = TRUE;
					UDPGet(&ResolvedInfo.IPAddr.v[0]);
					UDPGet(&ResolvedInfo.IPAddr.v[1]);
					UDPGet(&ResolvedInfo.IPAddr.v[2]);
					UDPGet(&ResolvedInfo.IPAddr.v[3]);
					goto DoneSearchingRecords;
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(&i);
					}
				}
			}

DoneSearchingRecords:

			UDPDiscard();
			UDPClose(MySocket);
			MySocket = INVALID_UDP_SOCKET;
			smDNS = DNS_DONE;
			// No break, DNS_DONE is the correct step

		case DNS_DONE:
			// Return 0.0.0.0 if DNS resolution failed, otherwise return the 
			// resolved IP address
			if(!Flags.bits.AddressValid)
				ResolvedInfo.IPAddr.Val = 0;
			HostIP->Val = ResolvedInfo.IPAddr.Val;
			return TRUE;

		case DNS_FAIL:
			// If 3 attempts or more, quit
			if(vDNSAttemptCount >= 2u)
			{
				// Return an invalid IP address 0.0.0.0 if we can't finish ARP or DNS query step
				HostIP->Val = 0x00000000;
				return TRUE;
			}
			vDNSAttemptCount++;

			// Swap primary and secondary DNS servers if there is a secondary DNS server programmed
			if(AppConfig.SecondaryDNSServer.Val)
			{
				AppConfig.PrimaryDNSServer.Val ^= AppConfig.SecondaryDNSServer.Val;
				AppConfig.SecondaryDNSServer.Val ^= AppConfig.PrimaryDNSServer.Val;
				AppConfig.PrimaryDNSServer.Val ^= AppConfig.SecondaryDNSServer.Val;

				// Start another ARP resolution for the secondary server (now primary)
				vARPAttemptCount = 0;
				if(MySocket != INVALID_UDP_SOCKET)
				{
					UDPClose(MySocket);
					MySocket = INVALID_UDP_SOCKET;
				}
				smDNS = DNS_ARP_START_RESOLVE;
			}

			break;

	}
	
	return FALSE;
}
Example #14
0
void EthernetRun(void (*ProcessData)(BYTE *data, WORD dataLen))
{
    // Now that all items are initialized, begin the co-operative
    // multitasking loop.  This infinite loop will continuously 
    // execute all stack-related tasks, as well as your own
    // application's functions.  Custom functions should be added
    // at the end of this loop.
    // Note that this is a "co-operative mult-tasking" mechanism
    // where every task performs its tasks (whether all in one shot
    // or part of it) and returns so that other tasks can do their
    // job.
    // If a task needs very long time to do its job, it must be broken
    // down into smaller pieces so that other tasks can have CPU time.

	// First prepare all UDP stuff.
	UDPTask();

	WORD dataCount;
	IP_ADDR tempLocalIP;
	BYTE cFrameType;
	BYTE cIPFrameType;

	// And then process incoming data ending this loop once a valid packet is received.
	int cont = 1;
	while (cont) {
		// Before fetching new data, be sure all old UDP data is discarded.
		UDPDiscard();

		// Fetch a packet. We stop receiving data if no data is waiting.
		if (!MACGetHeader(&remoteNode.MACAddr, &cFrameType)) {
			break;
		}

		// And now process the packet.
		switch(cFrameType) {
			// Process any ARP packets. These are used for determining a MAC-to-IP mapping.
			case MAC_ARP:
				ARPProcess();
				break;

			// Process any IP packets (of which UDP is a type).
			case MAC_IP:
				// If the received packet is not a valid IP packet, ignore it.
				if (!IPGetHeader(&tempLocalIP, &remoteNode, &cIPFrameType, &dataCount)) {
					break;
				}

				// Now if we've found a valid UDP packet, quit processing data.
				if (cIPFrameType == IP_PROT_UDP) {
					// Stop processing data if we came upon a complete UDP packet.
					if (UDPProcess(&remoteNode, &tempLocalIP, dataCount)) {
						cont = 0;
					}
				}

				break;
		}
	}

	// Send new UDP data to processing function.
	if (ProcessData) {
		WORD dataLen = 0;
		if ((dataLen = UDPIsGetReady(localServerSocket))) {
			BYTE data[dataLen];
			if (UDPGetArray(data, dataLen) == dataLen) {
				ProcessData(data, dataLen);
			}
		}
	}

	// Now run the DHCP server task. This needs to be run continuously as there's no way to tell
	// if any clients are connected to perform the lease once post-init. The default lease time
	// is also super short, 60s, so the server needs to be able to process new DHCP stuff.
	DHCPServerTask();
}
Example #15
0
/*****************************************************************************
  Function:
	void DHCPServerTask(NET_CONFIG* pConfig)

  Summary:
	Performs periodic DHCP server tasks.

  Description:
	This function performs any periodic tasks requied by the DHCP server 
	module, such as processing DHCP requests and distributing IP addresses.

  Precondition:
	None

  Parameters:
	pConfig   - interface

  Returns:
  	None
  ***************************************************************************/
void DHCPServerTask(NET_CONFIG* pConfig)
{
	uint8_t 				i;
	uint8_t				Option, Len;
	BOOTP_HEADER		BOOTPHeader;
	uint32_t				dw;
	bool				bAccept;
    int                 netIx;
    UDP_SOCKET          s;
    

#if defined(TCPIP_STACK_USE_DHCP_CLIENT)
	// Make sure we don't clobber anyone else's DHCP server
	if(DHCPIsServerDetected(pConfig))
		return;
#endif

    netIx = _TCPIPStackNetIx(pConfig);
	if(!bDHCPServerEnabled[netIx])
		return;

    s = MySocket[netIx];

	switch(smDHCPServer[netIx])
	{
		case DHCP_OPEN_SOCKET:
			// Obtain a UDP socket to listen/transmit on
			MySocket[netIx] = UDPOpen(0,UDP_OPEN_SERVER,DHCP_SERVER_PORT, DHCP_CLIENT_PORT);
			if(MySocket[netIx] == INVALID_UDP_SOCKET)
				break;

            UDPSocketSetNet(MySocket[netIx], pConfig);
			// Decide which address to lease out
			// Note that this needs to be changed if we are to 
			// support more than one lease
			DHCPNextLease[netIx].Val = (pConfig->MyIPAddr.Val & pConfig->MyMask.Val) + 0x02000000;
			if(DHCPNextLease[netIx].v[3] == 255u)
				DHCPNextLease[netIx].v[3] += 0x03;
			if(DHCPNextLease[netIx].v[3] == 0u)
				DHCPNextLease[netIx].v[3] += 0x02;

			smDHCPServer[netIx]++;

		case DHCP_LISTEN:
			// Check to see if a valid DHCP packet has arrived
			if(UDPIsGetReady(s) < 241u)
				break;

			// Retrieve the BOOTP header
			UDPGetArray(s, (uint8_t*)&BOOTPHeader, sizeof(BOOTPHeader));

			bAccept = (BOOTPHeader.ClientIP.Val == DHCPNextLease[netIx].Val) || (BOOTPHeader.ClientIP.Val == 0x00000000u);

			// Validate first three fields
			if(BOOTPHeader.MessageType != 1u)
				break;
			if(BOOTPHeader.HardwareType != 1u)
				break;
			if(BOOTPHeader.HardwareLen != 6u)
				break;

			// Throw away 10 unused bytes of hardware address,
			// server host name, and boot file name -- unsupported/not needed.
			for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)
				UDPGet(s, &Option);

			// Obtain Magic Cookie and verify
			UDPGetArray(s, (uint8_t*)&dw, sizeof(uint32_t));
			if(dw != 0x63538263ul)
				break;

			// Obtain options
			while(1)
			{
				// Get option type
				if(!UDPGet(s, &Option))
					break;
				if(Option == DHCP_END_OPTION)
					break;

				// Get option length
				UDPGet(s, &Len);
	
				// Process option
				switch(Option)
				{
					case DHCP_MESSAGE_TYPE:
						UDPGet(s, &i);
						switch(i)
						{
							case DHCP_DISCOVER_MESSAGE:
								DHCPReplyToDiscovery(&BOOTPHeader, netIx);
								break;

							case DHCP_REQUEST_MESSAGE:
							// NOTE : This #if section was missing from 5.36
                                #if defined(TCPIP_STACK_USE_ZEROCONF_LINK_LOCAL)
								if ( (BOOTPHeader.ClientIP.Val == 0x00000000u) &&
									 (bLeaseAvailable[netIx] == false) )
								{
									// Lease available only to the current lease holder
									break;
								}
								#endif

								DHCPReplyToRequest(&BOOTPHeader, bAccept, netIx);

							// NOTE : This #if section was missing from 5.36
                                #if defined(TCPIP_STACK_USE_ZEROCONF_LINK_LOCAL)
								bLeaseAvailable[netIx] = false;
								#endif

								break;

							// Need to handle these if supporting more than one DHCP lease
							case DHCP_RELEASE_MESSAGE:
							case DHCP_DECLINE_MESSAGE:
								break;
						}
						break;

					case DHCP_PARAM_REQUEST_IP_ADDRESS:
						if(Len == 4u)
						{
							// Get the requested IP address and see if it is the one we have on offer.
							UDPGetArray(s, (uint8_t*)&dw, 4);
							Len -= 4;
							bAccept = (dw == DHCPNextLease[netIx].Val);
						}
						break;

					case DHCP_END_OPTION:
						UDPDiscard(s);
						return;
				}

				// Remove any unprocessed bytes that we don't care about
				while(Len--)
				{
					UDPGet(s, &i);
				}
			}			

			UDPDiscard(s);
			break;
	}
}
Example #16
0
/**
 * Call DNSIsResolved() until the host is resolved.
 * You cannot start two DNS resolution proceedures concurrently.
 * You must not modify *Hostname until DNSIsResolved() returns TRUE.
 *
 * @preCondition        DNSResolve() was called.
 *
 * @param HostIP        4 byte IP address
 */
BOOL DNSIsResolved(IP_ADDR *HostIP)
{
    static UDP_SOCKET   MySocket;
    static NODE_INFO    Remote;
    static TICK         StartTime;
    BYTE                i;
    WORD_VAL            w;
    DNS_HEADER          DNSHeader;
    DNS_ANSWER_HEADER   DNSAnswerHeader;
    IP_ADDR             tmpIpAddr;

    switch(smDNS)
    {
        case DNS_HOME:
            tmpIpAddr.v[0] = MY_DNS_BYTE1;
            tmpIpAddr.v[1] = MY_DNS_BYTE2;
            tmpIpAddr.v[2] = MY_DNS_BYTE3;
            tmpIpAddr.v[3] = MY_DNS_BYTE4;
            ARPResolve(&tmpIpAddr);
            StartTime = TickGet();
            smDNS++;
            break;
        case DNS_RESOLVE_ARP:
            if(!ARPIsResolved(&tmpIpAddr, &Remote.MACAddr))
            {
                if(TickGet() - StartTime > DNS_TIMEOUT)
                {
                    smDNS--;
                }
                break;
            }
            Remote.IPAddr.Val = tmpIpAddr.Val;
            smDNS++;
            // No need to break, we can immediately start resolution

        case DNS_OPEN_SOCKET:
            MySocket = UDPOpen(0, &Remote, DNS_PORT);
            if(MySocket == INVALID_UDP_SOCKET) {
                #if (DEBUG_DNS >= LOG_ERROR)
                debugPutMsg(1); //@mxd:1:Could not open UDP socket
                #endif

                break;
            }

            smDNS++;
            // No need to break, we can immediately start resolution
            
        case DNS_QUERY:
            if(!UDPIsPutReady(MySocket))
                break;
            
            // Put DNS query here
            UDPPut(0x12);        // User chosen ID
            UDPPut(0x34);
            UDPPut(0x01);        // Standard query with recursion
            UDPPut(0x00);    
            UDPPut(0x00);        // 0x0001 questions
            UDPPut(0x01);
            UDPPut(0x00);        // 0x0000 answers
            UDPPut(0x00);
            UDPPut(0x00);        // 0x0000 name server resource records
            UDPPut(0x00);
            UDPPut(0x00);        // 0x0000 additional records
            UDPPut(0x00);

            // Put hostname string to resolve
            DNSPutString(DNSHostName);

            UDPPut(0x00);        // Type: A (host address)
            UDPPut(0x01);
            UDPPut(0x00);        // Class: IN (Internet)
            UDPPut(0x01);

            UDPFlush();
            StartTime = TickGet();
            smDNS++;
            break;

        case DNS_GET_RESULT:
            if(!UDPIsGetReady(MySocket))
            {
                if(TickGet() - StartTime > DNS_TIMEOUT)
                {
                    smDNS--;
                }
                break;
            }

            // Retrieve the DNS header and de-big-endian it
            UDPGet(&DNSHeader.TransactionID.v[1]);
            UDPGet(&DNSHeader.TransactionID.v[0]);
            UDPGet(&DNSHeader.Flags.v[1]);
            UDPGet(&DNSHeader.Flags.v[0]);
            UDPGet(&DNSHeader.Questions.v[1]);
            UDPGet(&DNSHeader.Questions.v[0]);
            UDPGet(&DNSHeader.Answers.v[1]);
            UDPGet(&DNSHeader.Answers.v[0]);
            UDPGet(&DNSHeader.AuthoritativeRecords.v[1]);
            UDPGet(&DNSHeader.AuthoritativeRecords.v[0]);
            UDPGet(&DNSHeader.AdditionalRecords.v[1]);
            UDPGet(&DNSHeader.AdditionalRecords.v[0]);

            // Remove all questions
            while(DNSHeader.Questions.Val--)
            {
                DNSGetString(NULL);
                UDPGet(&w.v[1]);        // Question type
                UDPGet(&w.v[0]);
                UDPGet(&w.v[1]);        // Question class
                UDPGet(&w.v[0]);
            }
            
            // Scan through answers
            while(DNSHeader.Answers.Val--)
            {
                UDPGet(&DNSAnswerHeader.ResponseName.v[1]);        // Response name
                UDPGet(&DNSAnswerHeader.ResponseName.v[0]);
                UDPGet(&DNSAnswerHeader.ResponseType.v[1]);        // Response type
                UDPGet(&DNSAnswerHeader.ResponseType.v[0]);
                UDPGet(&DNSAnswerHeader.ResponseClass.v[1]);    // Response class
                UDPGet(&DNSAnswerHeader.ResponseClass.v[0]);
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[3]);        // Time to live
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[2]);
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[1]);
                UDPGet(&DNSAnswerHeader.ResponseTTL.v[0]);
                UDPGet(&DNSAnswerHeader.ResponseLen.v[1]);        // Response length
                UDPGet(&DNSAnswerHeader.ResponseLen.v[0]);

                // Make sure that this is a 4 byte IP address, response type A, class 1
                // Check if this is Type A
                if(    DNSAnswerHeader.ResponseType.Val    == 0x0001u && 
                    DNSAnswerHeader.ResponseClass.Val    == 0x0001u && // Internet class
                    DNSAnswerHeader.ResponseLen.Val        == 0x0004u)
                {
                    UDPGet(&HostIP->v[0]);
                    UDPGet(&HostIP->v[1]);
                    UDPGet(&HostIP->v[2]);
                    UDPGet(&HostIP->v[3]);
                    break;
                }
                else
                {
                    while(DNSAnswerHeader.ResponseLen.Val--)
                    {
                        UDPGet(&i);
                    }
                }
            }

            UDPDiscard();
            UDPClose(MySocket);
            MySocket = INVALID_UDP_SOCKET;
            smDNS++;
            // No need to break, we are done and need to return TRUE

        case DNS_DONE:
            return TRUE;
    }
    
    return FALSE;
}
Example #17
0
int8_t vscp_getUDPEvent( PVSCPMSG pmsg )
{
    int i;
    BYTE b1, b2;
    crc  remainder = INITIAL_REMAINDER;


    // Must be something to receive
    if ( !UDPIsGetReady( vscp_udp_receivesocket ) ) return FALSE;

    // head
    if ( !UDPGet( &b1 ) ) return FALSE;
    crcSlow_bithandler( b1, &remainder );	// CRC calculation
    pmsg->head = b1;

    // class
    if ( !UDPGet( &b1 ) ) return FALSE;
    crcSlow_bithandler( b1, &remainder );	// CRC calculation
    if ( !UDPGet( &b2 ) ) return FALSE;
    crcSlow_bithandler( b2, &remainder );	// CRC calculation
    pmsg->vscp_class = ( b1 << 8 ) + b2;

    // type
    if ( !UDPGet( &b1 ) ) return FALSE;
    crcSlow_bithandler( b1, &remainder );	// CRC calculation
    if ( !UDPGet( &b2 ) ) return FALSE;
    crcSlow_bithandler( b2, &remainder );	// CRC calculation
    pmsg->vscp_type = ( b1 << 8 ) + b2;

    // GUID
    for ( i=0; i<16; i++ ) {
        if ( !UDPGet( &b1 ) ) return FALSE;
        crcSlow_bithandler( b1, &remainder );	// CRC calculation
        pmsg->GUID[ i ] = b1;
    }

    // Size
    if ( !UDPGet( &b1 ) ) return FALSE;
    crcSlow_bithandler( b1, &remainder );	// CRC calculation
    if ( !UDPGet( &b2 ) ) return FALSE;
    crcSlow_bithandler( b2, &remainder );	// CRC calculation
    pmsg->sizeData = ( b1 << 8 ) + b2;

#ifdef VSCP_LEVEL2_LIMITED_DEVICE
    if ( pmsg->sizeData > LIMITED_DEVICE_DATASIZE ) return FALSE;
#else
    if ( pmsg->sizeData > (512-25) ) return FALSE;
#endif

    // Data
    for ( i=0; i<pmsg->sizeData; i++ ) {
        if ( !UDPGet( &b1 ) ) return FALSE;
        crcSlow_bithandler( b1, &remainder );	// CRC calculation
        pmsg->data[ i ] = b1;
    }

    // crc
    if ( !UDPGet( &b1 ) ) return FALSE;
    crcSlow_bithandler( b1, &remainder );	// CRC calculation
    if ( !UDPGet( &b2 ) ) return FALSE;
    crcSlow_bithandler( b2, &remainder );	// CRC calculation
    pmsg->crc = ( b1 << 8 ) + b2;

    if ( ( remainder ^ FINAL_XOR_VALUE ) ) return FALSE;

    // we have the information we need
    UDPDiscard();

    return TRUE;
}
Example #18
0
/*********************************************************************
 * Function:        void ANNOUNCE_Task(void)
 *
 * Summary:         Announce callback task.
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Recurring task used to listen for Discovery
 *                  messages on the specified ANNOUNCE_PORT.  These
 *                  messages can be sent using the TCP/IP
 *                  Discoverer tool. If one is received, this
 *                  function will transmit a reply.
 *
 * Note:            A UDP socket must be available before this 
 *					function is called.  It is freed at the end of 
 *					the function.  UDP_MAX_SOCKETS may need to be 
 *					increased if other modules use UDP sockets.
 ********************************************************************/
void ANNOUNCE_Task(NET_CONFIG * pNetIf)
{
	static enum {
		DISCOVERY_HOME = 0,
		DISCOVERY_LISTEN,
		DISCOVERY_REQUEST_RECEIVED,
		DISCOVERY_DISABLED
	} DiscoverySM[TCPIP_NETWORK_INTERFACES] = {DISCOVERY_HOME};

	static UDP_SOCKET	MySocket[TCPIP_NETWORK_INTERFACES];
	uint8_t 				i;
    int                 netIx;
    UDP_SOCKET          s;

    if(!pNetIf)
    {
        return;
    }
    else
    {
        netIx = _TCPIPStackNetIx(pNetIf);
    }
    
    s = MySocket[netIx];

	switch(DiscoverySM[netIx])
	{
		case DISCOVERY_HOME:
			// Open a UDP socket for inbound and outbound transmission
			// Since we expect to only receive broadcast packets and 
			// only send unicast packets directly to the node we last 
			// received from, the remote NodeInfo parameter can be anything
			MySocket[netIx] = UDPOpen(0,UDP_OPEN_SERVER,ANNOUNCE_PORT, ANNOUNCE_PORT);

			if(MySocket[netIx] == INVALID_UDP_SOCKET)
            {
				return;
            }
			else
            {
                DiscoverySM[netIx]++;
                UDPSocketSetNet(MySocket[netIx], pNetIf);
            }
			break;

		case DISCOVERY_LISTEN:
			// Do nothing if no data is waiting
			if(!UDPIsGetReady(s))
				return;
			
			// See if this is a discovery query or reply
			UDPGet(s, &i);
			UDPDiscard(s);
			if(i != 'D')
				return;

			// We received a discovery request, reply when we can
			DiscoverySM[netIx]++;

			// Change the destination to the unicast address of the last received packet
            TCPIP_IPV4_SetDestAddress(UDPSocketDcpt[s].pTxPkt,remoteNode.IPAddr.Val);
        	memcpy((void*)&UDPSocketDcpt[s].pTxPkt->remoteMACAddr, (const void*)&remoteNode.MACAddr, sizeof(MAC_ADDR));
			
			// No break needed.  If we get down here, we are now ready for the DISCOVERY_REQUEST_RECEIVED state

		case DISCOVERY_REQUEST_RECEIVED:
            ANNOUNCE_Notify (pNetIf, 0, NULL);		
			// Listen for other discovery requests
			DiscoverySM[netIx] = DISCOVERY_LISTEN;
			break;

		case DISCOVERY_DISABLED:
			break;
	}	

}
Example #19
0
/*********************************************************************
 * Function:        void NBNSTask(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          Sends responses to NetBIOS name requests
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
void NBNSTask(void)
{
	static UDP_SOCKET	MySocket;
	BYTE 				i;
	WORD_VAL			Type, Class;
	NBNS_HEADER			NBNSHeader;
	BYTE				NameString[16];
	static enum
	{
		NBNS_HOME = 0,
		NBNS_OPEN_SOCKET,
		NBNS_LISTEN
	} smNBNS = NBNS_HOME;

	switch(smNBNS)
	{
		case NBNS_HOME:
			smNBNS++;
			break;

		case NBNS_OPEN_SOCKET:
			MySocket = UDPOpen(NBNS_PORT, NULL, NBNS_PORT);
			if(MySocket == INVALID_UDP_SOCKET)
				break;

			smNBNS++;

		case NBNS_LISTEN:
			if(!UDPIsGetReady(MySocket))
				break;

			// Respond only to name requests sent to us from nodes on the same subnet
			// This prevents us from sending out the wrong IP address information if 
			// we haven't gotten a DHCP lease yet.
        	if((remoteNode.IPAddr.Val & AppConfig.MyMask.Val) != (AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val))
			{
				UDPDiscard();
				break;
			}

			// Retrieve the NBNS header and de-big-endian it
			UDPGet(&NBNSHeader.TransactionID.v[1]);
			UDPGet(&NBNSHeader.TransactionID.v[0]);
			UDPGet(&NBNSHeader.Flags.v[1]);
			UDPGet(&NBNSHeader.Flags.v[0]);
			UDPGet(&NBNSHeader.Questions.v[1]);
			UDPGet(&NBNSHeader.Questions.v[0]);
			UDPGet(&NBNSHeader.Answers.v[1]);
			UDPGet(&NBNSHeader.Answers.v[0]);
			UDPGet(&NBNSHeader.AuthoritativeRecords.v[1]);
			UDPGet(&NBNSHeader.AuthoritativeRecords.v[0]);
			UDPGet(&NBNSHeader.AdditionalRecords.v[1]);
			UDPGet(&NBNSHeader.AdditionalRecords.v[0]);

			// Remove all questions
			while(NBNSHeader.Questions.Val--)
			{
				NBNSGetName(NameString);
				UDPGet(&i);				// <??> Trailing character on string
				UDPGet(&Type.v[1]);		// Question type
				UDPGet(&Type.v[0]);
				UDPGet(&Class.v[1]);	// Question class
				UDPGet(&Class.v[0]);
				
				if(Type.Val == 0x0020u && Class.Val == 0x0001u && strcmp((char*)NameString, (char*)AppConfig.NetBIOSName) == 0)
				{
					while(!UDPIsPutReady(MySocket));

					NBNSHeader.Flags.Val = 0x8400;

					UDPPut(NBNSHeader.TransactionID.v[1]);
					UDPPut(NBNSHeader.TransactionID.v[0]);
					UDPPut(NBNSHeader.Flags.v[1]);
					UDPPut(NBNSHeader.Flags.v[0]);
					UDPPut(0x00);	// 0x0000 Questions
					UDPPut(0x00);
					UDPPut(0x00);	// 0x0001 Answers
					UDPPut(0x01);
					UDPPut(0x00);	// 0x0000 Athoritative records
					UDPPut(0x00);
					UDPPut(0x00);	// 0x0000 Additional records
					UDPPut(0x00);

					NBNSPutName(AppConfig.NetBIOSName);
					UDPPut(0x00);	// 0x0020 Type: NetBIOS
					UDPPut(0x20);
					UDPPut(0x00);	// 0x0001 Class: Internet
					UDPPut(0x01);
					UDPPut(0x00);	// 0x00000000 Time To Live
					UDPPut(0x00);
					UDPPut(0x00);
					UDPPut(0x00);

					UDPPut(0x00);	// 0x0006 Data length
					UDPPut(0x06);	
					UDPPut(0x60);	// 0x6000 Flags: H-node, Unique
					UDPPut(0x00);
					UDPPut(AppConfig.MyIPAddr.v[0]);	// Put out IP address
					UDPPut(AppConfig.MyIPAddr.v[1]);
					UDPPut(AppConfig.MyIPAddr.v[2]);
					UDPPut(AppConfig.MyIPAddr.v[3]);

					// Change the destination address to the unicast address of the last received packet
		        	memcpy((void*)&UDPSocketInfo[MySocket].remoteNode, (const void*)&remoteNode, sizeof(remoteNode));
					UDPFlush();				
				}

			}
			
			UDPDiscard();

			break;
	}
}
Example #20
0
/*********************************************************************
        DHCP PACKET FORMAT AS PER RFC 1541

   0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
   +---------------+---------------+---------------+---------------+
   |                            xid (4)                            |
   +-------------------------------+-------------------------------+
   |           secs (2)            |           flags (2)           |
   +-------------------------------+-------------------------------+
   |                          ciaddr  (4)                          |
   +---------------------------------------------------------------+
   |                          yiaddr  (4)                          |
   +---------------------------------------------------------------+
   |                          siaddr  (4)                          |
   +---------------------------------------------------------------+
   |                          giaddr  (4)                          |
   +---------------------------------------------------------------+
   |                                                               |
   |                          chaddr  (16)                         |
   |                                                               |
   |                                                               |
   +---------------------------------------------------------------+
   |                                                               |
   |                          sname   (64)                         |
   +---------------------------------------------------------------+
   |                                                               |
   |                          file    (128)                        |
   +---------------------------------------------------------------+
   |                                                               |
   |                          options (312)                        |
   +---------------------------------------------------------------+

 ********************************************************************/
static BYTE _DHCPReceive(void)
{
    BYTE v;
    BYTE i, j;
    BYTE type;
    BOOL lbDone;
    DWORD_VAL tempServerID;


    // Assume unknown message until proven otherwise.
    type = DHCP_UNKNOWN_MESSAGE;

    UDPGet(&v);                             // op

    //Make sure this is BOOT_REPLY.
    if ( v == BOOT_REPLY )
    {
        //Discard htype, hlen, hops, xid, secs, flags, ciaddr.
        for ( i = 0; i < 15u; i++ )
            UDPGet(&v);

      // Check to see if this is the first offer
      if(DHCPState.bits.bOfferReceived)
      {
           // Discard offered IP address, we already have an offer
           for ( i = 0; i < 4u; i++ )
               UDPGet(&v);
      }
      else
      {
           // Save offered IP address until we know for sure that we have it.
           UDPGet(&tempIPAddress.v[0]);
           UDPGet(&tempIPAddress.v[1]);
           UDPGet(&tempIPAddress.v[2]);
           UDPGet(&tempIPAddress.v[3]);
         ValidValues.bits.IPAddress = 1;
      }

        //Ignore siaddr, giaddr
        for ( i = 0; i < 8u; i++ )
            UDPGet(&v);

        //Check to see if chaddr (Client Hardware Address) belongs to us.
        for ( i = 0; i < 6u; i++ )
        {
            UDPGet(&v);
            if ( v != AppConfig.MyMACAddr.v[i])
                goto UDPInvalid;
        }

        //Ignore part of chaddr, sname, file, magic cookie.
        for ( i = 0; i < 206u; i++ )
            UDPGet(&v);

        lbDone = FALSE;
        do
        {
         // Get the Option number
         // Break out eventually in case if this is a malformed
         // DHCP message, ie: missing DHCP_END_OPTION marker
         if(!UDPGet(&v))
         {
            lbDone = TRUE;
            break;
         }

            switch(v)
            {
            case DHCP_MESSAGE_TYPE:
                UDPGet(&v);                         // Skip len
                // Len must be 1.
                if ( v == 1u )
                {
                    UDPGet(&type);                  // Get type

               // Throw away the packet if we know we don't need it (ie: another offer when we already have one)
               if(DHCPState.bits.bOfferReceived && (type == DHCP_OFFER_MESSAGE))
               {
                  goto UDPInvalid;
               }
            }
                else
                    goto UDPInvalid;
                break;

            case DHCP_SUBNET_MASK:
                UDPGet(&v);                     // Skip len
                // Len must be 4.
                if ( v == 4u )
                {
               // Check to see if this is the first offer
               if(DHCPState.bits.bOfferReceived)
               {
                    // Discard offered IP mask, we already have an offer
                    for ( i = 0; i < 4u; i++ )
                        UDPGet(&v);
               }
               else
               {
                       UDPGet(&tempMask.v[0]);
                       UDPGet(&tempMask.v[1]);
                       UDPGet(&tempMask.v[2]);
                       UDPGet(&tempMask.v[3]);
                  ValidValues.bits.Mask = 1;
               }
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_ROUTER:
                UDPGet(&j);
                // Len must be >= 4.
                if ( j >= 4u )
                {
               // Check to see if this is the first offer
               if(DHCPState.bits.bOfferReceived)
               {
                    // Discard offered Gateway address, we already have an offer
                    for ( i = 0; i < 4u; i++ )
                        UDPGet(&v);
               }
               else
               {
                       UDPGet(&tempGateway.v[0]);
                       UDPGet(&tempGateway.v[1]);
                       UDPGet(&tempGateway.v[2]);
                       UDPGet(&tempGateway.v[3]);
                  ValidValues.bits.Gateway = 1;
               }
                }
                else
                    goto UDPInvalid;

                // Discard any other router addresses.
                j -= 4;
                while(j--)
                    UDPGet(&v);
                break;

#if STACK_USE_DNS
            case DHCP_DNS:
                UDPGet(&j);
                // Len must be >= 4.
                if ( j >= 4u )
                {
               // Check to see if this is the first offer
               if(DHCPState.bits.bOfferReceived)
               {
                    // Discard offered DNS server address, we already have an offer
                    for ( i = 0; i < 4u; i++ )
                        UDPGet(&v);
               }
               else
               {
                       UDPGet(&tempDNS.v[0]);
                       UDPGet(&tempDNS.v[1]);
                       UDPGet(&tempDNS.v[2]);
                       UDPGet(&tempDNS.v[3]);
                  ValidValues.bits.DNS = 1;
               }
                }
                else
                    goto UDPInvalid;

                // Discard any other DNS server addresses
                j -= 4;
                while(j--)
                    UDPGet(&v);
                break;
#endif

//            case DHCP_HOST_NAME:
//                UDPGet(&j);
//                // Len must be >= 4.
//                if(j < 1u)
//               goto UDPInvalid;
//
//            // Check to see if this is the first offer
//            if(DHCPState.bits.bOfferReceived)
//            {
//                 // Discard offered host name, we already have an offer
//                   while(j--)
//                       UDPGet(&v);
//            }
//            else
//            {
//               for(i = 0; j, i < sizeof(tempHostName); i++, j--)
//               {
//                  UDPGet(&tempHostName[i]);
//               }
//               while(j--)
//               {
//                  UDPGet(&v);
//               }
//               ValidValues.bits.HostName = 1;
//            }
//
//                break;

            case DHCP_SERVER_IDENTIFIER:
                UDPGet(&v);                         // Get len
                // Len must be 4.
                if ( v == 4u )
                {
                    UDPGet(&tempServerID.v[3]);   // Get the id
                    UDPGet(&tempServerID.v[2]);
                    UDPGet(&tempServerID.v[1]);
                    UDPGet(&tempServerID.v[0]);
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_END_OPTION:
                lbDone = TRUE;
                break;

            case DHCP_IP_LEASE_TIME:
                UDPGet(&v);                         // Get len
                // Len must be 4.
                if ( v == 4u )
                {
               // Check to see if this is the first offer
               if(DHCPState.bits.bOfferReceived)
               {
                    // Discard offered lease time, we already have an offer
                    for ( i = 0; i < 4u; i++ )
                        UDPGet(&v);
               }
               else
               {
                       UDPGet(&DHCPLeaseTime.v[3]);
                       UDPGet(&DHCPLeaseTime.v[2]);
                       UDPGet(&DHCPLeaseTime.v[1]);
                       UDPGet(&DHCPLeaseTime.v[0]);

                       // Due to possible timing delays, consider actual lease
                       // time less by half hour.
                       if ( DHCPLeaseTime.Val > HALF_HOUR )
                           DHCPLeaseTime.Val = DHCPLeaseTime.Val - HALF_HOUR;
               }
                }
                else
                    goto UDPInvalid;
                break;

            default:
                // Ignore all unsupport tags.
                UDPGet(&j);                     // Get option len
                while( j-- )                    // Ignore option values
                    UDPGet(&v);
            }
        } while( !lbDone );
    }

    // If this is an OFFER message, remember current server id.
    if ( type == DHCP_OFFER_MESSAGE )
    {
        DHCPServerID.Val = tempServerID.Val;
      DHCPState.bits.bOfferReceived = TRUE;
    }
    else
    {
        // For other types of messages, make sure that received
        // server id matches with our previous one.
        if ( DHCPServerID.Val != tempServerID.Val )
            type = DHCP_UNKNOWN_MESSAGE;
    }

    UDPDiscard();                             // We are done with this packet
    return type;

UDPInvalid:
    UDPDiscard();
    return DHCP_UNKNOWN_MESSAGE;

}
Example #21
0
/*********************************************************************
 * Function:        TFTP_RESULT TFTPIsGetReady(void)
 *
 * PreCondition:    TFTPOpenFile() is called with TFTP_FILE_MODE_READ
 *                  and TFTPIsFileOpened() returned with TRUE.
 *
 * Input:           None
 *
 * Output:          TFTP_OK if it there is more data byte available
 *                  to read
 *
 *                  TFTP_TIMEOUT if timeout occurred waiting for
 *                  new data.
 *
 *                  TFTP_END_OF_FILE if end of file has reached.
 *
 *                  TFTP_ERROR if remote server returned ERROR.
 *                      Actual error code may be read by calling
 *                      TFTPGetError()
 *
 *                  TFTP_NOT_READY if still waiting for new data.
 *
 * Side Effects:    None
 *
 * Overview:        Waits for data block.  If data block does not
 *                  arrive within specified timeout, it automatically
 *                  sends out ack for previous block to remind
 *                  server to send next data block.
 *                  If all attempts are exhausted, it returns with
 *                  TFTP_TIMEOUT.
 *
 * Note:            By default, this funciton uses "octet" or binary
 *                  mode of file transfer.
 ********************************************************************/
TFTP_RESULT TFTPIsGetReady(void)
{
    WORD_VAL opCode;
    WORD_VAL blockNumber;
    BOOL bTimeOut;


    // Check to see if timeout has occurred.
    bTimeOut = FALSE;
    if ( TickGetDiff(TickGet(), _tftpStartTick) >= TFTP_GET_TIMEOUT_VAL )
    {
        bTimeOut = TRUE;
        _tftpStartTick = TickGet();
    }


    switch(_tftpState)
    {
    case SM_TFTP_WAIT_FOR_DATA:
        // If timeout occurs in this state, it may be because, we have not
        // even received very first data block or some in between block.
        if ( bTimeOut == TRUE )
        {
            bTimeOut = FALSE;

            if ( _tftpRetries++ > (TFTP_MAX_RETRIES-1) )
            {
                DEBUG(printf("TFTPIsGetReady(): Timeout.\n"));

                // Forget about all previous attempts.
                _tftpRetries = 1;

                return TFTP_TIMEOUT;
            }

            // If we have not even received first block, ask application
            // retry.
            if ( MutExVar.group2._tftpBlockNumber.Val == 1 )
            {
                DEBUG(printf("TFTPIsGetReady(): TFTPOpen Retry.\n"));
                return TFTP_RETRY;
            }
            else
            {
                DEBUG(printf("TFTPIsGetReady(): ACK Retry #%d...,\n", _tftpRetries));

                // Block number was already incremented in last ACK attempt,
                // so decrement it.
                MutExVar.group2._tftpBlockNumber.Val--;

                // Do it.
                _tftpState = SM_TFTP_SEND_ACK;
                break;
            }
        }

        // For Read operation, server will respond with data block.
        if ( !UDPIsGetReady(_tftpSocket) )
            break;

        // Get opCode
        UDPGet(&opCode.byte.MSB);
        UDPGet(&opCode.byte.LSB);

        // Get block number.
        UDPGet(&blockNumber.byte.MSB);
        UDPGet(&blockNumber.byte.LSB);

        // In order to read file, this must be data with block number of 0.
        if ( opCode.Val == TFTP_OPCODE_DATA )
        {
            // Make sure that this is not a duplicate block.
            if ( MutExVar.group2._tftpBlockNumber.Val == blockNumber.Val )
            {
                // Mark that we have not acked this block.
                _tftpFlags.bits.bIsAcked = FALSE;

                // Since we have a packet, forget about previous retry count.
                _tftpRetries = 1;

                _tftpState = SM_TFTP_READY;
                return TFTP_OK;
            }

            // If received block has already been received, simply ack it
            // so that Server can "get over" it and send next block.
            else if ( MutExVar.group2._tftpBlockNumber.Val > blockNumber.Val )
            {
                DEBUG(printf("TFTPIsGetReady(): "\
                            "Duplicate block %d received - droping it...\n", \
                            blockNumber.Val));
                MutExVar.group2._tftpDuplicateBlock.Val = blockNumber.Val;
                _tftpState = SM_TFTP_DUPLICATE_ACK;
            }
#if defined(TFTP_DEBUG)
            else
            {
                DEBUG(printf("TFTPIsGetReady(): "\
                             "Unexpected block %d received - droping it...\n", \
                             blockNumber.Val));
            }
#endif
        }
        // Discard all unexpected and error blocks.
        UDPDiscard();

        // If this was an error, remember error code for later delivery.
        if ( opCode.Val == TFTP_OPCODE_ERROR )
        {
            _tftpError = blockNumber.Val;
            return TFTP_ERROR;
        }

        break;

    case SM_TFTP_DUPLICATE_ACK:
        if ( UDPIsPutReady(_tftpSocket) )
        {
            _TFTPSendAck(MutExVar.group2._tftpDuplicateBlock);
            _tftpState = SM_TFTP_WAIT_FOR_DATA;
        }
        break;

    case SM_TFTP_READY:
        if ( UDPIsGetReady(_tftpSocket) )
        {
            _tftpStartTick = TickGet();
            return TFTP_OK;
        }

        // End of file is reached when data block is less than 512 bytes long.
        // To reduce code, only MSB compared against 0x02 (of 0x200 = 512) to
        // determine if block is less than 512 bytes long or not.
        else if ( MutExVar.group2._tftpBlockLength.Val == 0 ||
                  MutExVar.group2._tftpBlockLength.byte.MSB < TFTP_BLOCK_SIZE_MSB )
            _tftpState = SM_TFTP_SEND_LAST_ACK;
        else
            break;


    case SM_TFTP_SEND_LAST_ACK:
    case SM_TFTP_SEND_ACK:
        if ( UDPIsPutReady(_tftpSocket) )
        {
            _TFTPSendAck(MutExVar.group2._tftpBlockNumber);

            // This is the next block we are expecting.
            MutExVar.group2._tftpBlockNumber.Val++;

            // Remember that we have already acked current block.
            _tftpFlags.bits.bIsAcked = TRUE;

            if ( _tftpState == SM_TFTP_SEND_LAST_ACK )
                return TFTP_END_OF_FILE;

            _tftpState = SM_TFTP_WAIT_FOR_DATA;
        }
        break;
    }



    return TFTP_NOT_READY;
}
Example #22
0
/*****************************************************************************
  Function:
	void DHCPServerTask(void)

  Summary:
	Performs periodic DHCP server tasks.

  Description:
	This function performs any periodic tasks requied by the DHCP server 
	module, such as processing DHCP requests and distributing IP addresses.

  Precondition:
	None

  Parameters:
	None

  Returns:
  	None
  ***************************************************************************/
void DHCPServerTask(void)
{
	BYTE 				i;
	BYTE				Option, Len;
	BOOTP_HEADER		BOOTPHeader;
	DWORD				dw;
	BOOL				bAccept;
	static enum
	{
		DHCP_OPEN_SOCKET,
		DHCP_LISTEN
	} smDHCPServer = DHCP_OPEN_SOCKET;

#if defined(STACK_USE_DHCP_CLIENT)
	// Make sure we don't clobber anyone else's DHCP server
	if(DHCPIsServerDetected(0))
		return;
#endif

	if(!bDHCPServerEnabled)
		return;

	switch(smDHCPServer)
	{
		case DHCP_OPEN_SOCKET:
			// Obtain a UDP socket to listen/transmit on
			//MySocket = UDPOpen(DHCP_SERVER_PORT, NULL, DHCP_CLIENT_PORT);
			MySocket = UDPOpenEx(0,UDP_OPEN_SERVER,DHCP_SERVER_PORT, DHCP_CLIENT_PORT);
			if(MySocket == INVALID_UDP_SOCKET)
				break;


			// Decide which address to lease out
			// Note that this needs to be changed if we are to 
			// support more than one lease
			DHCPNextLease.Val = (AppConfig.MyIPAddr.Val & AppConfig.MyMask.Val) + 0x02000000;
			if(DHCPNextLease.v[3] == 255u)
				DHCPNextLease.v[3] += 0x03;
			if(DHCPNextLease.v[3] == 0u)
				DHCPNextLease.v[3] += 0x02;

			smDHCPServer++;

		case DHCP_LISTEN:
			// Check to see if a valid DHCP packet has arrived
			if(UDPIsGetReady(MySocket) < 241u)
				break;

			// Retrieve the BOOTP header
			UDPGetArray((BYTE*)&BOOTPHeader, sizeof(BOOTPHeader));

			bAccept = (BOOTPHeader.ClientIP.Val == DHCPNextLease.Val) || (BOOTPHeader.ClientIP.Val == 0x00000000u);

			// Validate first three fields
			if(BOOTPHeader.MessageType != 1u)
				break;
			if(BOOTPHeader.HardwareType != 1u)
				break;
			if(BOOTPHeader.HardwareLen != 6u)
				break;

			// Throw away 10 unused bytes of hardware address,
			// server host name, and boot file name -- unsupported/not needed.
			for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)
				UDPGet(&Option);

			// Obtain Magic Cookie and verify
			UDPGetArray((BYTE*)&dw, sizeof(DWORD));
			if(dw != 0x63538263ul)
				break;

			// Obtain options
			while(1)
			{
				// Get option type
				if(!UDPGet(&Option))
					break;
				if(Option == DHCP_END_OPTION)
					break;

				// Get option length
				UDPGet(&Len);
	
				// Process option
				switch(Option)
				{
					case DHCP_MESSAGE_TYPE:
						UDPGet(&i);
						switch(i)
						{
							case DHCP_DISCOVER_MESSAGE:
								DHCPReplyToDiscovery(&BOOTPHeader);
								break;

							case DHCP_REQUEST_MESSAGE:
								DHCPReplyToRequest(&BOOTPHeader, bAccept);
								break;

							// Need to handle these if supporting more than one DHCP lease
							case DHCP_RELEASE_MESSAGE:
							case DHCP_DECLINE_MESSAGE:
								break;
						}
						break;

					case DHCP_PARAM_REQUEST_IP_ADDRESS:
						if(Len == 4u)
						{
							// Get the requested IP address and see if it is the one we have on offer.
							UDPGetArray((BYTE*)&dw, 4);
							Len -= 4;
							bAccept = (dw == DHCPNextLease.Val);
						}
						break;

					case DHCP_END_OPTION:
						UDPDiscard();
						return;
				}

				// Remove any unprocessed bytes that we don't care about
				while(Len--)
				{
					UDPGet(&i);
				}
			}			

			UDPDiscard();
			break;
	}
}
Example #23
0
/*********************************************************************
 * Function:        TFTP_RESULT TFTPIsPutReady(void)
 *
 * PreCondition:    TFTPOpenFile() is called with TFTP_FILE_MODE_WRITE
 *                  and TFTPIsFileOpened() returned with TRUE.
 *
 * Input:           None
 *
 * Output:          TFTP_OK if it is okay to write more data byte.
 *
 *                  TFTP_TIMEOUT if timeout occurred waiting for
 *                  ack from server
 *
 *                  TFTP_RETRY if all server did not send ack
 *                  on time and application needs to resend
 *                  last block.
 *
 *                  TFTP_ERROR if remote server returned ERROR.
 *                  Actual error code may be read by calling
 *                  TFTPGetError()
 *
 *                  TFTP_NOT_READY if still waiting...
 *
 * Side Effects:    None
 *
 * Overview:        Waits for ack from server.  If ack does not
 *                  arrive within specified timeout, it it instructs
 *                  application to retry last block by returning
 *                  TFTP_RETRY.
 *
 *                  If all attempts are exhausted, it returns with
 *                  TFTP_TIMEOUT.
 *
 * Note:            None
 ********************************************************************/
TFTP_RESULT TFTPIsPutReady(void)
{
    WORD_VAL opCode;
    WORD_VAL blockNumber;
    BOOL bTimeOut;

    // Check to see if timeout has occurred.
    bTimeOut = FALSE;
    if ( TickGetDiff(TickGet(), _tftpStartTick) >= TFTP_GET_TIMEOUT_VAL )
    {
        bTimeOut = TRUE;
        _tftpStartTick = TickGet();
    }

    switch(_tftpState)
    {
    case SM_TFTP_WAIT_FOR_ACK:
        // When timeout occurs in this state, application must retry.
        if ( bTimeOut )
        {
            if ( _tftpRetries++ > (TFTP_MAX_RETRIES-1) )
            {
                DEBUG(printf("TFTPIsPutReady(): Timeout.\n"));

                // Forget about all previous attempts.
                _tftpRetries = 1;

                return TFTP_TIMEOUT;
            }

            else
            {
                DEBUG(printf("TFTPIsPutReady(): Retry.\n"));
                return TFTP_RETRY;
            }
        }

        // Must wait for ACK from server before we transmit next block.
        if ( !UDPIsGetReady(_tftpSocket) )
            break;

        // Get opCode.
        UDPGet(&opCode.byte.MSB);
        UDPGet(&opCode.byte.LSB);

        // Get block number.
        UDPGet(&blockNumber.byte.MSB);
        UDPGet(&blockNumber.byte.LSB);

        // Discard everything else.
        UDPDiscard();

        // This must be ACK or else there is a problem.
        if ( opCode.Val == TFTP_OPCODE_ACK )
        {
            // Also the block number must match with what we are expecting.
            if ( MutExVar.group2._tftpBlockNumber.Val == blockNumber.Val )
            {
                // Mark that block we sent previously has been ack'ed.
                _tftpFlags.bits.bIsAcked = TRUE;

                // Since we have ack, forget about previous retry count.
                _tftpRetries = 1;

                // If this file is being closed, this must be last ack.
                // Declare it as closed.
                if ( _tftpFlags.bits.bIsClosing )
                {
                    _tftpFlags.bits.bIsClosed = TRUE;
                    return TFTP_OK;
                }

                // Or else, wait for put to become ready so that caller
                // can transfer more data blocks.
                _tftpState = SM_TFTP_WAIT;
            }

            else
            {
                DEBUG(printf("TFTPIsPutReady(): "\
                    "Unexpected block %d received - droping it...\n", \
                    blockNumber.Val));
                return TFTP_NOT_READY;
            }
        }

        else if ( opCode.Val == TFTP_OPCODE_ERROR )
        {
            // For error opCode, remember error code so that application
            // can read it later.
            _tftpError = blockNumber.Val;

            // Declare error.
            return TFTP_ERROR;
        }
        else
            break;


    case SM_TFTP_WAIT:
        // Wait for UDP is to be ready to transmit.
        if ( UDPIsPutReady(_tftpSocket) )
        {
            // Put next block of data.
            MutExVar.group2._tftpBlockNumber.Val++;
            UDPPut(0);
            UDPPut(TFTP_OPCODE_DATA);

            UDPPut(MutExVar.group2._tftpBlockNumber.byte.MSB);
            UDPPut(MutExVar.group2._tftpBlockNumber.byte.LSB);

            // Remember that this block is not yet flushed.
            _tftpFlags.bits.bIsFlushed = FALSE;

            // Remember that this block is not acknowledged.
            _tftpFlags.bits.bIsAcked = FALSE;

            // Now, TFTP module is ready to put more data.
            _tftpState = SM_TFTP_READY;

            return TFTP_OK;
        }
        break;

    case SM_TFTP_READY:
        // TFTP module is said to be ready only when underlying UDP
        // is ready to transmit.
        if ( UDPIsPutReady(_tftpSocket) )
            return TFTP_OK;
    }

    return TFTP_NOT_READY;
}
Example #24
0
/*****************************************************************************
  Function:
	void _DHCPReceive(void)

  Description:
	Receives and parses a DHCP message.

  Precondition:
	A DHCP message is waiting in the UDP buffer.

  Parameters:
	None

  Returns:
  	One of the DCHP_TYPE* contants.
  ***************************************************************************/
static BYTE _DHCPReceive(void)
{
	/*********************************************************************
	        DHCP PACKET FORMAT AS PER RFC 1541
	
	   0                   1                   2                   3
	   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	   |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
	   +---------------+---------------+---------------+---------------+
	   |                            xid (4)                            |
	   +-------------------------------+-------------------------------+
	   |           secs (2)            |           flags (2)           |
	   +-------------------------------+-------------------------------+
	   |                          ciaddr  (4)                          |
	   +---------------------------------------------------------------+
	   |                          yiaddr  (4)                          |
	   +---------------------------------------------------------------+
	   |                          siaddr  (4)                          |
	   +---------------------------------------------------------------+
	   |                          giaddr  (4)                          |
	   +---------------------------------------------------------------+
	   |                                                               |
	   |                          chaddr  (16)                         |
	   |                                                               |
	   |                                                               |
	   +---------------------------------------------------------------+
	   |                                                               |
	   |                          sname   (64)                         |
	   +---------------------------------------------------------------+
	   |                                                               |
	   |                          file    (128)                        |
	   +---------------------------------------------------------------+
	   |                                                               |
	   |                          options (312)                        |
	   +---------------------------------------------------------------+
	
	 ********************************************************************/
    BYTE v;
    BYTE i, j;
    BYTE type;
    BOOL lbDone;
    DWORD_VAL tempServerID;


    // Assume unknown message until proven otherwise.
    type = DHCP_UNKNOWN_MESSAGE;

    UDPGet(&v);                             // op
    
    // Make sure this is BOOT_REPLY.
    if ( v == BOOT_REPLY )
    {
        // Discard htype, hlen, hops, xid, secs, flags, ciaddr.
        for ( i = 0; i < 15u; i++ )
            UDPGet(&v);

		// Check to see if this is the first offer
		if(DHCPFlags.bits.bOfferReceived)
		{
	        // Discard offered IP address, we already have an offer
	        for ( i = 0; i < 4u; i++ )
	            UDPGet(&v);
		}
		else
		{
	        // Save offered IP address until we know for sure that we have it.
			UDPGetArray((BYTE*)&tempIPAddress, sizeof(tempIPAddress));
			ValidValues.bits.IPAddress = 1;
		}

        // Ignore siaddr, giaddr
        for ( i = 0; i < 8u; i++ )
            UDPGet(&v);

        // Check to see if chaddr (Client Hardware Address) belongs to us.
        for ( i = 0; i < 6u; i++ )
        {
            UDPGet(&v);
            if ( v != AppConfig.MyMACAddr.v[i])
                goto UDPInvalid;
        }


        // Ignore part of chaddr, sname, file, magic cookie.
        for ( i = 0; i < 206u; i++ )
            UDPGet(&v);

        lbDone = FALSE;
        do
        {
			// Get the Option number
			// Break out eventually in case if this is a malformed 
			// DHCP message, ie: missing DHCP_END_OPTION marker
			if(!UDPGet(&v))
			{
				lbDone = TRUE;
				break;
			}

            switch(v)
            {
            case DHCP_MESSAGE_TYPE:
                UDPGet(&v);                         // Skip len
                // Len must be 1.
                if ( v == 1u )
                {
                    UDPGet(&type);                  // Get type

					// Throw away the packet if we know we don't need it (ie: another offer when we already have one)
					if(DHCPFlags.bits.bOfferReceived && (type == DHCP_OFFER_MESSAGE))
					{
						goto UDPInvalid;
					}
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_SUBNET_MASK:
                UDPGet(&v);                     // Skip len
                // Len must be 4.
                if ( v == 4u )
                {
					// Check to see if this is the first offer
					if(DHCPFlags.bits.bOfferReceived)
					{
				        // Discard offered IP mask, we already have an offer
				        for ( i = 0; i < 4u; i++ )
				            UDPGet(&v);
					}
					else
					{
						UDPGetArray((BYTE*)&tempMask, sizeof(tempMask));
						ValidValues.bits.Mask = 1;
					}
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_ROUTER:
                UDPGet(&j);
                // Len must be >= 4.
                if ( j >= 4u )
                {
					// Check to see if this is the first offer
					if(DHCPFlags.bits.bOfferReceived)
					{
				        // Discard offered Gateway address, we already have an offer
				        for ( i = 0; i < 4u; i++ )
				            UDPGet(&v);
					}
					else
					{
						UDPGetArray((BYTE*)&tempGateway, sizeof(tempGateway));
						ValidValues.bits.Gateway = 1;
					}
                }
                else
                    goto UDPInvalid;

                // Discard any other router addresses.
                j -= 4;
                while(j--)
                    UDPGet(&v);
                break;

#if defined(STACK_USE_DNS)
            case DHCP_DNS:
                UDPGet(&j);
                // Len must be >= 4.
                if(j < 4u)
                    goto UDPInvalid;

				// Check to see if this is the first offer
				if(!DHCPFlags.bits.bOfferReceived)
				{
					UDPGetArray((BYTE*)&tempDNS, sizeof(tempDNS));
					ValidValues.bits.DNS = 1;
					j -= 4;
				}

				// Len must be >= 4 for a secondary DNS server address
				if(j >= 4u)
				{
					// Check to see if this is the first offer
					if(!DHCPFlags.bits.bOfferReceived)
					{
						UDPGetArray((BYTE*)&tempDNS2, sizeof(tempDNS2));
						ValidValues.bits.DNS2 = 1;
						j -= 4;
					}
				}

                // Discard any other DNS server addresses
                while(j--)
                    UDPGet(&v);
                break;
#endif

//            case DHCP_HOST_NAME:
//                UDPGet(&j);
//                // Len must be >= 4.
//                if(j < 1u)
//					goto UDPInvalid;
//
//				// Check to see if this is the first offer
//				if(DHCPFlags.bits.bOfferReceived)
//				{
//			        // Discard offered host name, we already have an offer
//	                while(j--)
//	                    UDPGet(&v);
//				}
//				else
//				{
//					for(i = 0; j, i < sizeof(tempHostName); i++, j--)
//					{
//						UDPGet(&tempHostName[i]);
//					}
//					while(j--)
//					{
//						UDPGet(&v);
//					}
//					ValidValues.bits.HostName = 1;
//				}
//
//                break;

            case DHCP_SERVER_IDENTIFIER:
                UDPGet(&v);                         // Get len
                // Len must be 4.
                if ( v == 4u )
                {
                    UDPGet(&tempServerID.v[3]);   // Get the id
                    UDPGet(&tempServerID.v[2]);
                    UDPGet(&tempServerID.v[1]);
                    UDPGet(&tempServerID.v[0]);
                }
                else
                    goto UDPInvalid;
                break;

            case DHCP_END_OPTION:
                lbDone = TRUE;
                break;

            case DHCP_IP_LEASE_TIME:
                UDPGet(&v);                         // Get len
                // Len must be 4.
                if ( v == 4u )
                {
					// Check to see if this is the first offer
					if(DHCPFlags.bits.bOfferReceived)
					{
				        // Discard offered lease time, we already have an offer
				        for ( i = 0; i < 4u; i++ )
				            UDPGet(&v);
					}
					else
					{
	                    UDPGet(&DHCPLeaseTime.v[3]);
	                    UDPGet(&DHCPLeaseTime.v[2]);
	                    UDPGet(&DHCPLeaseTime.v[1]);
	                    UDPGet(&DHCPLeaseTime.v[0]);

	                    // In case if our clock is not as accurate as the remote 
						// DHCP server's clock, let's treat the lease time as only 
						// 96.875% of the value given
						DHCPLeaseTime.Val -= DHCPLeaseTime.Val>>5;
					}
                }
                else
                    goto UDPInvalid;
                break;

            default:
                // Ignore all unsupport tags.
                UDPGet(&j);                     // Get option len
                while( j-- )                    // Ignore option values
                    UDPGet(&v);
            }
        } while( !lbDone );
    }

    // If this is an OFFER message, remember current server id.
    if ( type == DHCP_OFFER_MESSAGE )
    {
        DHCPServerID.Val = tempServerID.Val;
		DHCPFlags.bits.bOfferReceived = TRUE;
    }
    else
    {
        // For other types of messages, make sure that received
        // server id matches with our previous one.
        if ( DHCPServerID.Val != tempServerID.Val )
            type = DHCP_UNKNOWN_MESSAGE;
    }

    UDPDiscard();                             // We are done with this packet
    return type;

UDPInvalid:
    UDPDiscard();
    return DHCP_UNKNOWN_MESSAGE;

}
Example #25
0
/**************************************************************************
  Function:
 	void SNMPTrapDemo(void)
 
  Summary:	
  	Send trap pdu demo application.
 	  	  
  Description:		
	This routine sends a trap pdu for the predefined ip addresses with the
	agent. The "event" to generate this trap pdu is "BUTTON_PUSH_EVENT". Whenever
	there occurs a specific button push, this routine is called and sends
	a trap containing PUSH_BUTTON mib var OID and notification type 
	as authentication failure. 
       
  PreCondition:
 	Application defined event occurs to send the trap.
 	
  parameters:
     None.
 
  Returns:          
 	 None.
 
  Remarks:
    This routine guides how to build a event generated trap notification.
    The application should make use of SNMPSendTrap() routine to generate 
    and send trap.
 *************************************************************************/
void SNMPTrapDemo(void)
{
	static SYS_TICK TimerRead=0;
	static bool analogPotNotify = false,buttonPushNotify=false;
	static uint8_t anaPotNotfyCntr=0,buttonPushNotfyCntr=0;
	static SNMP_VAL buttonPushval,analogPotVal;
	static uint8_t potReadLock=false,buttonLock=false;
	static uint8_t timeLock=false;
	static uint8_t maxTryToSendTrap=0;
	
	if(timeLock==(uint8_t)false)
	{
		TimerRead=SYS_TICK_Get();
		timeLock=true;
	}

	#if 1
	if(anaPotNotfyCntr >= trapInfo.Size)
	{
		anaPotNotfyCntr = 0;
		potReadLock=false;
		//analogPotNotify = false;
		analogPotNotify = true;
	}
	#endif
	
	if(!analogPotNotify)
	{
		//Read POT reading once and send trap to all configured recipient
		if(potReadLock ==(uint8_t)false)
		{
            analogPotVal.word= (uint16_t)ADC1BUF0;
			
			//Avoids Reading POT for every iteration unless trap sent to each configured recipients 
			potReadLock=true; 
		}
		if(trapInfo.table[anaPotNotfyCntr].Flags.bEnabled)
		{
			if(analogPotVal.word >512u)
			{
				gSpecificTrapNotification=POT_READING_MORE_512;
				gGenericTrapNotification=ENTERPRISE_SPECIFIC;
				if(SendNotification(anaPotNotfyCntr, ANALOG_POT0, analogPotVal))
					anaPotNotfyCntr++;
				else
				{					
					if(maxTryToSendTrap>=MAX_TRY_TO_SEND_TRAP)
					{
						anaPotNotfyCntr++;
						maxTryToSendTrap = 0;
						return;
					}
					maxTryToSendTrap++;
					return ;
				}
			}
		}
		else
			anaPotNotfyCntr++;
			
	}


	if(buttonPushNotfyCntr==trapInfo.Size)
	{
		buttonPushNotfyCntr = 0;
		buttonLock=false;
		buttonPushNotify = false;
	}


	if(buttonLock == (uint8_t)false)
	{
		if(BUTTON3_IO == 0u)
		{
			buttonPushNotify = true;
			buttonLock =true;
		}
	}

	if(buttonPushNotify)
	{			  
		buttonPushval.byte = 0;
		if ( trapInfo.table[buttonPushNotfyCntr].Flags.bEnabled )
		{
			gSpecificTrapNotification=BUTTON_PUSH_EVENT;
			gGenericTrapNotification=ENTERPRISE_SPECIFIC;
			if(SendNotification(buttonPushNotfyCntr, PUSH_BUTTON, buttonPushval))
				buttonPushNotfyCntr++;
		}
		else
			buttonPushNotfyCntr++;
	}

	//Try for max 5 seconds to send TRAP, do not get block in while()
	if((SYS_TICK_Get()-TimerRead)>(5*SYS_TICK_TicksPerSecondGet()))
	{
		UDPDiscard(s, gpSnmpIf);    
		buttonPushNotfyCntr = 0;
		buttonLock=false;
		buttonPushNotify = false;
		anaPotNotfyCntr = 0;
		potReadLock=false;
		analogPotNotify = false;
		timeLock=false;
		gSpecificTrapNotification=VENDOR_TRAP_DEFAULT;
		gGenericTrapNotification=ENTERPRISE_SPECIFIC;
		return;
	}

}
Example #26
0
/*********************************************************************
 * Function:        void DiscoveryTask(void)
 *
 * Summary:         Announce callback task.
 *
 * PreCondition:    Stack is initialized()
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Recurring task used to listen for Discovery
 *                  messages on the specified ANNOUNCE_PORT.  These
 *                  messages can be sent using the Microchip Device
 *                  Discoverer tool. If one is received, this
 *                  function will transmit a reply.
 *
 * Note:            A UDP socket must be available before this 
 *					function is called.  It is freed at the end of 
 *					the function.  MAX_UDP_SOCKETS may need to be 
 *					increased if other modules use UDP sockets.
 ********************************************************************/
void DiscoveryTask(void)
{
	static enum {
		DISCOVERY_HOME = 0,
		DISCOVERY_LISTEN,
		DISCOVERY_REQUEST_RECEIVED,
		DISCOVERY_DISABLED
	} DiscoverySM = DISCOVERY_HOME;

	static UDP_SOCKET	MySocket;
	BYTE 				i;
	
	switch(DiscoverySM)
	{
		case DISCOVERY_HOME:
			// Open a UDP socket for inbound and outbound transmission
			// Since we expect to only receive broadcast packets and 
			// only send unicast packets directly to the node we last 
			// received from, the remote NodeInfo parameter can be anything
			MySocket = UDPOpen(ANNOUNCE_PORT, NULL, ANNOUNCE_PORT);

			if(MySocket == INVALID_UDP_SOCKET)
				return;
			else
				DiscoverySM++;
			break;

		case DISCOVERY_LISTEN:
			// Do nothing if no data is waiting
			if(!UDPIsGetReady(MySocket))
				return;
			
			// See if this is a discovery query or reply
			UDPGet(&i);
			UDPDiscard();
			if(i != 'D')
				return;

			// We received a discovery request, reply when we can
			DiscoverySM++;

			// Change the destination to the unicast address of the last received packet
        	memcpy((void*)&UDPSocketInfo[MySocket].remoteNode, (const void*)&remoteNode, sizeof(remoteNode));
			
			// No break needed.  If we get down here, we are now ready for the DISCOVERY_REQUEST_RECEIVED state

		case DISCOVERY_REQUEST_RECEIVED:
			if(!UDPIsPutReady(MySocket))
				return;

			// Begin sending our MAC address in human readable form.
			// The MAC address theoretically could be obtained from the 
			// packet header when the computer receives our UDP packet, 
			// however, in practice, the OS will abstract away the useful
			// information and it would be difficult to obtain.  It also 
			// would be lost if this broadcast packet were forwarded by a
			// router to a different portion of the network (note that 
			// broadcasts are normally not forwarded by routers).
			UDPPutArray((BYTE*)AppConfig.NetBIOSName, sizeof(AppConfig.NetBIOSName)-1);
			UDPPut('\r');
			UDPPut('\n');
		
			// Convert the MAC address bytes to hex (text) and then send it
			i = 0;
			while(1)
			{
				UDPPut(btohexa_high(AppConfig.MyMACAddr.v[i]));
			    UDPPut(btohexa_low(AppConfig.MyMACAddr.v[i]));
			    if(++i == 6u)
			    	break;
			    UDPPut('-');
			}
			UDPPut('\r');
			UDPPut('\n');

			// Send the packet
			UDPFlush();

			// Listen for other discovery requests
			DiscoverySM = DISCOVERY_LISTEN;
			break;

		case DISCOVERY_DISABLED:
			break;
	}	

}
Example #27
0
/*****************************************************************************
  Function:
	void DNSClientTask(void)

  Summary:
	DNS client state machine
	
  Description:
    Process the DNS client state machine
  
  Precondition:
	DNSClientInit has been called.

  Parameters:
    None
    
  Return Values:
    None

  ***************************************************************************/
void DNSClientTask(void)
{
	uint8_t 				i;
	TCPIP_UINT16_VAL			w;
	DNS_HEADER			DNSHeader;
	DNS_ANSWER_HEADER	DNSAnswerHeader;
    

    switch(smDNS)
	{
		case DNS_IDLE:
            break;  // nothing to do

		case DNS_START:
            smDNS = DNSRetry(DNS_START);
            stateStartTime = 0;  // flag the first Open try
			break;

		case DNS_OPEN_SOCKET:
            DNSSocket = UDPOpenClient(IP_ADDRESS_TYPE_IPV4, DNS_CLIENT_PORT, (IP_MULTI_ADDRESS*)(DNSServers + vDNSServerIx));
			if(DNSSocket == INVALID_UDP_SOCKET)
            {
                if(stateStartTime == 0)
                {
                    stateStartTime = SYS_TICK_Get();
                }
                else if(SYS_TICK_Get() - stateStartTime > (DNS_CLIENT_OPEN_TMO * SYS_TICK_TicksPerSecondGet()))
                {
					smDNS = DNS_FAIL_OPEN_TMO;
                }
                
                break;
            }
            
            // got a valid UDP socket
            UDPSocketSetNet(DNSSocket, pDNSNet);
            stateStartTime = SYS_TICK_Get();
            smDNS = DNS_QUERY;
            // no break, start sending the query;

		case DNS_QUERY:
            if(!UDPIsOpened(DNSSocket) || (UDPIsTxPutReady(DNSSocket, 18 + strlen (DNSHostName)) < (18 + strlen (DNSHostName))))
            {
                if(SYS_TICK_Get() - stateStartTime > (DNS_CLIENT_OPEN_TMO * SYS_TICK_TicksPerSecondGet()))
                {
					smDNS = DNS_FAIL_OPEN_TMO;
                }
                
				break;  // wait some more
            }
			
			// Put DNS query here
			SentTransactionID.Val = (uint16_t)rand();
			UDPPut(DNSSocket, SentTransactionID.v[1]);// User chosen transaction ID
			UDPPut(DNSSocket, SentTransactionID.v[0]);
			UDPPut(DNSSocket, 0x01);		// Standard query with recursion
			UDPPut(DNSSocket, 0x00);	
			UDPPut(DNSSocket, 0x00);		// 0x0001 questions
			UDPPut(DNSSocket, 0x01);
			UDPPut(DNSSocket, 0x00);		// 0x0000 answers
			UDPPut(DNSSocket, 0x00);
			UDPPut(DNSSocket, 0x00);		// 0x0000 name server resource records
			UDPPut(DNSSocket, 0x00);
			UDPPut(DNSSocket, 0x00);		// 0x0000 additional records
			UDPPut(DNSSocket, 0x00);

			// Put hostname string to resolve
            DNSPutString(DNSSocket, DNSHostName);

			UDPPut(DNSSocket, 0x00);		// Type: DNS_TYPE_A A (host address) or DNS_TYPE_MX for mail exchange
			UDPPut(DNSSocket, RecordType);
			UDPPut(DNSSocket, 0x00);		// Class: IN (Internet)
			UDPPut(DNSSocket, 0x01);

			UDPFlush(DNSSocket);
			stateStartTime = SYS_TICK_Get();
			smDNS = DNS_GET_RESULT;
			break;

		case DNS_GET_RESULT:
			if(!UDPIsGetReady(DNSSocket))
			{
				if(SYS_TICK_Get() - stateStartTime > (DNS_CLIENT_SERVER_TMO * SYS_TICK_TicksPerSecondGet()))
                {
					smDNS = DNS_FAIL_SERVER;
                }
				break;
			}


			// Retrieve the DNS header and de-big-endian it
			UDPGet(DNSSocket, &DNSHeader.TransactionID.v[1]);
			UDPGet(DNSSocket, &DNSHeader.TransactionID.v[0]);

			// Throw this packet away if it isn't in response to our last query
			if(DNSHeader.TransactionID.Val != SentTransactionID.Val)
			{
				UDPDiscard(DNSSocket);
				break;
			}

			UDPGet(DNSSocket, &DNSHeader.Flags.v[1]);
			UDPGet(DNSSocket, &DNSHeader.Flags.v[0]);
			UDPGet(DNSSocket, &DNSHeader.Questions.v[1]);
			UDPGet(DNSSocket, &DNSHeader.Questions.v[0]);
			UDPGet(DNSSocket, &DNSHeader.Answers.v[1]);
			UDPGet(DNSSocket, &DNSHeader.Answers.v[0]);
			UDPGet(DNSSocket, &DNSHeader.AuthoritativeRecords.v[1]);
			UDPGet(DNSSocket, &DNSHeader.AuthoritativeRecords.v[0]);
			UDPGet(DNSSocket, &DNSHeader.AdditionalRecords.v[1]);
			UDPGet(DNSSocket, &DNSHeader.AdditionalRecords.v[0]);

			// Remove all questions (queries)
			while(DNSHeader.Questions.Val--)
			{
				DNSDiscardName(DNSSocket);
				UDPGet(DNSSocket, &w.v[1]);		// Question type
				UDPGet(DNSSocket, &w.v[0]);
				UDPGet(DNSSocket, &w.v[1]);		// Question class
				UDPGet(DNSSocket, &w.v[0]);
			}
			
			// Scan through answers
			while(DNSHeader.Answers.Val--)
			{				
				DNSDiscardName(DNSSocket);					// Throw away response name
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A, MX, or AAAA
				if( DNSAnswerHeader.ResponseClass.Val	== 0x0001u) // Internet class
				{
                    if (DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
    					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
                    {
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV4;
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[0]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[1]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[2]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[3]);
    					goto DoneSearchingRecords;
                    }
                    else if (DNSAnswerHeader.ResponseType.Val == 0x001Cu &&
    					        DNSAnswerHeader.ResponseLen.Val	== 0x0010u)
                    {
                        if (RecordType != DNS_TYPE_AAAA)
                        {
        					while(DNSAnswerHeader.ResponseLen.Val--)
        					{
        						UDPGet(DNSSocket, &i);
        					}
                            break;
                        }
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV6;
                        UDPGetArray (DNSSocket, (void *)&ResolvedAddress.ipv6Address, sizeof (IPV6_ADDR));
    					goto DoneSearchingRecords;                        
                    }
                    else
                    {
    					while(DNSAnswerHeader.ResponseLen.Val--)
    					{
    						UDPGet(DNSSocket, &i);
    					}
                    }
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(DNSSocket, &i);
					}
				}
			}

			// Remove all Authoritative Records
			while(DNSHeader.AuthoritativeRecords.Val--)
			{
				DNSDiscardName(DNSSocket);					// Throw away response name
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A
				if( DNSAnswerHeader.ResponseClass.Val	== 0x0001u) // Internet class
				{
                    if (DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
    					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
                    {
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV4;
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[0]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[1]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[2]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[3]);
    					goto DoneSearchingRecords;
                    }
                    else if (DNSAnswerHeader.ResponseType.Val == 0x001Cu &&
    					        DNSAnswerHeader.ResponseLen.Val	== 0x0010u)
                    {
                        if (RecordType != DNS_TYPE_AAAA)
                        {
        					while(DNSAnswerHeader.ResponseLen.Val--)
        					{
        						UDPGet(DNSSocket, &i);
        					}
                            break;
                        }
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV6;
                        UDPGetArray (DNSSocket, (void *)&ResolvedAddress.ipv6Address, sizeof (IPV6_ADDR));
    					goto DoneSearchingRecords;                        
                    }
                    else
                    {
    					while(DNSAnswerHeader.ResponseLen.Val--)
    					{
    						UDPGet(DNSSocket, &i);
    					}
                    }
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(DNSSocket, &i);
					}
				}
			}

			// Remove all Additional Records
			while(DNSHeader.AdditionalRecords.Val--)
			{
				DNSDiscardName(DNSSocket);					// Throw away response name
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[1]);		// Response type
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseType.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[1]);	// Response class
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseClass.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[3]);		// Time to live
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[2]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[1]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseTTL.v[0]);
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[1]);		// Response length
				UDPGet(DNSSocket, &DNSAnswerHeader.ResponseLen.v[0]);

				// Make sure that this is a 4 byte IP address, response type A or MX, class 1
				// Check if this is Type A
				if( DNSAnswerHeader.ResponseClass.Val	== 0x0001u) // Internet class
				{
                    if (DNSAnswerHeader.ResponseType.Val	== 0x0001u &&
    					DNSAnswerHeader.ResponseLen.Val		== 0x0004u)
                    {
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV4;
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[0]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[1]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[2]);
    					UDPGet(DNSSocket, &ResolvedAddress.ipv4Address.v[3]);
    					goto DoneSearchingRecords;
                    }
                    else if (DNSAnswerHeader.ResponseType.Val == 0x001Cu &&
    					        DNSAnswerHeader.ResponseLen.Val	== 0x0010u)
                    {
                        if (RecordType != DNS_TYPE_AAAA)
                        {
        					while(DNSAnswerHeader.ResponseLen.Val--)
        					{
        						UDPGet(DNSSocket, &i);
        					}
                            break;
                        }
    					Flags.bits.AddressValid = true;
                        Flags.bits.AddressType = IP_ADDRESS_TYPE_IPV6;
                        UDPGetArray (DNSSocket, (void *)&ResolvedAddress.ipv6Address, sizeof (IPV6_ADDR));
    					goto DoneSearchingRecords;                        
                    }
                    else
                    {
    					while(DNSAnswerHeader.ResponseLen.Val--)
    					{
    						UDPGet(DNSSocket, &i);
    					}
                    }
				}
				else
				{
					while(DNSAnswerHeader.ResponseLen.Val--)
					{
						UDPGet(DNSSocket, &i);
					}
				}
			}

DoneSearchingRecords:

			UDPDiscard(DNSSocket);
            _DNSReleaseSocket();
			if(Flags.bits.AddressValid)
            {
                smDNS = DNS_DONE;
            }
            else
            {
                smDNS = DNSRetry(DNS_FAIL_SERVER);
            }
            break;  // done
            
		case DNS_FAIL_ARP:
            // see if there is other server we may try
            smDNS = DNSRetry(DNS_FAIL_ARP);
            break;

		case DNS_FAIL_SERVER:
            smDNS = DNSRetry(DNS_FAIL_SERVER);
			break;

        default:    // DNS_DONE, DNS_FAIL_ARP_TMO, DNS_FAIL_OPEN_TMO, DNS_FAIL_SERVER_TMO  
            // either done or some error state
            break;
	}
    
#if DNS_CLIENT_VERSION_NO >= 2
    dnsTickPending = 0;
#endif  // DNS_CLIENT_VERSION_NO >= 2
}
Example #28
0
/**************************************************************************
  Function:
 	void SNMPTrapDemo(void)
 
  Summary:	
  	Send trap pdu demo application.
 	  	  
  Description:		
	This routine sends a trap pdu for the predefined ip addresses with the
	agent. The "event" to generate this trap pdu is "BUTTON_PUSH_EVENT". Whenever
	there occurs a specific button push, this routine is called and sends
	a trap containing PUSH_BUTTON mib var OID and notification type 
	as authentication failure. 
       
  PreCondition:
 	Application defined event occurs to send the trap.
 	
  parameters:
     None.
 
  Returns:          
 	 None.
 
  Remarks:
    This routine guides how to build a event generated trap notification.
    The application should make use of SNMPSendTrap() routine to generate 
    and send trap.
 *************************************************************************/
void SNMPTrapDemo(void)
{
	static DWORD TimerRead=0;
	static BOOL analogPotNotify = FALSE,buttonPushNotify=FALSE;
	static BYTE anaPotNotfyCntr=0,buttonPushNotfyCntr=0;
	static SNMP_VAL buttonPushval,analogPotVal;
	static BYTE potReadLock=FALSE,buttonLock=FALSE;
	static BYTE timeLock=FALSE;
	static BYTE maxTryToSendTrap=0;
	
	if(timeLock==(BYTE)FALSE)
	{
		TimerRead=TickGet();
		timeLock=TRUE;
	}

	#if 1
	if(anaPotNotfyCntr >= trapInfo.Size)
	{
		anaPotNotfyCntr = 0;
		potReadLock=FALSE;
		//analogPotNotify = FALSE;
		analogPotNotify = TRUE;
	}
	#endif
	
	if(!analogPotNotify)
	{
		//Read POT reading once and send trap to all configured recipient
		if(potReadLock ==(BYTE)FALSE)
		{
			#if defined(__18CXX)
				// Wait until A/D conversion is done
				ADCON0bits.GO = 1;
				while(ADCON0bits.GO);

				// Convert 10-bit value into ASCII string
				analogPotVal.word= (WORD)ADRES;
			#else
				analogPotVal.word= (WORD)ADC1BUF0;
			#endif
			
			//Avoids Reading POT for every iteration unless trap sent to each configured recipients 
			potReadLock=TRUE; 
		}
		if(trapInfo.table[anaPotNotfyCntr].Flags.bEnabled)
		{
			if(analogPotVal.word >512u)
			{
				gSpecificTrapNotification=POT_READING_MORE_512;
				gGenericTrapNotification=ENTERPRISE_SPECIFIC;
				if(SendNotification(anaPotNotfyCntr, ANALOG_POT0, analogPotVal))
					anaPotNotfyCntr++;
				else
				{					
					if(maxTryToSendTrap>=MAX_TRY_TO_SEND_TRAP)
					{
						anaPotNotfyCntr++;
						maxTryToSendTrap = 0;
						return;
					}
					maxTryToSendTrap++;
					return ;
				}
			}
		}
		else
			anaPotNotfyCntr++;
			
	}


	if(buttonPushNotfyCntr==trapInfo.Size)
	{
		buttonPushNotfyCntr = 0;
		buttonLock=FALSE;
		buttonPushNotify = FALSE;
	}


	if(buttonLock == (BYTE)FALSE)
	{
		if(BUTTON3_IO == 0u)
		{
			buttonPushNotify = TRUE;
			buttonLock =TRUE;
		}
	}

	if(buttonPushNotify)
	{			  
		buttonPushval.byte = 0;
		if ( trapInfo.table[buttonPushNotfyCntr].Flags.bEnabled )
		{
			gSpecificTrapNotification=BUTTON_PUSH_EVENT;
			gGenericTrapNotification=ENTERPRISE_SPECIFIC;
			if(SendNotification(buttonPushNotfyCntr, PUSH_BUTTON, buttonPushval))
				buttonPushNotfyCntr++;
		}
		else
			buttonPushNotfyCntr++;
	}

	//Try for max 5 seconds to send TRAP, do not get block in while()
	if((TickGet()-TimerRead)>(5*TICK_SECOND))
	{
		UDPDiscard();
		buttonPushNotfyCntr = 0;
		buttonLock=FALSE;
		buttonPushNotify = FALSE;
		anaPotNotfyCntr = 0;
		potReadLock=FALSE;
		analogPotNotify = FALSE;
		timeLock=FALSE;
		gSpecificTrapNotification=VENDOR_TRAP_DEFAULT;
		gGenericTrapNotification=ENTERPRISE_SPECIFIC;
		return;
	}

}
Example #29
0
bool NBNSTask(TCPIP_NET_IF* pNetIf)
{
	uint8_t 			i;
	TCPIP_UINT16_VAL    Type, Class;
	NBNS_HEADER			NBNSHeader;
	uint8_t				NameString[16];
    UDP_SOCKET          s;
    int                 nbnsRxSize;
    int                 nbnsTxSize;

    s = nbnsDcpt.uSkt;

	switch(nbnsDcpt.sm)
    {
        case NBNS_HOME:
            nbnsDcpt.sm++;
            break;

        case NBNS_OPEN_SOCKET:
            s = UDPOpenServer(IP_ADDRESS_TYPE_IPV4, NBNS_PORT, 0);
            if(s == INVALID_UDP_SOCKET)
                break;

            if(!UDPRemoteBind(s, IP_ADDRESS_TYPE_IPV4, NBNS_PORT,  0))
            {
                UDPClose(s);
                break;
            }

            nbnsDcpt.uSkt = s;
            nbnsDcpt.sm++;

        case NBNS_LISTEN:
            //if(!UDPIsGetReady(s))
            nbnsRxSize = UDPIsGetReady(s);
            if(!nbnsRxSize)
            {
                break;
            }


            // Respond only to name requests sent to us from nodes on the same subnet
            // This prevents us from sending out the wrong IP address information if 
            // we haven't gotten a DHCP lease yet.
            if((remoteNode.IPAddr.Val & pNetIf->netMask.Val) != (pNetIf->netIPAddr.Val & pNetIf->netMask.Val))
            {
                UDPDiscard(s);
                break;
            }

#ifdef _NBNS_DEBUG
            nbnsRxOks++;
            if(nbnsRxSize > nbnsRxMaxSize)
            {
                nbnsRxMaxSize = nbnsRxSize;
            }
#endif  // _NBNS_DEBUG
            // Retrieve the NBNS header and de-big-endian it
            UDPGet(s, &NBNSHeader.TransactionID.v[1]);
            UDPGet(s, &NBNSHeader.TransactionID.v[0]);
            UDPGet(s, &NBNSHeader.Flags.v[1]);
            UDPGet(s, &NBNSHeader.Flags.v[0]);
            UDPGet(s, &NBNSHeader.Questions.v[1]);
            UDPGet(s, &NBNSHeader.Questions.v[0]);
            UDPGet(s, &NBNSHeader.Answers.v[1]);
            UDPGet(s, &NBNSHeader.Answers.v[0]);
            UDPGet(s, &NBNSHeader.AuthoritativeRecords.v[1]);
            UDPGet(s, &NBNSHeader.AuthoritativeRecords.v[0]);
            UDPGet(s, &NBNSHeader.AdditionalRecords.v[1]);
            UDPGet(s, &NBNSHeader.AdditionalRecords.v[0]);

            // Remove all questions
            while(NBNSHeader.Questions.Val--)
            {
                NBNSGetName(s, NameString);
                UDPGet(s, &i);				// <??> Trailing character on string
                UDPGet(s, &Type.v[1]);		// Question type
                UDPGet(s, &Type.v[0]);
                UDPGet(s, &Class.v[1]);	// Question class
                UDPGet(s, &Class.v[0]);

                if(Type.Val == 0x0020u && Class.Val == 0x0001u)
                {
                    int nIfs, nIx;
                    TCPIP_NET_IF*   pIf;
                    const char*     netbName;

                    nIfs = TCPIP_STACK_NetworksNo();
                    for(nIx = 0; nIx < nIfs; nIx++)
                    { 
                        pIf = (TCPIP_NET_IF*)TCPIP_STACK_IxToNet(nIx); 
                        netbName = TCPIP_STACK_NetBIOSName(pIf);    // this checks the IF is up!
                        if(memcmp((void*)NameString, netbName, sizeof(pIf->NetBIOSName)) == 0)
                        {   // one of our interfaces has this name
                            nbnsTxSize = UDPIsTxPutReady(s, 64);
                            if(nbnsTxSize)
                            {   
#ifdef _NBNS_DEBUG
                                nbnsTxOks++;    
                                if(nbnsTxSize > nbnsTxMaxSize)
                                {
                                    nbnsTxMaxSize = nbnsTxSize;
                                }
#endif  // _NBNS_DEBUG

                                NBNSHeader.Flags.Val = 0x8400;

                                UDPPut(s, NBNSHeader.TransactionID.v[1]);
                                UDPPut(s, NBNSHeader.TransactionID.v[0]);
                                UDPPut(s, NBNSHeader.Flags.v[1]);
                                UDPPut(s, NBNSHeader.Flags.v[0]);
                                UDPPut(s, 0x00);	// 0x0000 Questions
                                UDPPut(s, 0x00);
                                UDPPut(s, 0x00);	// 0x0001 Answers
                                UDPPut(s, 0x01);
                                UDPPut(s, 0x00);	// 0x0000 Athoritative records
                                UDPPut(s, 0x00);
                                UDPPut(s, 0x00);	// 0x0000 Additional records
                                UDPPut(s, 0x00);

                                NBNSPutName(s, netbName);
                                UDPPut(s, 0x00);	// 0x0020 Type: NetBIOS
                                UDPPut(s, 0x20);
                                UDPPut(s, 0x00);	// 0x0001 Class: Internet
                                UDPPut(s, 0x01);
                                UDPPut(s, 0x00);	// 0x00000000 Time To Live
                                UDPPut(s, 0x00);
                                UDPPut(s, 0x00);
                                UDPPut(s, 0x00);

                                UDPPut(s, 0x00);	// 0x0006 Data length
                                UDPPut(s, 0x06);	
                                UDPPut(s, 0x60);	// 0x6000 Flags: H-node, Unique
                                UDPPut(s, 0x00);
                                UDPPut(s, pIf->netIPAddr.v[0]);	// Put out IP address
                                UDPPut(s, pIf->netIPAddr.v[1]);
                                UDPPut(s, pIf->netIPAddr.v[2]);
                                UDPPut(s, pIf->netIPAddr.v[3]);

                                // Change the destination address to the unicast address of the last received packet
                                UDPSetDestinationIPAddress(s, IP_ADDRESS_TYPE_IPV4, (IP_MULTI_ADDRESS*)&remoteNode.IPAddr);
                                memcpy((void*)&((IPV4_PACKET*)UDPSocketDcpt[s].pTxPkt)->remoteMACAddr, (const void*)&remoteNode.MACAddr, sizeof(remoteNode.MACAddr));
                                UDPFlush(s);				
                            }
#ifdef _NBNS_DEBUG
                            else
                            {
                                nbnsTxFails++;
                            }
#endif  // _NBNS_DEBUG
                            break;
                        }
                    }
                }
            }

            UDPDiscard(s);

            break;
    }

    return true;
}
Example #30
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)
{
    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;
		}
	}
}