Ejemplo n.º 1
0
static void DNSPutString(BYTE *String)
{
    BYTE *RightPtr;
    BYTE i;
    BYTE Len;

    RightPtr = String;

    while(1)
    {
        do
        {
            i = *RightPtr++;
        } while((i != 0x00) && (i != '.') && (i != '/'));
    
        // Put the length parameter
        Len = (BYTE)(RightPtr-String-1);
        UDPPut(Len);
        while(Len--)
        {
            UDPPut(*String++);
        }
        if(i == 0x00 || i == '/')
            break;

        // Skip over the '.' in the input string
        String++;
    }
    
    // Put the string terminator character
    UDPPut(0x00);
}
Ejemplo n.º 2
0
Archivo: DNS.c Proyecto: CEIT-UQ/RGB
static void DNSPutROMString(ROM BYTE* String)
{
	ROM BYTE *RightPtr;
	BYTE i;
	BYTE Len;

	RightPtr = String;

	while(1)
	{
		do
		{
			i = *RightPtr++;
		} while((i != 0x00u) && (i != '.') && (i != '/') && (i != ',') && (i != '>'));
	
		// Put the length and data
		// Also, skip over the '.' in the input string
		Len = (BYTE)(RightPtr-String-1);
		UDPPut(Len);
		String += UDPPutROMArray(String, Len) + 1;

		if(i == 0x00u || i == '/' || i == ',' || i == '>')
			break;
	}
	
	// Put the string terminator character (zero length label)
	UDPPut(0x00);
}
Ejemplo n.º 3
0
/*****************************************************************************
  Function:
	static void DNSPutString(UDP_SOCKET s, const char* String)

  Summary:
	Writes a string to the DNS socket.
	
  Description:
	This function writes a string to the DNS socket, ensuring that it is
	properly formatted.

  Precondition:
	UDP socket is obtained and ready for writing.

  Parameters:
	String - the string to write to the UDP socket.

  Returns:
  	None
  ***************************************************************************/
static void DNSPutString(UDP_SOCKET s, const char* String)
{
	const char *RightPtr;
	uint8_t i;
	uint8_t Len;

	RightPtr = String;

	while(1)
	{
		do
		{
			i = *RightPtr++;
		} while((i != 0x00u) && (i != '.') && (i != '/') && (i != ',') && (i != '>'));
	
		// Put the length and data
		// Also, skip over the '.' in the input string
		Len = (uint8_t)(RightPtr-String-1);
		UDPPut(s, Len);
		String += UDPPutArray(s, (uint8_t*)String, Len) + 1;

		if(i == 0x00u || i == '/' || i == ',' || i == '>')
			break;
	}
	
	// Put the string null terminator character (zero length label)
	UDPPut(s, 0x00);
}
Ejemplo n.º 4
0
static void _TFTPSendFileName(TFTP_OPCODE opcode, char *fileName)
{
    BYTE c;

    // Write opCode
    UDPPut(0);
    UDPPut(opcode);

    // write file name, including NULL.
    do
    {
        c = *fileName++;
        UDPPut(c);
    } while ( c != '\0' );

    // Write mode - always use octet or binay mode to transmit files.
    UDPPut('o');
    UDPPut('c');
    UDPPut('t');
    UDPPut('e');
    UDPPut('t');
    UDPPut(0);

    // Transmit it.
    UDPFlush();

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

}
Ejemplo n.º 5
0
/****************************************************************************************************
  Function:
            void AnnounceIP(void)
    
  Summary:
    Transmits an Announce packet.
  Conditions:
    Stack is initialized()
  Return:
    None
  Side Effects:
    None
  Description:
    AnnounceIP opens a UDP socket and transmits a broadcast packet to port
    \30303. If a computer is on the same subnet and a utility is looking
    for packets on the UDP port, it will receive the broadcast. For this
    application, it is used to announce the change of this board's IP
    address. The messages can be viewed with the TCP/IP Discoverer
    software tool.
  Remarks:
    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 AnnounceIP(void)
{
	UDP_SOCKET	MySocket;
	BYTE 		i;

	if(!MACIsLinked())  // Check for link before blindly opening and transmitting (similar to DHCP case)
		return;

	// Open a UDP socket for outbound broadcast transmission
	//MySocket = UDPOpen(2860, NULL, ANNOUNCE_PORT);
	MySocket = UDPOpenEx(0,UDP_OPEN_SERVER,2860, ANNOUNCE_PORT);
            LED1_IO = 0;

	// Abort operation if no UDP sockets are available
	// If this ever happens, incrementing MAX_UDP_SOCKETS in 
	// StackTsk.h may help (at the expense of more global memory 
	// resources).
	if(MySocket == INVALID_UDP_SOCKET)
		return;
	
	// Make certain the socket can be written to
	while(!UDPIsPutReady(MySocket));
	
	// 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('-');
	}

	// Send some other human readable information.
	UDPPutROMString((ROM BYTE*)"\r\nDHCP/Power event occurred");

	// Send the packet
	UDPFlush();
	
	// Close the socket so it can be used by other modules
	UDPClose(MySocket);
}
Ejemplo n.º 6
0
static void _TFTPSendROMFileName(TFTP_OPCODE opcode, ROM BYTE *fileName)
{
    BYTE c;

	// Select the proper UDP socket and wait until we can write to it
	while(!UDPIsPutReady(_tftpSocket));

    // Write opCode
    UDPPut(0);
    UDPPut(opcode);

    // write file name, including NULL.
    do
    {
        c = *fileName++;
        UDPPut(c);
    } while ( c != '\0' );

    // Write mode - always use octet or binay mode to transmit files.
    UDPPut('o');
    UDPPut('c');
    UDPPut('t');
    UDPPut('e');
    UDPPut('t');
    UDPPut(0);

    // Transmit it.
    UDPFlush();

    // Reset data block length.
    MutExVar.group2._tftpBlockLength.Val = 0;
}
Ejemplo n.º 7
0
static void _TFTPSendAck(WORD_VAL blockNumber)
{
    // Write opCode.
    UDPPut(0);
    UDPPut(TFTP_OPCODE_ACK);

    // Write block number for this ack.
    UDPPut(blockNumber.byte.MSB);
    UDPPut(blockNumber.byte.LSB);

    // Transmit it.
    UDPFlush();
}
Ejemplo n.º 8
0
static void NBNSPutName(BYTE *String)
{
	BYTE i, j;

	UDPPut(32);	// NetBIOS names are always 32 bytes long (16 decoded bytes)
	for(i = 0; i < 16u; i++)
	{
		j = *String++;
		UDPPut((j>>4) + 'A');
		UDPPut((j & 0x0F) + 'A');
	}
	
	UDPPut(0x00);
}
Ejemplo n.º 9
0
/*********************************************************************
 * Function:        static void NBNSPutName (UDP_SOCKET s, const char *String)
 *
 * PreCondition:    None
 *
 * Input:           String: The name to transmit
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Transmits the NetBIOS name across an open UDP
 *                  socket.
 *
 * Note:            None
 ********************************************************************/
