LCOV - code coverage report
Current view: top level - lib/dnssd/minimal_mdns/core - DnsHeader.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 32 37 86.5 %
Date: 2024-02-15 08:20:41 Functions: 26 29 89.7 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020 Project CHIP Authors
       4             :  *
       5             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6             :  *    you may not use this file except in compliance with the License.
       7             :  *    You may obtain a copy of the License at
       8             :  *
       9             :  *        http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  *    Unless required by applicable law or agreed to in writing, software
      12             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  *    See the License for the specific language governing permissions and
      15             :  *    limitations under the License.
      16             :  */
      17             : #pragma once
      18             : 
      19             : #include <lib/core/CHIPEncoding.h>
      20             : 
      21             : namespace mdns {
      22             : namespace Minimal {
      23             : 
      24             : /**
      25             :  * Wrapper around a MDNS bit-packed flags in a DNS header as defined in
      26             :  * RFC 1035 and RFC 6762
      27             :  *
      28             :  * | 0| 1 2 3 4| 5| 6| 7| 8| 9| 0| 1| 2 3 4 5 |
      29             :  * |QR| OPCODE |AA|TC|RD|RA| Z|AD|CD| RCODE   |
      30             :  *
      31             :  * RFC 6762 states:
      32             :  *   - OPCODE must be 0 on transmission and queries received that are not 0 MUST be ignored
      33             :  *   - RCODE must be 0 on transmission and messages received with non-zero must be silently ignored
      34             :  *
      35             :  *   - AA (Authoritative Answer) MUST be 0 on transmission, ignored on reception
      36             :  *   - RD (Recursion desired) MUST be 0 on transmission, ignored on reception
      37             :  *   - RA (Recursion available) MUST be 0 on transmission, ignored on reception
      38             :  *   - AD (Authentic data) MUST be 0 on transmission, ignored on reception
      39             :  *   - CD (Checking Disabled) MUST be 0 on transmission, ignored on reception
      40             :  *
      41             :  * Accessors are only provided on useful values
      42             :  */
      43             : class BitPackedFlags
      44             : {
      45             : public:
      46         208 :     explicit BitPackedFlags(uint16_t value) : mValue(value) {}
      47             : 
      48          56 :     uint16_t RawValue() const { return mValue & kMdnsNonIgnoredMask; }
      49             : 
      50          32 :     bool IsQuery() const { return (mValue & kIsResponseMask) == 0; }
      51           0 :     BitPackedFlags & SetQuery() { return ClearMask(kIsResponseMask); }
      52             : 
      53          64 :     bool IsResponse() const { return (mValue & kIsResponseMask) == kIsResponseMask; }
      54         110 :     BitPackedFlags & SetResponse() { return SetMask(kIsResponseMask); }
      55             : 
      56             :     bool IsAuthoritative() const { return (mValue & kAuthoritativeMask) == kAuthoritativeMask; }
      57         110 :     BitPackedFlags & SetAuthoritative() { return SetMask(kAuthoritativeMask); }
      58             : 
      59             :     bool IsTruncated() const { return (mValue & kTruncationMask) != 0; }
      60          10 :     BitPackedFlags & SetTruncated(bool value) { return value ? SetMask(kTruncationMask) : ClearMask(kTruncationMask); }
      61             : 
      62             :     /// Validates that the message does not need to be ignored according to
      63             :     /// RFC 6762
      64          64 :     bool IsValidMdns() const { return (mValue & (kOpcodeMask | kReturnCodeMask)) == 0; }
      65             : 
      66             : private:
      67             :     uint16_t mValue = 0;
      68             : 
      69           0 :     inline BitPackedFlags & ClearMask(uint16_t mask)
      70             :     {
      71           0 :         mValue &= static_cast<uint16_t>(~mask);
      72           0 :         return *this;
      73             :     }
      74             : 
      75         230 :     inline BitPackedFlags & SetMask(uint16_t mask)
      76             :     {
      77         230 :         mValue |= mask;
      78         230 :         return *this;
      79             :     }
      80             : 
      81             :     // Mask to limit values to what RFC 6762 consideres useful
      82             :     // 1111 1110 0000 0000 = FE0F
      83             :     // TODO(cecille): need to better document this value. Why is the comment different than the value?
      84             :     static constexpr uint16_t kMdnsNonIgnoredMask = 0x8E08;
      85             :     static constexpr uint16_t kAuthoritativeMask  = 0x0400;
      86             :     static constexpr uint16_t kIsResponseMask     = 0x8000;
      87             :     static constexpr uint16_t kOpcodeMask         = 0x7000;
      88             :     static constexpr uint16_t kTruncationMask     = 0x0200;
      89             :     static constexpr uint16_t kReturnCodeMask     = 0x000F;
      90             : };
      91             : 
      92             : /**
      93             :  * Allows operations on a DNS header. A DNS Header is defined in RFC 1035
      94             :  * and looks like this:
      95             :  *
      96             :  * | 0| 1 2 3 4| 5| 6| 7| 8| 9| 0| 1| 2 3 4 5 |
      97             :  * |               Message ID                 |
      98             :  * |QR| OPCODE |AA|TC|RD|RA| Z|AD|CD| RCODE   |
      99             :  * |       Items in QUESTION Section          |
     100             :  * |       Items in ANSWER Section            |
     101             :  * |       Items in AUTHORITY Section         |
     102             :  * |       Items in ADDITIONAL Section        |
     103             :  */
     104             : class ConstHeaderRef
     105             : {
     106             : public:
     107             :     static constexpr size_t kSizeBytes = 12; /// size of a DNS header structure
     108         193 :     ConstHeaderRef(const uint8_t * buffer) : mBuffer(buffer) {}
     109             : 
     110          24 :     uint16_t GetMessageId() const { return Get16At(kMessageIdOffset); }
     111             : 
     112         208 :     BitPackedFlags GetFlags() const { return BitPackedFlags(Get16At(kFlagsOffset)); }
     113             : 
     114          88 :     uint16_t GetQueryCount() const { return Get16At(kQueryCountOffset); }
     115        1137 :     uint16_t GetAnswerCount() const { return Get16At(kAnswerCountOffset); }
     116         541 :     uint16_t GetAuthorityCount() const { return Get16At(kAuthorityCountOffset); }
     117         513 :     uint16_t GetAdditionalCount() const { return Get16At(kAdditionalCountOffset); }
     118             : 
     119             : protected:
     120             :     const uint8_t * mBuffer;
     121             : 
     122        2435 :     inline uint16_t Get16At(size_t offset) const { return chip::Encoding::BigEndian::Get16(mBuffer + offset); }
     123             :     uint16_t GetRawFlags() const { return Get16At(kFlagsOffset); }
     124             : 
     125             :     static constexpr size_t kMessageIdOffset       = 0;
     126             :     static constexpr size_t kFlagsOffset           = 2;
     127             :     static constexpr size_t kQueryCountOffset      = 4;
     128             :     static constexpr size_t kAnswerCountOffset     = 6;
     129             :     static constexpr size_t kAuthorityCountOffset  = 8;
     130             :     static constexpr size_t kAdditionalCountOffset = 10;
     131             : };
     132             : 
     133             : class HeaderRef : public ConstHeaderRef
     134             : {
     135             : public:
     136         129 :     HeaderRef(uint8_t * buffer) : ConstHeaderRef(buffer) {}
     137             :     HeaderRef(const HeaderRef & other)             = default;
     138             :     HeaderRef & operator=(const HeaderRef & other) = default;
     139             : 
     140          56 :     HeaderRef & Clear()
     141             :     {
     142          56 :         memset(GetWritable(), 0, kSizeBytes);
     143          56 :         return *this;
     144             :     }
     145             : 
     146          56 :     HeaderRef & SetMessageId(uint16_t value) { return Set16At(kMessageIdOffset, value); }
     147          56 :     HeaderRef & SetFlags(BitPackedFlags flags) { return Set16At(kFlagsOffset, flags.RawValue()); }
     148           0 :     HeaderRef & SetQueryCount(uint16_t value) { return Set16At(kQueryCountOffset, value); }
     149         832 :     HeaderRef & SetAnswerCount(uint16_t value) { return Set16At(kAnswerCountOffset, value); }
     150           1 :     HeaderRef & SetAuthorityCount(uint16_t value) { return Set16At(kAuthorityCountOffset, value); }
     151          25 :     HeaderRef & SetAdditionalCount(uint16_t value) { return Set16At(kAdditionalCountOffset, value); }
     152             : 
     153             : private:
     154             :     /// Returns the internal buffer as writable. Const-cast is correct because
     155             :     /// the construct took a non-const buffer as well.
     156         591 :     uint8_t * GetWritable() { return const_cast<uint8_t *>(mBuffer); }
     157             : 
     158         552 :     inline HeaderRef & Set16At(size_t offset, uint16_t value)
     159             :     {
     160         552 :         chip::Encoding::BigEndian::Put16(GetWritable() + offset, value);
     161         552 :         return *this;
     162             :     }
     163             : 
     164             :     HeaderRef & SetRawFlags(uint16_t value) { return Set16At(kFlagsOffset, value); }
     165             : };
     166             : 
     167             : } // namespace Minimal
     168             : } // namespace mdns

Generated by: LCOV version 1.14