diff --git a/source/FreeRTOS_DNS_Parser.c b/source/FreeRTOS_DNS_Parser.c index a1a3f2038..6f6c0443a 100644 --- a/source/FreeRTOS_DNS_Parser.c +++ b/source/FreeRTOS_DNS_Parser.c @@ -545,11 +545,22 @@ if( ( pxNetworkBuffer != NULL ) ) { pxAnswer = ( ( LLMNRAnswer_t * ) xSet.pucByte ); + /* We leave 'usIdentifier' and 'usQuestions' untouched */ - vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_RESPONSE ); /* Set the response flag */ - vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */ - vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */ - vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */ + if( xSet.usPortNumber == ipMDNS_PORT ) + { + /* Follow RFC6762 to set QR bit (section 18.2) and authoritative answer (AA) bit (section 18.4). */ + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usFlags, dnsMDNS_FLAGS_IS_RESPONSE ); + } + else + { + /* Follow RFC4795 to set QR bit (section 2.1.1) */ + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_RESPONSE ); + } + + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */ + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */ + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */ pxAnswer->ucNameCode = dnsNAME_IS_OFFSET; pxAnswer->ucNameOffset = ( uint8_t ) ( xSet.pcRequestedName - ( char * ) pucNewBuffer ); diff --git a/source/include/FreeRTOS_DNS_Globals.h b/source/include/FreeRTOS_DNS_Globals.h index 0de266e6c..698b5f4c5 100644 --- a/source/include/FreeRTOS_DNS_Globals.h +++ b/source/include/FreeRTOS_DNS_Globals.h @@ -109,12 +109,14 @@ #define ipLLMNR_IP_ADDR 0xFC0000E0UL #endif /* ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN */ - #define ipMDNS_TIME_TO_LIVE 255U - - #define ipLLMNR_PORT 5355U /* Standard LLMNR port. */ - #define ipDNS_PORT 53U /* Standard DNS port. */ - #define ipNBNS_PORT 137U /* NetBIOS Name Service. */ - #define ipNBDGM_PORT 138U /* Datagram Service, not included. */ +/* MDNS constants. */ + #define ipMDNS_TIME_TO_LIVE 255U + #define dnsMDNS_FLAGS_IS_RESPONSE 0x8400U /**< MDNS flag value for response. */ + + #define ipLLMNR_PORT 5355U /* Standard LLMNR port. */ + #define ipDNS_PORT 53U /* Standard DNS port. */ + #define ipNBNS_PORT 137U /* NetBIOS Name Service. */ + #define ipNBDGM_PORT 138U /* Datagram Service, not included. */ /** @brief freertos_addrinfo is the equivalent of 'struct addrinfo'. */ struct freertos_addrinfo diff --git a/test/unit-test/FreeRTOS_DNS_Parser/FreeRTOS_DNS_Parser_utest.c b/test/unit-test/FreeRTOS_DNS_Parser/FreeRTOS_DNS_Parser_utest.c index cee6d148a..589402af0 100644 --- a/test/unit-test/FreeRTOS_DNS_Parser/FreeRTOS_DNS_Parser_utest.c +++ b/test/unit-test/FreeRTOS_DNS_Parser/FreeRTOS_DNS_Parser_utest.c @@ -1776,7 +1776,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_xBufferAllocFixedsize( void ) uint8_t * pucUDPPayloadBuffer = udp_buffer + prvALIGNED_UDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; xBufferAllocFixedSize = pdTRUE; uint8_t * nullAddress = NULL; @@ -1854,7 +1854,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply( void ) uint8_t * pucUDPPayloadBuffer = udp_buffer + prvALIGNED_UDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; NetworkEndPoint_t xEndPoint = { 0 }; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -1927,7 +1927,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply2( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv6; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; NetworkEndPoint_t xEndPoint = { 0 }; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2000,7 +2000,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply3( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4 - 1; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; NetworkEndPoint_t xEndPoint = { 0 }; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2074,7 +2074,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_diffUsType( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; NetworkEndPoint_t xEndPoint = { 0 }; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2151,7 +2151,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_NullNetworkBuffer( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; NetworkEndPoint_t xEndPoint = { 0 }; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2228,7 +2228,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply4( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2299,7 +2299,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply5( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2371,7 +2371,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_query_hook_false( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; struct freertos_addrinfo * pxAddressInfo; struct xNetworkEndPoint xEndPoint = { 0 }; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; memset( pucUDPPayloadBuffer, 0x0, 250 ); size_t uxBufferLength = 250; @@ -2443,7 +2443,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_null_new_netbuffer( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; NetworkEndPoint_t xEndPoint = { 0 }; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2517,7 +2517,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_null_new_netbuffer2( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; NetworkEndPoint_t xEndPoint = { 0 }; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2591,7 +2591,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_valid_new_netbuffer( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; NetworkEndPoint_t xEndPoint = { 0 }; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2683,7 +2683,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_valid_new_netbuffer2( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; NetworkEndPoint_t xEndPoint = { 0 }; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2775,7 +2775,7 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_valid_new_netbuffer3( void ) uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; size_t uxBufferLength = 250; struct freertos_addrinfo * pxAddressInfo; - uint16_t usPort; + uint16_t usPort = ipLLMNR_PORT; NetworkEndPoint_t xEndPoint = { 0 }; memset( pucUDPPayloadBuffer, 0x00, uxBufferLength ); @@ -2855,6 +2855,89 @@ void test_DNS_ParseDNSReply_answer_lmmnr_reply_valid_new_netbuffer3( void ) ASSERT_DNS_QUERY_HOOK_CALLED(); } +/** + * @brief ensures that the ip set in Setup is passed to the network with + * vReturnEthernetFrame + */ +void test_DNS_ParseDNSReply_prepare_mdns_answer( void ) +{ + uint32_t ret; + uint8_t udp_buffer[ 250 + ipUDP_PAYLOAD_OFFSET_IPv4 + sizeof( LLMNRAnswer_t ) ] = { 0 }; + uint8_t * pucUDPPayloadBuffer = ( ( uint8_t * ) udp_buffer ) + ipUDP_PAYLOAD_OFFSET_IPv4; + struct freertos_addrinfo * pxAddressInfo; + struct xNetworkEndPoint xEndPoint = { 0 }; + uint16_t usPort = ipMDNS_PORT; + UDPPacket_t * pxUDPPacket; + + memset( pucUDPPayloadBuffer, 0x0, 250 + sizeof( LLMNRAnswer_t ) ); + size_t uxBufferLength = 250 + sizeof( LLMNRAnswer_t ); + + NetworkBufferDescriptor_t pxNetworkBuffer = { 0 }; + xEndPoint.ipv4_settings.ulIPAddress = 0xABCD1234; + pxNetworkBuffer.pucEthernetBuffer = udp_buffer; + pxNetworkBuffer.xDataLength = uxBufferLength; + pxNetworkBuffer.pxEndPoint = &xEndPoint; + + /* The second network buffer is used to store MDNS answer. */ + NetworkBufferDescriptor_t pxNewBuffer; + memcpy( &pxNewBuffer, &pxNetworkBuffer, sizeof( NetworkBufferDescriptor_t ) ); + pxNewBuffer.xDataLength = uxBufferLength; + pxNewBuffer.pucEthernetBuffer = udp_buffer; + + pxUDPPacket = ( ( UDPPacket_t * ) pxNetworkBuffer.pucEthernetBuffer ); + pxUDPPacket->xIPHeader.ulDestinationIPAddress = ipMDNS_IP_ADDRESS; + pxUDPPacket->xUDPHeader.usSourcePort = usPort; + pxUDPPacket->xUDPHeader.usDestinationPort = usPort; + + char dns[ 64 ]; + memset( dns, 'a', 64 ); + dns[ 63 ] = 0; + BaseType_t xExpected = pdFALSE; + size_t beg = sizeof( DNSMessage_t ); + + DNSMessage_t * dns_header; + + dns_header = ( DNSMessage_t * ) pucUDPPayloadBuffer; + + dns_header->usQuestions = FreeRTOS_htons( 1 ); + dns_header->usAnswers = FreeRTOS_htons( 0 ); + dns_header->usFlags = dnsDNS_PORT; + + pucUDPPayloadBuffer[ beg ] = 38; + beg++; + strcpy( pucUDPPayloadBuffer + beg, "FreeRTOSbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ); + beg += 38; + pucUDPPayloadBuffer[ beg ] = '\0'; + beg++; + + usChar2u16_ExpectAnyArgsAndReturn( dnsTYPE_A_HOST ); /* usType */ + usChar2u16_ExpectAnyArgsAndReturn( dnsCLASS_IN ); /* usClass */ + pxUDPPayloadBuffer_to_NetworkBuffer_ExpectAnyArgsAndReturn( &pxNetworkBuffer ); + + hook_return = pdTRUE; + + uxIPHeaderSizePacket_IgnoreAndReturn( ipSIZE_OF_IPv4_HEADER ); + pxDuplicateNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( &pxNewBuffer ); + usGenerateChecksum_ExpectAnyArgsAndReturn( 555 ); + usGenerateProtocolChecksum_ExpectAnyArgsAndReturn( 444 ); + vReturnEthernetFrame_Expect( &pxNewBuffer, pdFALSE ); + vReleaseNetworkBufferAndDescriptor_Expect( &pxNewBuffer ); + + ret = DNS_ParseDNSReply( pucUDPPayloadBuffer, + uxBufferLength, + &pxAddressInfo, + xExpected, + usPort ); + + TEST_ASSERT_EQUAL( 0, ret ); + ASSERT_DNS_QUERY_HOOK_CALLED(); + TEST_ASSERT_EQUAL( dnsMDNS_FLAGS_IS_RESPONSE, FreeRTOS_ntohs( dns_header->usFlags ) ); + TEST_ASSERT_EQUAL( 1, FreeRTOS_ntohs( dns_header->usAnswers ) ); + TEST_ASSERT_EQUAL( ipMDNS_TIME_TO_LIVE, pxUDPPacket->xIPHeader.ucTimeToLive ); + TEST_ASSERT_EQUAL( ipMDNS_PORT, pxUDPPacket->xUDPHeader.usSourcePort ); + TEST_ASSERT_EQUAL( ipMDNS_PORT, pxUDPPacket->xUDPHeader.usDestinationPort ); +} + /** * @brief ensures that when the number of answers is zero no packet is sent over * the network