static void NBNSPutName(UDP_SOCKET s, const char *String)
{
	uint8_t i, j;

	UDPPut(s, 32);	// NetBIOS names are always 32 bytes long (16 decoded bytes)
	for(i = 0; i < 16u; i++)
	{
		j = *String++;
		UDPPut(s, (j>>4) + 'A');
		UDPPut(s, (j & 0x0F) + 'A');
	}
	
	UDPPut(s, 0x00);
}
Ejemplo n.º 10
0
/*********************************************************************
 * Function:        void TFTPPut(BYTE c)
 *
 * PreCondition:    TFTPOpenFile() is called with TFTP_FILE_MODE_WRITE
 *                  and TFTPIsPutReady() = TRUE
 *
 * Input:           c       - Data byte that is to be written
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Puts given data byte into TFTP socket.
 *                  If end of data block is reached, it
 *                  transmits entire block.
 *
 * Note:            Use this function to write file to server.
 ********************************************************************/
void TFTPPut(BYTE c)
{
    // Put given byte directly to UDP
    UDPPut(c);

    // One more byte in data block.
    ++MutExVar.group2._tftpBlockLength.Val;

    // Check to see if data block is full.
    if ( MutExVar.group2._tftpBlockLength.byte.MSB == TFTP_BLOCK_SIZE_MSB )
    {
        // If it is, then transmit this block.
        UDPFlush();

        // Remember that current block is already flushed.
        _tftpFlags.bits.bIsFlushed = TRUE;

        // Prepare for next block.
        MutExVar.group2._tftpBlockLength.Val = 0;

        // Need to wait for ACK from server before putting
        // next block of data.
        _tftpState = SM_TFTP_WAIT_FOR_ACK;
    }
}
Ejemplo n.º 11
0
void sendToLocalListeners() {
	int i, len;
	char *b;

	/* Only transmit if at least one listener has registered */
	if (!listenerActive) {
		return;
	}
	
	if(s == INVALID_UDP_SOCKET) {
		s = UDPOpen(localPort, &remote, localPort);
	}
	if(s == INVALID_UDP_SOCKET) {
		return;
	}

	if (!UDPIsPutReady(s)) {
		return;
	}
	b = LMContent();
	len = strlen(b);
	for(i=0; i<len; ++i) {
		UDPPut(b[i]);
	}
	UDPFlush();
}
Ejemplo n.º 12
0
/**
 * Check LCD display every 50ms
 *
 * @return Set's bit 0 in returned byte if data added to UDP event port
 */
BYTE chkLCD(void) {
    BYTE ret = 0;
    BYTE i;
    BYTE key;

    //Empty all keypad buffers
    for (i=0; i<LCD2S_MAX_NUMBER; i++) {
        while (kpadHasKeys(i)) {
            key = kpadGetKey(i);    //Get next key

            //UDP Event port is active
            if ( ((activeEventPorts & EVT_PORT_UDP)!=0) && UDPIsPutReady(udpSocketEvt) ) {
                ret |= EVT_PORT_UDP; //Indicate that data was added to UDP event port

                //Tags for keypad data from LCD display 1 to 4 is "l34" to "l37"
                UDPPut('l');
                UDPPut('3');
                UDPPut('4' + i);
                UDPPut('=');
                UDPPut(key);
                UDPPut(';');
            }
        }
    }
    
    return ret;
}
Ejemplo n.º 13
0
/*****************************************************************************
  Function:
	static void DNSCopyRXNameToTX(void)

  Summary:
	Copies a DNS hostname, possibly including name compression, from the RX 
	packet to the TX packet (without name compression in TX case).
	
  Description:
	None

  Precondition:
	RX pointer is set to currently point to the DNS name to copy

  Parameters:
	None

  Returns:
  	None
  ***************************************************************************/
static void DNSCopyRXNameToTX(void)
{
	WORD w;
	BYTE i;
	BYTE len;

	while(1)
	{
		// Get first byte which will tell us if this is a 16-bit pointer or the 
		// length of the first of a series of labels
		if(!UDPGet(&i))
			return;
		
		// Check if this is a pointer, if so, get the reminaing 8 bits and seek to the pointer value
		if((i & 0xC0u) == 0xC0u)
		{
			((BYTE*)&w)[1] = i & 0x3F;
			UDPGet((BYTE*)&w);
			IPSetRxBuffer(sizeof(UDP_HEADER) + w);
			continue;
		}

		// Write the length byte
		len = i;
		UDPPut(len);
		
		// Exit if we've reached a zero length label
		if(len == 0u)
			return;
		
		// Copy all of the bytes in this label	
		while(len--)
		{
			UDPGet(&i);
			UDPPut(i);
		}
	}
}
Ejemplo n.º 14
0
/*****************************************************************************
  Function:
	static void DNSCopyRXNameToTX(UDP_SOCKET s, NET_CONFIG* pNet)

  Summary:
	Copies a DNS hostname, possibly including name compression, from the RX 
	packet to the TX packet (without name compression in TX case).
	
  Description:
	None

  Precondition:
	RX pointer is set to currently point to the DNS name to copy

  Parameters:
	None

  Returns:
  	None
  ***************************************************************************/
