|
263 | 263 | BaseType_t xReturn = pdTRUE; |
264 | 264 | uint32_t ulIPAddress = 0U; |
265 | 265 | BaseType_t xDNSHookReturn = 0U; |
| 266 | + NetworkBufferDescriptor_t * pxNewBuffer = NULL; |
266 | 267 |
|
267 | 268 | ( void ) memset( &( xSet ), 0, sizeof( xSet ) ); |
268 | 269 | xSet.usPortNumber = usPort; |
|
383 | 384 | xSet.pucByte = &( xSet.pucByte[ uxResult ] ); |
384 | 385 | xSet.uxSourceBytesRemaining -= uxResult; |
385 | 386 |
|
| 387 | + if( ( x == 0U ) && ( xSet.usPortNumber == ipMDNS_PORT ) ) |
| 388 | + { |
| 389 | + /* Note that the Questions section turns into the Answers section. |
| 390 | + * uxSkipCount points to the first byte after e.g. 'name.local' */ |
| 391 | + xSet.uxSkipCount = ( size_t ) ( xSet.pucByte - pucUDPPayloadBuffer ); |
| 392 | + } |
| 393 | + |
386 | 394 | /* Check the remaining buffer size. */ |
387 | 395 | if( xSet.uxSourceBytesRemaining >= sizeof( uint32_t ) ) |
388 | 396 | { |
|
430 | 438 | NetworkEndPoint_t * pxEndPoint, xEndPoint; |
431 | 439 | size_t uxUDPOffset; |
432 | 440 |
|
| 441 | + #if ( ipconfigUSE_IPv6 == 0 ) |
| 442 | + /* Don't treat AAAA request when IPv6 is not enabled. */ |
| 443 | + if( xSet.usType == dnsTYPE_AAAA_HOST ) |
| 444 | + { |
| 445 | + break; |
| 446 | + } |
| 447 | + #endif |
| 448 | + #if ( ipconfigUSE_IPv4 == 0 ) |
| 449 | + /* Don't treat A request when IPv4 is not enabled. */ |
| 450 | + if( xSet.usType == dnsTYPE_A_HOST ) |
| 451 | + { |
| 452 | + break; |
| 453 | + } |
| 454 | + #endif |
| 455 | + |
433 | 456 | pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer ); |
434 | 457 |
|
435 | 458 | /* This test could be replaced with a assert(). */ |
|
458 | 481 | #if ( ipconfigUSE_IPv6 != 0 ) |
459 | 482 | { |
460 | 483 | /*logging*/ |
461 | | - FreeRTOS_printf( ( "prvParseDNS_HandleLLMNRRequest[%s]: type %04X\n", xSet.pcName, xSet.usType ) ); |
| 484 | + FreeRTOS_printf( ( "DNS_ParseDNSReply[%s]: type %04X\n", xSet.pcName, xSet.usType ) ); |
462 | 485 |
|
463 | 486 | xEndPoint.usDNSType = ( uint8_t ) xSet.usType; |
464 | 487 | } |
|
482 | 505 | if( xDNSHookReturn != pdFALSE ) |
483 | 506 | { |
484 | 507 | int16_t usLength; |
485 | | - NetworkBufferDescriptor_t * pxNewBuffer = NULL; |
486 | 508 | LLMNRAnswer_t * pxAnswer; |
487 | 509 | uint8_t * pucNewBuffer = NULL; |
488 | | - size_t uxExtraLength; |
489 | | - size_t uxDataLength = uxBufferLength + |
490 | | - sizeof( UDPHeader_t ) + |
491 | | - sizeof( EthernetHeader_t ) + |
492 | | - uxIPHeaderSizePacket( pxNetworkBuffer ); |
| 510 | + /* Number of bytes to write the Answers section: 16 (A) or 28 (AAAA). */ |
| 511 | + size_t uxExtraLength = 0U; |
| 512 | + size_t uxDataLength = uxBufferLength + /* Length of the UDP payload buffer */ |
| 513 | + sizeof( UDPHeader_t ) + /* Length of the UDP header */ |
| 514 | + sizeof( EthernetHeader_t ) + /* Length of the Ethernet header */ |
| 515 | + uxIPHeaderSizePacket( pxNetworkBuffer ); /* Lentgh of IP 20 or 40. */ |
493 | 516 |
|
494 | 517 | #if ( ipconfigUSE_IPv6 != 0 ) |
495 | 518 | if( xSet.usType == dnsTYPE_AAAA_HOST ) |
496 | 519 | { |
| 520 | + /* The number of bytes needed by Answers section (28 bytes). */ |
497 | 521 | uxExtraLength = sizeof( LLMNRAnswer_t ) + ipSIZE_OF_IPv6_ADDRESS - sizeof( pxAnswer->ulIPAddress ); |
498 | 522 | } |
499 | 523 | else |
500 | 524 | #endif /* ( ipconfigUSE_IPv6 != 0 ) */ |
501 | 525 | #if ( ipconfigUSE_IPv4 != 0 ) |
502 | 526 | { |
| 527 | + /* The number of bytes needed by Answers section (16 bytes). */ |
503 | 528 | uxExtraLength = sizeof( LLMNRAnswer_t ); |
504 | 529 | } |
505 | 530 | #else /* ( ipconfigUSE_IPv4 != 0 ) */ |
|
510 | 535 |
|
511 | 536 | if( xBufferAllocFixedSize == pdFALSE ) |
512 | 537 | { |
513 | | - /* Set the size of the outgoing packet. */ |
| 538 | + /* Set the size of the outgoing packet. |
| 539 | + * setting 'xDataLength' determines the minimum number of bytes copied. */ |
514 | 540 | pxNetworkBuffer->xDataLength = uxDataLength; |
515 | 541 | pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, |
516 | 542 | uxDataLength + |
|
553 | 579 |
|
554 | 580 | if( ( pxNetworkBuffer != NULL ) ) |
555 | 581 | { |
556 | | - pxAnswer = ( ( LLMNRAnswer_t * ) xSet.pucByte ); |
| 582 | + size_t uxDistance; |
| 583 | + |
557 | 584 | /* We leave 'usIdentifier' and 'usQuestions' untouched */ |
558 | | - vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_RESPONSE ); /* Set the response flag */ |
559 | | - vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */ |
560 | | - vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */ |
561 | | - vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */ |
| 585 | + if( xSet.uxSkipCount >= 2 ) |
| 586 | + { |
| 587 | + /* Four bytes back to write usType/usClass. */ |
| 588 | + pxAnswer = ( LLMNRAnswer_t * ) ( &( pucNewBuffer[ xSet.uxSkipCount - 2 ] ) ); |
| 589 | + /* Follow RFC6762 to set QR bit (section 18.2) and authoritative answer (AA) bit (section 18.4). */ |
| 590 | + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usFlags, dnsMDNS_FLAGS_IS_RESPONSE ); |
| 591 | + /* When replying to an mDNS request, do not include the Questions section. */ |
| 592 | + xSet.usQuestions = 0; |
| 593 | + } |
| 594 | + else |
| 595 | + { |
| 596 | + pxAnswer = ( ( LLMNRAnswer_t * ) xSet.pucByte ); |
| 597 | + /* Follow RFC4795 to set QR bit (section 2.1.1) */ |
| 598 | + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_RESPONSE ); |
| 599 | + } |
562 | 600 |
|
563 | | - pxAnswer->ucNameCode = dnsNAME_IS_OFFSET; |
564 | | - pxAnswer->ucNameOffset = ( uint8_t ) ( xSet.pcRequestedName - ( char * ) pucNewBuffer ); |
| 601 | + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usQuestions, xSet.usQuestions ); /* Might be zero. */ |
| 602 | + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */ |
| 603 | + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */ |
| 604 | + vSetField16( xSet.pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */ |
| 605 | + |
| 606 | + if( xSet.usQuestions > 0 ) |
| 607 | + { |
| 608 | + pxAnswer->ucNameCode = dnsNAME_IS_OFFSET; |
| 609 | + pxAnswer->ucNameOffset = ( uint8_t ) ( xSet.pcRequestedName - ( char * ) pucNewBuffer ); |
| 610 | + } |
565 | 611 |
|
566 | 612 | vSetField16( pxAnswer, LLMNRAnswer_t, usType, xSet.usType ); /* Type A or AAAA: host */ |
567 | 613 | vSetField16( pxAnswer, LLMNRAnswer_t, usClass, dnsCLASS_IN ); /* 1: Class IN */ |
568 | 614 | vSetField32( pxAnswer, LLMNRAnswer_t, ulTTL, dnsLLMNR_TTL_VALUE ); |
569 | 615 |
|
570 | | - usLength = ( int16_t ) ( sizeof( *pxAnswer ) + ( size_t ) ( xSet.pucByte - pucNewBuffer ) ); |
| 616 | + uxDistance = ( size_t ) ( ( ( const uint8_t * ) pxAnswer ) - pucNewBuffer ); |
571 | 617 |
|
572 | 618 | #if ( ipconfigUSE_IPv6 != 0 ) |
573 | 619 | if( xSet.usType == dnsTYPE_AAAA_HOST ) |
574 | 620 | { |
575 | | - size_t uxDistance; |
576 | 621 | vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, ipSIZE_OF_IPv6_ADDRESS ); |
577 | 622 | ( void ) memcpy( &( pxAnswer->ulIPAddress ), xEndPoint.ipv6_settings.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); |
578 | | - uxDistance = ( size_t ) ( xSet.pucByte - pucNewBuffer ); |
579 | 623 | /* An extra 12 bytes will be sent compared to an A-record. */ |
580 | 624 | usLength = ( int16_t ) ( sizeof( *pxAnswer ) + uxDistance + ipSIZE_OF_IPv6_ADDRESS - sizeof( pxAnswer->ulIPAddress ) ); |
581 | 625 | } |
582 | 626 | else |
583 | 627 | #endif /* ( ipconfigUSE_IPv6 != 0 ) */ |
584 | 628 | { |
585 | | - size_t uxDistance; |
586 | 629 | vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, ( uint16_t ) sizeof( pxAnswer->ulIPAddress ) ); |
587 | 630 | vSetField32( pxAnswer, LLMNRAnswer_t, ulIPAddress, FreeRTOS_ntohl( xEndPoint.ipv4_settings.ulIPAddress ) ); |
588 | | - uxDistance = ( size_t ) ( xSet.pucByte - pucNewBuffer ); |
589 | 631 | usLength = ( int16_t ) ( sizeof( *pxAnswer ) + uxDistance ); |
590 | 632 | } |
591 | 633 |
|
592 | 634 | prepareReplyDNSMessage( pxNetworkBuffer, usLength ); |
593 | | - /* This function will fill in the eth addresses and send the packet */ |
594 | | - vReturnEthernetFrame( pxNetworkBuffer, pdFALSE ); |
595 | 635 |
|
596 | | - if( pxNewBuffer != NULL ) |
597 | | - { |
598 | | - vReleaseNetworkBufferAndDescriptor( pxNewBuffer ); |
599 | | - } |
| 636 | + /* This function will fill in the eth addresses and send the packet. |
| 637 | + * xReleaseAfterSend = pdFALSE. */ |
| 638 | + vReturnEthernetFrame( pxNetworkBuffer, pdFALSE ); |
600 | 639 | } |
601 | 640 | } |
602 | 641 | else |
|
607 | 646 | #endif /* ipconfigUSE_LLMNR == 1 */ |
608 | 647 | ( void ) uxBytesRead; |
609 | 648 | } while( ipFALSE_BOOL ); |
| 649 | + |
| 650 | + if( pxNewBuffer != NULL ) |
| 651 | + { |
| 652 | + vReleaseNetworkBufferAndDescriptor( pxNewBuffer ); |
| 653 | + } |
610 | 654 | } |
611 | 655 |
|
612 | 656 | if( xReturn == pdFALSE ) |
|
0 commit comments