static void DNSCopyRXNameToTX(UDP_SOCKET s, NET_CONFIG* pNet)
{
	uint16_t w;
	uint8_t i;
	uint8_t len;

	while(1)
	{
		// Get first byte which will tell us if this is a 16-bit pointer or the 
		// length of the first of a series of labels
		if(!UDPGet(s, &i))
			return;
		
		// Check if this is a pointer, if so, get the reminaing 8 bits and seek to the pointer value
		if((i & 0xC0u) == 0xC0u)
		{
			((uint8_t*)&w)[1] = i & 0x3F;
			UDPGet(s, (uint8_t*)&w);
			IPSetRxBuffer(pNet, sizeof(UDP_HEADER) + w);
			continue;
		}

		// Write the length byte
		len = i;
		UDPPut(s, len);
		
		// Exit if we've reached a zero length label
		if(len == 0u)
			return;
		
		// Copy all of the bytes in this label	
		while(len--)
		{
			UDPGet(s, &i);
			UDPPut(s, i);
		}
	}
}
Ejemplo n.º 15
0
int8_t vscp_sendUDPEvent( PVSCPMSG pmsg )
{
    int i;

    if ( UDPIsPutReady( vscp_udp_transmitsocket ) ) {

        pmsg->crc = crcSlow( (unsigned char *)pmsg, sizeof( vscpMsg ) - 2  );

        UDPPut( pmsg->head );

        UDPPut( ( pmsg->vscp_class >> 8 ) & 0xff );
        UDPPut( pmsg->vscp_class & 0xff );

        UDPPut( ( pmsg->vscp_type >> 8 ) & 0xff );
        UDPPut( pmsg->vscp_type & 0xff );

        for ( i=0; i<16; i++ ) {
            UDPPut( vscp_getGUID( i ) );
        }

        UDPPut( ( pmsg->sizeData >> 8 ) & 0xff );
        UDPPut( pmsg->sizeData & 0xff );

        for ( i=0; i<pmsg->sizeData; i++ ) {
            UDPPut( pmsg->data[ i ] );
        }

        UDPPut( ( pmsg->crc >> 8 ) & 0xff );
        UDPPut( pmsg->crc & 0xff );

        UDPFlush();
        return TRUE;
    }

    return FALSE;
}
Ejemplo n.º 16
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
}
Ejemplo n.º 17
0
/*****************************************************************************
  Function:
	static void DHCPReplyToDiscovery(BOOTP_HEADER *Header)

  Summary:
	Replies to a DHCP Discover message.

  Description:
	This function replies to a DHCP Discover message by sending out a 
	DHCP Offer message.

  Precondition:
	None

  Parameters:
	Header - the BootP header this is in response to.

  Returns:
  	None
  ***************************************************************************/
static void DHCPReplyToDiscovery(BOOTP_HEADER *Header)
{
	BYTE i;

	// Set the correct socket to active and ensure that 
	// enough space is available to generate the DHCP response
	if(UDPIsPutReady(MySocket) < 300u)
		return;

	// Begin putting the BOOTP Header and DHCP options
	UDPPut(BOOT_REPLY);			// Message Type: 2 (BOOTP Reply)
	// Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
	UDPPutArray((BYTE*)&(Header->HardwareType), 7);
	UDPPut(0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPut(0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
	UDPPut(0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR));	// Lease IP address to give out
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPutArray((BYTE*)&(Header->ClientMAC), sizeof(MAC_ADDR));	// Client MAC address: Same as given by client
	for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)	// Remaining 10 bytes of client hardware address, server host name: Null string (not used)
		UDPPut(0x00);									// Boot filename: Null string (not used)
	UDPPut(0x63);				// Magic Cookie: 0x63538263
	UDPPut(0x82);				// Magic Cookie: 0x63538263
	UDPPut(0x53);				// Magic Cookie: 0x63538263
	UDPPut(0x63);				// Magic Cookie: 0x63538263
	
	// Options: DHCP Offer
	UDPPut(DHCP_MESSAGE_TYPE);	
	UDPPut(1);
	UDPPut(DHCP_OFFER_MESSAGE);

	// Option: Subnet Mask
	UDPPut(DHCP_SUBNET_MASK);
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR));

	// Option: Lease duration
	UDPPut(DHCP_IP_LEASE_TIME);
	UDPPut(4);
	UDPPut((DHCP_LEASE_DURATION>>24) & 0xFF);
	UDPPut((DHCP_LEASE_DURATION>>16) & 0xFF);
	UDPPut((DHCP_LEASE_DURATION>>8) & 0xFF);
	UDPPut((DHCP_LEASE_DURATION) & 0xFF);

	// Option: Server identifier
	UDPPut(DHCP_SERVER_IDENTIFIER);	
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

	// Option: Router/Gateway address
	UDPPut(DHCP_ROUTER);		
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

	// No more options, mark ending
	UDPPut(DHCP_END_OPTION);

	// Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
	while(UDPTxCount < 300u)
		UDPPut(0); 

	// Transmit the packet
	UDPFlush();
}
Ejemplo n.º 18
0
Archivo: DNS.c Proyecto: 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;
}
Ejemplo n.º 19
0
/*****************************************************************************
  Function:
	static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept)

  Summary:
	Replies to a DHCP Request message.

  Description:
	This function replies to a DHCP Request message by sending out a 
	DHCP Acknowledge message.

  Precondition:
	None

  Parameters:
	Header - the BootP header this is in response to.
	bAccept - whether or not we've accepted this request

  Returns:
  	None
  
  Internal:
	Needs to support more than one simultaneous lease in the future.
  ***************************************************************************/
static void DHCPReplyToRequest(BOOTP_HEADER *Header, BOOL bAccept)
{
	BYTE i;

	// Set the correct socket to active and ensure that 
	// enough space is available to generate the DHCP response
	if(UDPIsPutReady(MySocket) < 300u)
		return;

	// Search through all remaining options and look for the Requested IP address field
	// Obtain options
	while(UDPIsGetReady(MySocket))
	{
		BYTE Option, Len;
		DWORD dw;

		// Get option type
		if(!UDPGet(&Option))
			break;
		if(Option == DHCP_END_OPTION)
			break;

		// Get option length
		UDPGet(&Len);

		// Process option
		if((Option == DHCP_PARAM_REQUEST_IP_ADDRESS) && (Len == 4u))
		{
			// Get the requested IP address and see if it is the one we have on offer.  If not, we should send back a NAK, but since there could be some other DHCP server offering this address, we'll just silently ignore this request.
			UDPGetArray((BYTE*)&dw, 4);
			Len -= 4;
			if(dw != DHCPNextLease.Val)
			{
				bAccept = FALSE;
			}
			break;
		}

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


#if defined(STACK_USE_DHCP_CLIENT)
	// Someone is using our DHCP server, start using a static 
	// IP address and update the bind count so it displays on 
	// the LCD
	AppConfig.Flags.bInConfigMode = FALSE;
	DHCPBindCount++;
#endif

	// Begin putting the BOOTP Header and DHCP options
	UDPPut(BOOT_REPLY);			// Message Type: 2 (BOOTP Reply)
	// Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
	UDPPutArray((BYTE*)&(Header->HardwareType), 7);
	UDPPut(0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPut(0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPutArray((BYTE*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
	UDPPutArray((BYTE*)&(Header->ClientIP), sizeof(IP_ADDR));// Your (client) IP Address:
	UDPPutArray((BYTE*)&DHCPNextLease, sizeof(IP_ADDR));	// Lease IP address to give out
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPutArray((BYTE*)&(Header->ClientMAC), sizeof(MAC_ADDR));	// Client MAC address: Same as given by client
	for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)	// Remaining 10 bytes of client hardware address, server host name: Null string (not used)
		UDPPut(0x00);									// Boot filename: Null string (not used)
	UDPPut(0x63);				// Magic Cookie: 0x63538263
	UDPPut(0x82);				// Magic Cookie: 0x63538263
	UDPPut(0x53);				// Magic Cookie: 0x63538263
	UDPPut(0x63);				// Magic Cookie: 0x63538263
	
	// Options: DHCP lease ACKnowledge
	if(bAccept)
	{
		UDPPut(DHCP_OPTION_ACK_MESSAGE);	
		UDPPut(1);
		UDPPut(DHCP_ACK_MESSAGE);
	}
	else	// Send a NACK
	{
		UDPPut(DHCP_OPTION_ACK_MESSAGE);	
		UDPPut(1);
		UDPPut(DHCP_NAK_MESSAGE);
	}

	// Option: Lease duration
	UDPPut(DHCP_IP_LEASE_TIME);
	UDPPut(4);
	UDPPut((DHCP_LEASE_DURATION>>24) & 0xFF);
	UDPPut((DHCP_LEASE_DURATION>>16) & 0xFF);
	UDPPut((DHCP_LEASE_DURATION>>8) & 0xFF);
	UDPPut((DHCP_LEASE_DURATION) & 0xFF);

	// Option: Server identifier
	UDPPut(DHCP_SERVER_IDENTIFIER);	
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

	// Option: Subnet Mask
	UDPPut(DHCP_SUBNET_MASK);
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyMask, sizeof(IP_ADDR));

	// Option: Router/Gateway address
	UDPPut(DHCP_ROUTER);		
	UDPPut(sizeof(IP_ADDR));
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr, sizeof(IP_ADDR));

	// No more options, mark ending
	UDPPut(DHCP_END_OPTION);

	// Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
	while(UDPTxCount < 300u)
		UDPPut(0); 

	// Transmit the packet
	UDPFlush();
}
Ejemplo n.º 20
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;
	}
}
Ejemplo n.º 21
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;
	}	

}
Ejemplo n.º 22
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;
}
Ejemplo n.º 23
0
/*
 * Main entry point.
 */
void main(void)
{
    TICK8  tsecWait = 0;           //General purpose wait timer
    TICK16 tsecMsgSent = 0;        //Time last message was sent
    TICK16 tsecBlinker = 0;  
    BYTE main_state;				// what are the inputs
	BYTE main_inputs;				// who has the transmit
    char c;
    NODE_INFO udpServerNode;

    //Initialize AppConfig structure
    appcfgInit();
    
    //Initialize any application specific hardware.
    InitializeBoard();

    //Initialize all stack related components.
    TickInit();

    //Initialize the TCP/IP stack
    StackInit();


    /////////////////////////////////////////////////
    //Initialize UDP socket

    //Initialize remote IP and address with 10.1.0.101. The MAC address is
    //is not intialized yet, but after we receive an ARP responce.
    //Configure for local port 54123 and remote port 54124.
    udpServerNode.IPAddr.v[0] = 255;
    udpServerNode.IPAddr.v[1] = 255;
    udpServerNode.IPAddr.v[2] = 255;
    udpServerNode.IPAddr.v[3] = 255;
    udpSocketUser = UDPOpen(54123, &udpServerNode, 54124);
	//udpSocketUser = UDPOpen(54123, NULL, 54124);
	smUdp = SM_UDP_RESOLVED;
    
    //An error occurred during the UDPOpen() function
    if (udpSocketUser == INVALID_UDP_SOCKET) {
        //Add user code here to take action if required!
    }

    /*
     * Once all items are initialized, go into infinite loop and let stack items execute
     * their tasks. If the application needs to perform its own task, it should be done at
     * the end of while 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 broken down into smaller pieces so that other tasks can have CPU time.
     */
    while(1)
    {
	    ServiceBoard();
		if (TickGetSecDiff(tsecBlinker) >= (TICK16)1) 
		{
			tsecBlinker = TickGetSec();     //Update with current time
			//Toggle system LED 
#ifdef BLINKTIME
            TRISB_RB6 = 0;
            LATB6 ^= 1;
#endif
		}
        switch (smUdp) {
        case SM_UDP_SEND_ARP:
            if (ARPIsTxReady()) {
                tsecWait = TickGet8bitSec();   //Remember when we sent last request
                
                //Send ARP request for given IP address
                ARPResolve(&udpServerNode.IPAddr);
                
                smUdp = SM_UDP_WAIT_RESOLVE;
            }
            break;
        case SM_UDP_WAIT_RESOLVE:
            //The IP address has been resolved, we now have the MAC address of the
            //node at 10.1.0.101
            if (ARPIsResolved(&udpServerNode.IPAddr, &udpServerNode.MACAddr)) {
                smUdp = SM_UDP_RESOLVED;
            }
            //If not resolved after 2 seconds, send next request
            else {
                if (TickGetDiff8bitSec(tsecWait) >= (TICK8)2) {
                    smUdp = SM_UDP_SEND_ARP;
                }
            }
            break;
        case SM_UDP_RESOLVED:
            if ( 1 || !PORTB_RB0) {
                //Send a message every second for as long as PIC port pin B0 is = 0
                if ((TickGetSecDiff(tsecMsgSent) >= (TICK16)1) ||
					((main_state != old_state) || (main_inputs != old_inputs))) {
                    //Checks if there is a transmit buffer ready for accepting data, and that the given socket
                    //is valid (not equal to INVALID_UDP_SOCKET for example)
                    if (UDPIsPutReady(udpSocketUser)) {
                        tsecMsgSent = TickGetSec();     //Update with current time

                        //Send a UDP Datagram with one byte only indicating the status We are only interrested in the first byte of the message.
                        UDPPut('H');UDPPut('E');UDPPut('L');UDPPut('L');UDPPut('O');
						UDPPut(old_state);
						UDPPut(old_inputs);
						main_state = old_state;
						main_inputs = old_inputs;
                        //Send contents of transmit buffer, and free buffer
                        UDPFlush();
                       	
						//Toggle system LED each time a message is sent
                    	TRISB_RB6 = 0;
                    	LATB6 ^= 1; 
                    }

                    
                }
            }
            break;
        }

        //This task performs normal stack task including checking for incoming packet,
        //type of packet and calling appropriate stack entity to process it.
        StackTask();

        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        // ADD USER CODE HERE
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    }
}
Ejemplo n.º 24
0
/*****************************************************************************
  Function:
	static void DHCPReplyToRequest(BOOTP_HEADER *Header, bool bAccept, int netIx)

  Summary:
	Replies to a DHCP Request message.

  Description:
	This function replies to a DHCP Request message by sending out a 
	DHCP Acknowledge message.

  Precondition:
	None

  Parameters:
	Header - the BootP header this is in response to.
	bAccept - whether or not we've accepted this request
    netIx   - interface index

  Returns:
  	None
  
  Internal:
	Needs to support more than one simultaneous lease in the future.
  ***************************************************************************/
static void DHCPReplyToRequest(BOOTP_HEADER *Header, bool bAccept, int netIx)
{
	uint8_t         i;
    NET_CONFIG*     pConfig;
    UDP_SOCKET      s;
    
	// Set the correct socket to active and ensure that 
	// enough space is available to generate the DHCP response
    s = MySocket[netIx];
    if(UDPIsPutReady(s) < 300u)
		return;
    
    pConfig = UDPSocketGetNet(s);

	// Search through all remaining options and look for the Requested IP address field
	// Obtain options
	while(UDPIsGetReady(s))
	{
		uint8_t Option, Len;
		uint32_t dw;

		// Get option type
		if(!UDPGet(s, &Option))
			break;
		if(Option == DHCP_END_OPTION)
			break;

		// Get option length
		UDPGet(s, &Len);

		// Process option
		if((Option == DHCP_PARAM_REQUEST_IP_ADDRESS) && (Len == 4u))
		{
			// Get the requested IP address and see if it is the one we have on offer.  If not, we should send back a NAK, but since there could be some other DHCP server offering this address, we'll just silently ignore this request.
			UDPGetArray(s, (uint8_t*)&dw, 4);
			Len -= 4;
			if(dw != DHCPNextLease[netIx].Val)
			{
				bAccept = false;
			}
			break;
		}

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

	// Begin putting the BOOTP Header and DHCP options
	UDPPut(s, BOOT_REPLY);			// Message Type: 2 (BOOTP Reply)
	// Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
	UDPPutArray(s, (uint8_t*)&(Header->HardwareType), 7);
	UDPPut(s, 0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPut(s, 0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPutArray(s, (uint8_t*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
	UDPPutArray(s, (uint8_t*)&(Header->ClientIP), sizeof(IP_ADDR));// Your (client) IP Address:
	UDPPutArray(s, (uint8_t*)&DHCPNextLease[netIx], sizeof(IP_ADDR));	// Lease IP address to give out
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPutArray(s, (uint8_t*)&(Header->ClientMAC), sizeof(MAC_ADDR));	// Client MAC address: Same as given by client
	for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)	// Remaining 10 bytes of client hardware address, server host name: Null string (not used)
		UDPPut(s, 0x00);									// Boot filename: Null string (not used)
	UDPPut(s, 0x63);				// Magic Cookie: 0x63538263
	UDPPut(s, 0x82);				// Magic Cookie: 0x63538263
	UDPPut(s, 0x53);				// Magic Cookie: 0x63538263
	UDPPut(s, 0x63);				// Magic Cookie: 0x63538263
	
	// Options: DHCP lease ACKnowledge
	if(bAccept)
	{
		UDPPut(s, DHCP_OPTION_ACK_MESSAGE);	
		UDPPut(s, 1);
		UDPPut(s, DHCP_ACK_MESSAGE);
	}
	else	// Send a NACK
	{
		UDPPut(s, DHCP_OPTION_ACK_MESSAGE);	
		UDPPut(s, 1);
		UDPPut(s, DHCP_NAK_MESSAGE);
	}

	// Option: Lease duration
	UDPPut(s, DHCP_IP_LEASE_TIME);
	UDPPut(s, 4);
	UDPPut(s, (DHCP_LEASE_DURATION>>24) & 0xFF);
	UDPPut(s, (DHCP_LEASE_DURATION>>16) & 0xFF);
	UDPPut(s, (DHCP_LEASE_DURATION>>8) & 0xFF);
	UDPPut(s, (DHCP_LEASE_DURATION) & 0xFF);

	// Option: Server identifier
	UDPPut(s, DHCP_SERVER_IDENTIFIER);	
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyIPAddr, sizeof(IP_ADDR));

	// Option: Subnet Mask
	UDPPut(s, DHCP_SUBNET_MASK);
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyMask, sizeof(IP_ADDR));

	// Option: Router/Gateway address
	UDPPut(s, DHCP_ROUTER);		
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyIPAddr, sizeof(IP_ADDR));

	// Option: DNS server address
	UDPPut(s, DHCP_DNS);
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyIPAddr, sizeof(IP_ADDR));

	// No more options, mark ending
	UDPPut(s, DHCP_END_OPTION);

	// Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
	while(UDPGetTxCount(s) < 300u)
		UDPPut(s, 0); 

	// Force remote destination address to be the broadcast address, regardless 
	// of what the node's source IP address was (to ensure we don't try to 
	// unicast to 0.0.0.0).
	memset((void*)&UDPSocketDcpt[s].remoteNode, 0xFF, sizeof(NODE_INFO));

	// Transmit the packet
	UDPFlush(s);
}
Ejemplo n.º 25
0
/*****************************************************************************
  Function:
	static void DHCPReplyToDiscovery(BOOTP_HEADER *Header, int netIx)

  Summary:
	Replies to a DHCP Discover message.

  Description:
	This function replies to a DHCP Discover message by sending out a 
	DHCP Offer message.

  Precondition:
	None

  Parameters:
	Header - the BootP header this is in response to.
    netIx   - interface index

  Returns:
  	None
  ***************************************************************************/
static void DHCPReplyToDiscovery(BOOTP_HEADER *Header, int netIx)
{
	uint8_t         i;
    NET_CONFIG*     pConfig;
    UDP_SOCKET      s;
    
	// Set the correct socket to active and ensure that 
	// enough space is available to generate the DHCP response
    s = MySocket[netIx];
    if(UDPIsPutReady(s) < 300u)
		return;

    pConfig = UDPSocketGetNet(s);

	// Begin putting the BOOTP Header and DHCP options
	UDPPut(s, BOOT_REPLY);			// Message Type: 2 (BOOTP Reply)
	// Reply with the same Hardware Type, Hardware Address Length, Hops, and Transaction ID fields
	UDPPutArray(s, (uint8_t*)&(Header->HardwareType), 7);
	UDPPut(s, 0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPut(s, 0x00);				// Seconds Elapsed: 0 (Not used)
	UDPPutArray(s, (uint8_t*)&(Header->BootpFlags), sizeof(Header->BootpFlags));
	UDPPut(s, 0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(s, 0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(s, 0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPut(s, 0x00);				// Your (client) IP Address: 0.0.0.0 (none yet assigned)
	UDPPutArray(s, (uint8_t*)&DHCPNextLease[netIx], sizeof(IP_ADDR));	// Lease IP address to give out
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Next Server IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPut(s, 0x00);				// Relay Agent IP Address: 0.0.0.0 (not used)
	UDPPutArray(s, (uint8_t*)&(Header->ClientMAC), sizeof(MAC_ADDR));	// Client MAC address: Same as given by client
	for(i = 0; i < 64+128+(16-sizeof(MAC_ADDR)); i++)	// Remaining 10 bytes of client hardware address, server host name: Null string (not used)
		UDPPut(s, 0x00);									// Boot filename: Null string (not used)
	UDPPut(s, 0x63);				// Magic Cookie: 0x63538263
	UDPPut(s, 0x82);				// Magic Cookie: 0x63538263
	UDPPut(s, 0x53);				// Magic Cookie: 0x63538263
	UDPPut(s, 0x63);				// Magic Cookie: 0x63538263
	
	// Options: DHCP Offer
	UDPPut(s, DHCP_MESSAGE_TYPE);	
	UDPPut(s, 1);
	UDPPut(s, DHCP_OFFER_MESSAGE);

	// Option: Subnet Mask
	UDPPut(s, DHCP_SUBNET_MASK);
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyMask, sizeof(IP_ADDR));

	// Option: Lease duration
	UDPPut(s, DHCP_IP_LEASE_TIME);
	UDPPut(s, 4);
	UDPPut(s, (DHCP_LEASE_DURATION>>24) & 0xFF);
	UDPPut(s, (DHCP_LEASE_DURATION>>16) & 0xFF);
	UDPPut(s, (DHCP_LEASE_DURATION>>8) & 0xFF);
	UDPPut(s, (DHCP_LEASE_DURATION) & 0xFF);

	// Option: Server identifier
	UDPPut(s, DHCP_SERVER_IDENTIFIER);	
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyIPAddr, sizeof(IP_ADDR));

	// Option: Router/Gateway address
	UDPPut(s, DHCP_ROUTER);		
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyIPAddr, sizeof(IP_ADDR));

	// Option: DNS server address
	UDPPut(s, DHCP_DNS);
	UDPPut(s, sizeof(IP_ADDR));
	UDPPutArray(s, (uint8_t*)&pConfig->MyIPAddr, sizeof(IP_ADDR));

	// No more options, mark ending
	UDPPut(s, DHCP_END_OPTION);

	// Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
	while(UDPGetTxCount(s) < 300u)
		UDPPut(s, 0); 

	// Force remote destination address to be the broadcast address, regardless 
	// of what the node's source IP address was (to ensure we don't try to 
	// unicast to 0.0.0.0).
	memset((void*)&UDPSocketDcpt[s].remoteNode, 0xFF, sizeof(NODE_INFO));

	// Transmit the packet
	UDPFlush(s);
}
Ejemplo n.º 26
0
/*********************************************************************
 * Function:        void DNSServerTask(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Sends dummy responses that point to ourself for DNS requests
 *
 * Note:            None
 ********************************************************************/
void DNSServerTask(void)
{
	static UDP_SOCKET	MySocket = INVALID_UDP_SOCKET;
	struct
	{
		WORD wTransactionID;
		WORD wFlags;
		WORD wQuestions;
		WORD wAnswerRRs;
		WORD wAuthorityRRs;
		WORD wAdditionalRRs;
	} DNSHeader;


	// Create a socket to listen on if this is the first time calling this function
	if(MySocket == INVALID_UDP_SOCKET)
	{
		//MySocket = UDPOpen(DNS_PORT, NULL, 0);
		
		MySocket = UDPOpenEx(0,UDP_OPEN_SERVER,DNS_PORT,0);
		return;
	}

	// See if a DNS query packet has arrived
	if(UDPIsGetReady(MySocket) < sizeof(DNSHeader))
		return;

	// Read DNS header
	UDPGetArray((BYTE*)&DNSHeader, sizeof(DNSHeader));

	// Ignore this packet if it isn't a query
	if((DNSHeader.wFlags & 0x8000) == 0x8000u)
		return;

	// Ignore this packet if there are no questions in it
	if(DNSHeader.wQuestions == 0u)
		return;

	// Block until we can transmit a DNS response packet
	while(!UDPIsPutReady(MySocket));

	// Write DNS response packet
	UDPPutArray((BYTE*)&DNSHeader.wTransactionID, 2);	// 2 byte Transaction ID
	if(DNSHeader.wFlags & 0x0100)
		UDPPut(0x81);	// Message is a response with recursion desired
	else
		UDPPut(0x80);	// Message is a response without recursion desired flag set
	UDPPut(0x80);	// Recursion available
	UDPPut(0x00);	// 0x0000 Questions
	UDPPut(0x00);
	UDPPut(0x00);	// 0x0001 Answers RRs
	UDPPut(0x01);
	UDPPut(0x00);	// 0x0000 Authority RRs
	UDPPut(0x00);
	UDPPut(0x00);	// 0x0000 Additional RRs
	UDPPut(0x00);
	DNSCopyRXNameToTX();	// Copy hostname of first question over to TX packet
	UDPPut(0x00);	// Type A Host address
	UDPPut(0x01);
	UDPPut(0x00);	// Class INternet
	UDPPut(0x01);
	UDPPut(0x00);	// Time to Live 10 seconds
	UDPPut(0x00);
	UDPPut(0x00);
	UDPPut(0x0A);
	UDPPut(0x00);	// Data Length 4 bytes
	UDPPut(0x04);
	UDPPutArray((BYTE*)&AppConfig.MyIPAddr.Val, 4);	// Our IP address
	#warning tim had added extra code here
	UDPFlush();
}
Ejemplo n.º 27
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;
}
Ejemplo n.º 28
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;
}
Ejemplo n.º 29
0
void ANNOUNCE_Send(void)
{
    UDP_SOCKET  announceSocket;
    int         netIx;
    uint16_t    dataLen;
    uint16_t    minimumDataLen;
    uint16_t    txLen;
    bool truncated;
    NET_CONFIG * pNetIf;
    ANNOUNCE_LIST_NODE *  node = (ANNOUNCE_LIST_NODE *)announceEvents.head;
    ANNOUNCE_FIELD_PAYLOAD payloadType;
    uint16_t terminatorLen = strlen ((const char *)announceFieldTerminator);

#if defined (TCPIP_STACK_USE_IPV6)
    IPV6_ADDR_STRUCT * addressPointer;
#endif

    while (node != NULL)
    {    
        pNetIf = (NET_CONFIG *)node->handle;

        netIx = TCPIP_STACK_NetIx (pNetIf);

        truncated = false;

        dataLen = ((terminatorLen + 1) * 4) + sizeof (IPV4_ADDR) + sizeof (MAC_ADDR);

        dataLen += strlen(TCPIP_HOSTS_CONFIGURATION[netIx].interface);
        dataLen += strlen((char *)pNetIf->NetBIOSName);
    
        minimumDataLen = dataLen + 1 + terminatorLen;
    
        if(!MACIsLinked(_TCPIPStackNetToMac(pNetIf)))  // Check for link before blindly opening and transmitting (similar to DHCP case)
        {
            return;
        }
    
        announceSocket = UDPOpenClient(IP_ADDRESS_TYPE_IPV4, ANNOUNCE_PORT, 0);
    
        if (announceSocket == INVALID_UDP_SOCKET)
        {
            return;
        }
    
        UDPSocketSetNet (announceSocket, pNetIf);
    
    #if defined (TCPIP_STACK_USE_IPV6)
        addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6UnicastAddresses.head;
    
        while(addressPointer != NULL)
        {
            dataLen += sizeof (IPV6_ADDR) + 1 + terminatorLen;
            addressPointer = addressPointer->next;
        }
    
        addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6MulticastAddresses.head;
    
        while(addressPointer != NULL)
        {
            dataLen += sizeof (IPV6_ADDR) + 1 + terminatorLen;
            addressPointer = addressPointer->next;
        }
    #endif
    
        if (dataLen > ANNOUNCE_MAX_PAYLOAD)
        {
            dataLen = ANNOUNCE_MAX_PAYLOAD;
        }
    
        if ((txLen = UDPIsTxPutReady(announceSocket, dataLen)) < dataLen)
        {
            truncated = true;
            if ((txLen = UDPIsTxPutReady(announceSocket, minimumDataLen)) < minimumDataLen)
            {
                UDPClose (announceSocket);
                return;
            }
        }
    
        // Put Mac Address
        payloadType = ANNOUNCE_FIELD_MAC_ADDR;
        UDPPut (announceSocket, payloadType);
        UDPPutArray(announceSocket, (const uint8_t *)&pNetIf->MyMACAddr, sizeof (MAC_ADDR));
        UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);

        if (truncated)
        {
            payloadType = ANNOUNCE_FIELD_TRUNCATED;
            UDPPut (announceSocket, payloadType);
            UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);
        }

        // Put Mac Type
        payloadType = ANNOUNCE_FIELD_MAC_TYPE;
        UDPPut (announceSocket, payloadType);
        UDPPutArray(announceSocket, (const uint8_t *)TCPIP_HOSTS_CONFIGURATION[netIx].interface, strlen ((const char *)TCPIP_HOSTS_CONFIGURATION[netIx].interface));
        UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);

        // Put Host Name
        payloadType = ANNOUNCE_FIELD_HOST_NAME;
        UDPPut (announceSocket, payloadType);
        UDPPutArray(announceSocket, (const uint8_t *)&pNetIf->NetBIOSName, strlen((char*)pNetIf->NetBIOSName));
        UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);

        // Put IPv4 Address
        payloadType = ANNOUNCE_FIELD_IPV4_ADDRESS;
        UDPPut (announceSocket, payloadType);
        UDPPutArray(announceSocket, (const uint8_t *)&pNetIf->MyIPAddr, sizeof (IP_ADDR));
        UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);
    
#if defined (TCPIP_STACK_USE_IPV6)
    
        // Put IPv6 unicast addresses
        minimumDataLen = sizeof (IPV6_ADDR) + 1 + terminatorLen;
    
        addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6UnicastAddresses.head;
    
        payloadType = ANNOUNCE_FIELD_IPV6_UNICAST;

        while(addressPointer != NULL && (UDPIsTxPutReady(announceSocket, minimumDataLen) >= minimumDataLen))
        {
            UDPPut (announceSocket, payloadType);
            UDPPutArray(announceSocket, (const uint8_t *)&addressPointer->address, sizeof (IPV6_ADDR));
            UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);
            addressPointer = addressPointer->next;
        }
    
        // Put IPv6 multicast listeners    
        addressPointer = (IPV6_ADDR_STRUCT *)ipv6Config[netIx].listIpv6MulticastAddresses.head;
    
        payloadType = ANNOUNCE_FIELD_IPV6_MULTICAST;

        while(addressPointer != NULL && (UDPIsTxPutReady(announceSocket, minimumDataLen) >= minimumDataLen))
        {
            UDPPut (announceSocket, payloadType);
            UDPPutArray(announceSocket, (const uint8_t *)&addressPointer->address, sizeof (IPV6_ADDR));
            UDPPutArray (announceSocket, announceFieldTerminator, terminatorLen);
            addressPointer = addressPointer->next;
        }
#endif
    
        UDPFlush (announceSocket);
    
        UDPClose (announceSocket);

        SingleListRemoveHead(&announceEvents);

        TCPIP_HEAP_Free (announceMemH, node);

        node = (ANNOUNCE_LIST_NODE *)announceEvents.head;

        if (node == NULL)
        {
            announceEventPending = false;
        }
    }
}
Ejemplo n.º 30
0
/*****************************************************************************
  Function:
	static void _DHCPSend(BYTE messageType, BOOL bRenewing)

  Description:
	Sends a DHCP message.

  Precondition:
	UDP is ready to write a DHCP packet.

  Parameters:
	messageType - One of the DHCP_TYPE constants
	bRenewing - Whether or not this is a renewal request

  Returns:
  	None
  ***************************************************************************/
static void _DHCPSend(BYTE messageType, BOOL bRenewing)
{
    BYTE i;
	IP_ADDR	MyIP;


    UDPPut(BOOT_REQUEST);                       // op
    UDPPut(BOOT_HW_TYPE);                       // htype
    UDPPut(BOOT_LEN_OF_HW_TYPE);                // hlen
    UDPPut(0);                                  // hops
    UDPPut(0x12);                               // xid[0]
    UDPPut(0x23);                               // xid[1]
    UDPPut(0x34);                               // xid[2]
    UDPPut(0x56);                               // xid[3]
    UDPPut(0);                                  // secs[0]
    UDPPut(0);                                  // secs[1]
    UDPPut(0x80);                               // flags[0] with BF set
    UDPPut(0);                                  // flags[1]

    // If this is DHCP REQUEST message, use previously allocated IP address.
    if((messageType == DHCP_REQUEST_MESSAGE) && bRenewing)
    {
		UDPPutArray((BYTE*)&tempIPAddress, sizeof(tempIPAddress));
    }
    else
    {
        UDPPut(0x00);
        UDPPut(0x00);
        UDPPut(0x00);
        UDPPut(0x00);
    }

    // Set yiaddr, siaddr, giaddr as zeros,
    for ( i = 0; i < 12u; i++ )
        UDPPut(0x00);

    // Load chaddr - Client hardware address.
	UDPPutArray((BYTE*)&AppConfig.MyMACAddr, sizeof(AppConfig.MyMACAddr));

    // Set chaddr[6..15], sname and file as zeros.
    for ( i = 0; i < 202u; i++ )
        UDPPut(0);

    // Load magic cookie as per RFC 1533.
    UDPPut(99);
    UDPPut(130);
    UDPPut(83);
    UDPPut(99);

    // Load message type.
    UDPPut(DHCP_MESSAGE_TYPE);
    UDPPut(DHCP_MESSAGE_TYPE_LEN);
    UDPPut(messageType);

	if(messageType == DHCP_DISCOVER_MESSAGE)
	{
		// Reset offered flag so we know to act upon the next valid offer
		DHCPFlags.bits.bOfferReceived = FALSE;
	}


    if((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing)
    {
         // DHCP REQUEST message must include server identifier the first time
         // to identify the server we are talking to.
         // _DHCPReceive() would populate "serverID" when it
         // receives DHCP OFFER message. We will simply use that
         // when we are replying to server.
         // If this is a renwal request, we must not include server id.
         UDPPut(DHCP_SERVER_IDENTIFIER);
         UDPPut(DHCP_SERVER_IDENTIFIER_LEN);
         UDPPut(DHCPServerID.v[3]);
         UDPPut(DHCPServerID.v[2]);
         UDPPut(DHCPServerID.v[1]);
         UDPPut(DHCPServerID.v[0]);
     }

    // Load our interested parameters
    // This is hardcoded list.  If any new parameters are desired,
    // new lines must be added here.
    UDPPut(DHCP_PARAM_REQUEST_LIST);
    UDPPut(DHCP_PARAM_REQUEST_LIST_LEN);
    UDPPut(DHCP_SUBNET_MASK);
    UDPPut(DHCP_ROUTER);
	UDPPut(DHCP_DNS);
	UDPPut(DHCP_HOST_NAME);

     // Add requested IP address to DHCP Request Message
    if( ((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing) || 
    	((messageType == DHCP_DISCOVER_MESSAGE) && tempIPAddress.Val))
    {
        UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS);
        UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
		UDPPutArray((BYTE*)&tempIPAddress, DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
    }

    // Add any new paramter request here.

    // End of Options.
    UDPPut(DHCP_END_OPTION);

	// Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
	while(UDPTxCount < 300u)
		UDPPut(0); 

	// Make sure we advirtise a 0.0.0.0 IP address so all DHCP servers will respond.  If we have a static IP outside the DHCP server's scope, it may simply ignore discover messages.
	MyIP.Val = AppConfig.MyIPAddr.Val;
	if(!bRenewing)
		AppConfig.MyIPAddr.Val = 0x00000000;
    UDPFlush();
	AppConfig.MyIPAddr.Val = MyIP.Val;
	
}