/* Copyright (C) 2019 CZ.NIC, z.s.p.o. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /*! * \file * * \brief Functions for manipulating and parsing raw data in DNS packets. * * \addtogroup wire * @{ */ #pragma once #include #include #include "libknot/attribute.h" #include "libknot/wire.h" /*! \brief Offset of DNS header fields in wireformat. */ enum knot_wire_offsets { KNOT_WIRE_OFFSET_ID = 0, KNOT_WIRE_OFFSET_FLAGS1 = 2, KNOT_WIRE_OFFSET_FLAGS2 = 3, KNOT_WIRE_OFFSET_QDCOUNT = 4, KNOT_WIRE_OFFSET_ANCOUNT = 6, KNOT_WIRE_OFFSET_NSCOUNT = 8, KNOT_WIRE_OFFSET_ARCOUNT = 10 }; /*! \brief Minimum size for some parts of the DNS packet. */ enum knot_wire_sizes { KNOT_WIRE_HEADER_SIZE = 12, KNOT_WIRE_QUESTION_MIN_SIZE = 5, KNOT_WIRE_RR_MIN_SIZE = 11, KNOT_WIRE_MIN_PKTSIZE = 512, KNOT_WIRE_MAX_PKTSIZE = 65535, KNOT_WIRE_MAX_PAYLOAD = KNOT_WIRE_MAX_PKTSIZE - KNOT_WIRE_HEADER_SIZE - KNOT_WIRE_QUESTION_MIN_SIZE }; /* * Packet header manipulation functions. */ /*! * \brief Returns the ID from wire format of the packet. * * \param packet Wire format of the packet. * * \return DNS packet ID. */ static inline uint16_t knot_wire_get_id(const uint8_t *packet) { assert(packet); return knot_wire_read_u16(packet + KNOT_WIRE_OFFSET_ID); } /*! * \brief Sets the ID to the wire format of the packet. * * \param packet Wire format of the packet. * \param id DNS packet ID. */ static inline void knot_wire_set_id(uint8_t *packet, uint16_t id) { assert(packet); knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_ID, id); } /*! * \brief Returns the first byte of flags from wire format of the packet. * * \param packet Wire format of the packet. * * \return First byte of DNS flags. */ static inline uint8_t knot_wire_get_flags1(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS1); } /*! * \brief Sets the first byte of flags to the wire format of the packet. * * \param packet Wire format of the packet. * \param flags1 First byte of the DNS flags. */ static inline uint8_t knot_wire_set_flags1(uint8_t *packet, uint8_t flags1) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS1) = flags1; } /*! * \brief Returns the second byte of flags from wire format of the packet. * * \param packet Wire format of the packet. * * \return Second byte of DNS flags. */ static inline uint8_t knot_wire_get_flags2(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS2); } /*! * \brief Sets the second byte of flags to the wire format of the packet. * * \param packet Wire format of the packet. * \param flags2 Second byte of the DNS flags. */ static inline uint8_t knot_wire_set_flags2(uint8_t *packet, uint8_t flags2) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS2) = flags2; } /*! * \brief Returns the QDCOUNT (count of Question entries) from wire format of * the packet. * * \param packet Wire format of the packet. * * \return QDCOUNT (count of Question entries in the packet). */ static inline uint16_t knot_wire_get_qdcount(const uint8_t *packet) { assert(packet); return knot_wire_read_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT); } /*! * \brief Sets the QDCOUNT (count of Question entries) to wire format of the * packet. * * \param packet Wire format of the packet. * \param qdcount QDCOUNT (count of Question entries in the packet). */ static inline void knot_wire_set_qdcount(uint8_t *packet, uint16_t qdcount) { assert(packet); knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT, qdcount); } /*! * \brief Adds to QDCOUNT. */ static inline void knot_wire_add_qdcount(uint8_t *packet, int16_t n) { assert(packet); knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_QDCOUNT, knot_wire_get_qdcount(packet) + n); } /*! * \brief Returns the ANCOUNT (count of Answer entries) from wire format of * the packet. * * \param packet Wire format of the packet. * * \return ANCOUNT (count of Answer entries in the packet). */ static inline uint16_t knot_wire_get_ancount(const uint8_t *packet) { assert(packet); return knot_wire_read_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT); } /*! * \brief Sets the ANCOUNT (count of Answer entries) to wire format of the * packet. * * \param packet Wire format of the packet. * \param ancount ANCOUNT (count of Answer entries in the packet). */ static inline void knot_wire_set_ancount(uint8_t *packet, uint16_t ancount) { assert(packet); knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT, ancount); } /*! * \brief Adds to ANCOUNT. */ static inline void knot_wire_add_ancount(uint8_t *packet, int16_t n) { assert(packet); knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_ANCOUNT, knot_wire_get_ancount(packet) + n); } /*! * \brief Returns the NSCOUNT (count of Authority entries) from wire format of * the packet. * * \param packet Wire format of the packet. * * \return NSCOUNT (count of Authority entries in the packet). */ static inline uint16_t knot_wire_get_nscount(const uint8_t *packet) { assert(packet); return knot_wire_read_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT); } /*! * \brief Sets the NSCOUNT (count of Authority entries) to wire format of the * packet. * * \param packet Wire format of the packet. * \param nscount NSCOUNT (count of Authority entries in the packet). */ static inline void knot_wire_set_nscount(uint8_t *packet, uint16_t nscount) { assert(packet); knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT, nscount); } /*! * \brief Adds to NSCOUNT. */ static inline void knot_wire_add_nscount(uint8_t *packet, int16_t n) { assert(packet); knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_NSCOUNT, knot_wire_get_nscount(packet) + n); } /*! * \brief Returns the ARCOUNT (count of Additional entries) from wire format of * the packet. * * \param packet Wire format of the packet. * * \return ARCOUNT (count of Additional entries in the packet). */ static inline uint16_t knot_wire_get_arcount(const uint8_t *packet) { assert(packet); return knot_wire_read_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT); } /*! * \brief Sets the ARCOUNT (count of Additional entries) to wire format of the * packet. * * \param packet Wire format of the packet. * \param arcount ARCOUNT (count of Additional entries in the packet). */ static inline void knot_wire_set_arcount(uint8_t *packet, uint16_t arcount) { assert(packet); knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT, arcount); } /*! * \brief Adds to ARCOUNT. */ static inline void knot_wire_add_arcount(uint8_t *packet, int16_t n) { assert(packet); knot_wire_write_u16(packet + KNOT_WIRE_OFFSET_ARCOUNT, knot_wire_get_arcount(packet) + n); } /* * Packet header flags manipulation functions. */ /*! \brief Constants for DNS header flags in the first flags byte. */ enum knot_wire_flags1_consts { KNOT_WIRE_RD_MASK = (uint8_t)0x01U, /*!< RD bit mask. */ KNOT_WIRE_RD_SHIFT = 0, /*!< RD bit shift. */ KNOT_WIRE_TC_MASK = (uint8_t)0x02U, /*!< TC bit mask. */ KNOT_WIRE_TC_SHIFT = 1, /*!< TC bit shift. */ KNOT_WIRE_AA_MASK = (uint8_t)0x04U, /*!< AA bit mask. */ KNOT_WIRE_AA_SHIFT = 2, /*!< AA bit shift. */ KNOT_WIRE_OPCODE_MASK = (uint8_t)0x78U, /*!< OPCODE mask. */ KNOT_WIRE_OPCODE_SHIFT = 3, /*!< OPCODE shift. */ KNOT_WIRE_QR_MASK = (uint8_t)0x80U, /*!< QR bit mask. */ KNOT_WIRE_QR_SHIFT = 7 /*!< QR bit shift. */ }; /*! \brief Constants for DNS header flags in the second flags byte. */ enum knot_wire_flags2_consts { KNOT_WIRE_RCODE_MASK = (uint8_t)0x0fU, /*!< RCODE mask. */ KNOT_WIRE_RCODE_SHIFT = 0, /*!< RCODE shift. */ KNOT_WIRE_CD_MASK = (uint8_t)0x10U, /*!< CD bit mask. */ KNOT_WIRE_CD_SHIFT = 4, /*!< CD bit shift. */ KNOT_WIRE_AD_MASK = (uint8_t)0x20U, /*!< AD bit mask. */ KNOT_WIRE_AD_SHIFT = 5, /*!< AD bit shift. */ KNOT_WIRE_Z_MASK = (uint8_t)0x40U, /*!< Zero bit mask. */ KNOT_WIRE_Z_SHIFT = 6, /*!< Zero bit shift. */ KNOT_WIRE_RA_MASK = (uint8_t)0x80U, /*!< RA bit mask. */ KNOT_WIRE_RA_SHIFT = 7 /*!< RA bit shift. */ }; /* * Functions for getting / setting / clearing flags and codes directly in packet */ /*! * \brief Returns the RD bit from wire format of the packet. * * \param packet Wire format of the packet. * * \return Flags with only the RD bit according to its setting in the packet. */ static inline uint8_t knot_wire_get_rd(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS1) & KNOT_WIRE_RD_MASK; } /*! * \brief Sets the RD bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_set_rd(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS1) |= KNOT_WIRE_RD_MASK; } /*! * \brief Clears the RD bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_clear_rd(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS1) &= ~KNOT_WIRE_RD_MASK; } /*! * \brief Returns the TC bit from wire format of the packet. * * \param packet Wire format of the packet. * * \return Flags with only the TC bit according to its setting in the packet. */ static inline uint8_t knot_wire_get_tc(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS1) & KNOT_WIRE_TC_MASK; } /*! * \brief Sets the TC bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_set_tc(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS1) |= KNOT_WIRE_TC_MASK; } /*! * \brief Clears the TC bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_clear_tc(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS1) &= ~KNOT_WIRE_TC_MASK; } /*! * \brief Returns the AA bit from wire format of the packet. * * \param packet Wire format of the packet. * * \return Flags with only the AA bit according to its setting in the packet. */ static inline uint8_t knot_wire_get_aa(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS1) & KNOT_WIRE_AA_MASK; } /*! * \brief Sets the AA bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_set_aa(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS1) |= KNOT_WIRE_AA_MASK; } /*! * \brief Clears the AA bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_clear_aa(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS1) &= ~KNOT_WIRE_AA_MASK; } /*! * \brief Returns the OPCODE from wire format of the packet. * * \param packet Wire format of the packet. * * \return OPCODE of the packet. */ static inline uint8_t knot_wire_get_opcode(const uint8_t *packet) { assert(packet); return (*(packet + KNOT_WIRE_OFFSET_FLAGS1) & KNOT_WIRE_OPCODE_MASK) >> KNOT_WIRE_OPCODE_SHIFT; } /*! * \brief Sets the OPCODE in the wire format of the packet. * * \param packet Wire format of the packet. * \param opcode OPCODE to set. */ static inline void knot_wire_set_opcode(uint8_t *packet, short opcode) { assert(packet); uint8_t *flags1 = packet + KNOT_WIRE_OFFSET_FLAGS1; *flags1 = (*flags1 & ~KNOT_WIRE_OPCODE_MASK) | ((opcode) << KNOT_WIRE_OPCODE_SHIFT); } /*! * \brief Returns the QR bit from wire format of the packet. * * \param packet Wire format of the packet. * * \return Nonzero for responses and zero for queries. */ static inline uint8_t knot_wire_get_qr(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS1) & KNOT_WIRE_QR_MASK; } /*! * \brief Sets the QR bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_set_qr(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS1) |= KNOT_WIRE_QR_MASK; } /*! * \brief Clears the QR bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_clear_qr(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS1) &= ~KNOT_WIRE_QR_MASK; } /*! * \brief Returns the RCODE from wire format of the packet. * * \param packet Wire format of the packet. * * \return RCODE of the packet. */ static inline uint8_t knot_wire_get_rcode(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS2) & KNOT_WIRE_RCODE_MASK; } /*! * \brief Sets the RCODE in the wire format of the packet. * * \param packet Wire format of the packet. * \param rcode RCODE to set. */ static inline void knot_wire_set_rcode(uint8_t *packet, short rcode) { assert(packet); uint8_t *flags2 = packet + KNOT_WIRE_OFFSET_FLAGS2; *flags2 = (*flags2 & ~KNOT_WIRE_RCODE_MASK) | (rcode); } /*! * \brief Returns the CD bit from wire format of the packet. * * \param packet Wire format of the packet. * * \return Flags with only the CD bit according to its setting in the packet. */ static inline uint8_t knot_wire_get_cd(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS2) & KNOT_WIRE_CD_MASK; } /*! * \brief Sets the CD bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_set_cd(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS2) |= KNOT_WIRE_CD_MASK; } /*! * \brief Clears the CD bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_clear_cd(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS2) &= ~KNOT_WIRE_CD_MASK; } /*! * \brief Returns the AD bit from wire format of the packet. * * \param packet Wire format of the packet. * * \return Flags with only the AD bit according to its setting in the packet. */ static inline uint8_t knot_wire_get_ad(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS2) & KNOT_WIRE_AD_MASK; } /*! * \brief Sets the AD bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_set_ad(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS2) |= KNOT_WIRE_AD_MASK; } /*! * \brief Clears the AD bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_clear_ad(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS2) &= ~KNOT_WIRE_AD_MASK; } /*! * \brief Returns the Zero bit from wire format of the packet. * * \param packet Wire format of the packet. * * \return Flags with only the Zero bit according to its setting in the packet. */ static inline uint8_t knot_wire_get_z(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS2) & KNOT_WIRE_Z_MASK; } /*! * \brief Sets the Zero bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_set_z(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS2) |= KNOT_WIRE_Z_MASK; } /*! * \brief Clears the Zero bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_clear_z(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS2) &= ~KNOT_WIRE_Z_MASK; } /*! * \brief Returns the RA bit from wire format of the packet. * * \param packet Wire format of the packet. * * \return Flags with only the RA bit according to its setting in the packet. */ static inline uint8_t knot_wire_get_ra(const uint8_t *packet) { assert(packet); return *(packet + KNOT_WIRE_OFFSET_FLAGS2) & KNOT_WIRE_RA_MASK; } /*! * \brief Sets the RA bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_set_ra(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS2) |= KNOT_WIRE_RA_MASK; } /*! * \brief Clears the RA bit in the wire format of the packet. * * \param packet Wire format of the packet. */ static inline void knot_wire_clear_ra(uint8_t *packet) { assert(packet); *(packet + KNOT_WIRE_OFFSET_FLAGS2) &= ~KNOT_WIRE_RA_MASK; } /* * Functions for getting / setting / clearing flags in flags variable */ /*! * \brief Returns the RD bit from the first byte of flags. * * \param flags1 First byte of DNS header flags. * * \return Flags byte with only the RD bit according to its setting in * \a flags1. */ static inline uint8_t knot_wire_flags_get_rd(uint8_t flags1) { return flags1 & KNOT_WIRE_RD_MASK; } /*! * \brief Sets the RD bit in the first byte of flags. * * \param flags1 First byte of DNS header flags. */ static inline void knot_wire_flags_set_rd(uint8_t *flags1) { assert(flags1); *flags1 |= KNOT_WIRE_RD_MASK; } /*! * \brief Clears the RD bit in the first byte of flags. * * \param flags1 First byte of DNS header flags. */ static inline void knot_wire_flags_clear_rd(uint8_t *flags1) { assert(flags1); *flags1 &= ~KNOT_WIRE_RD_MASK; } /*! * \brief Returns the TC bit from the first byte of flags. * * \param flags1 First byte of DNS header flags. * * \return Flags byte with only the TC bit according to its setting in * \a flags1. */ static inline uint8_t knot_wire_flags_get_tc(uint8_t flags1) { return flags1 & KNOT_WIRE_TC_MASK; } /*! * \brief Sets the TC bit in the first byte of flags. * * \param flags1 First byte of DNS header flags. */ static inline void knot_wire_flags_set_tc(uint8_t *flags1) { assert(flags1); *flags1 |= KNOT_WIRE_TC_MASK; } /*! * \brief Clears the TC bit in the first byte of flags. * * \param flags1 First byte of DNS header flags. */ static inline void knot_wire_flags_clear_tc(uint8_t *flags1) { assert(flags1); *flags1 &= ~KNOT_WIRE_TC_MASK; } /*! * \brief Returns the AA bit from the first byte of flags. * * \param flags1 First byte of DNS header flags. * * \return Flags byte with only the AA bit according to its setting in * \a flags1. */ static inline uint8_t knot_wire_flags_get_aa(uint8_t flags1) { return flags1 & KNOT_WIRE_AA_MASK; } /*! * \brief Sets the AA bit in the first byte of flags. * * \param flags1 First byte of DNS header flags. */ static inline void knot_wire_flags_set_aa(uint8_t *flags1) { assert(flags1); *flags1 |= KNOT_WIRE_AA_MASK; } /*! * \brief Clears the AA bit in the first byte of flags. * * \param flags1 First byte of DNS header flags. */ static inline void knot_wire_flags_clear_aa(uint8_t *flags1) { assert(flags1); *flags1 &= ~KNOT_WIRE_AA_MASK; } /*! * \brief Returns the OPCODE from the first byte of flags. * * \param flags1 First byte of DNS header flags. * * \return OPCODE */ static inline uint8_t knot_wire_flags_get_opcode(uint8_t flags1) { return (flags1 & KNOT_WIRE_OPCODE_MASK) >> KNOT_WIRE_OPCODE_SHIFT; } /*! * \brief Sets the OPCODE in the first byte of flags. * * \param flags1 First byte of DNS header flags. * \param opcode OPCODE to set. */ static inline void knot_wire_flags_set_opcode(uint8_t *flags1, short opcode) { assert(flags1); *flags1 = (*flags1 & ~KNOT_WIRE_OPCODE_MASK) | ((opcode) << KNOT_WIRE_OPCODE_SHIFT); } /*! * \brief Returns the QR bit from the first byte of flags. * * \param flags1 First byte of DNS header flags. * * \return Flags byte with only the QR bit according to its setting in * \a flags1. */ static inline uint8_t knot_wire_flags_get_qr(uint8_t flags1) { return flags1 & KNOT_WIRE_QR_MASK; } /*! * \brief Sets the QR bit in the first byte of flags. * * \param flags1 First byte of DNS header flags. */ static inline void knot_wire_flags_set_qr(uint8_t *flags1) { assert(flags1); *flags1 |= KNOT_WIRE_QR_MASK; } /*! * \brief Clears the QR bit in the first byte of flags. * * \param flags1 First byte of DNS header flags. */ static inline void knot_wire_flags_clear_qr(uint8_t *flags1) { assert(flags1); *flags1 &= ~KNOT_WIRE_QR_MASK; } /*! * \brief Returns the RCODE from the second byte of flags. * * \param flags2 First byte of DNS header flags. * * \return RCODE */ static inline uint8_t knot_wire_flags_get_rcode(uint8_t flags2) { return flags2 & KNOT_WIRE_RCODE_MASK; } /*! * \brief Sets the RCODE in the second byte of flags. * * \param flags2 Second byte of DNS header flags. * \param rcode RCODE to set. */ static inline void knot_wire_flags_set_rcode(uint8_t *flags2, short rcode) { assert(flags2); *flags2 = (*flags2 & ~KNOT_WIRE_RCODE_MASK) | (rcode); } /*! * \brief Returns the CD bit from the second byte of flags. * * \param flags2 Second byte of DNS header flags. * * \return Flags byte with only the CD bit according to its setting in * \a flags2. */ static inline uint8_t knot_wire_flags_get_cd(uint8_t flags2) { return flags2 & KNOT_WIRE_CD_MASK; } /*! * \brief Sets the CD bit in the second byte of flags. * * \param flags2 Second byte of DNS header flags. */ static inline void knot_wire_flags_set_cd(uint8_t *flags2) { assert(flags2); *flags2 |= KNOT_WIRE_CD_MASK; } /*! * \brief Clears the CD bit in the second byte of flags. * * \param flags2 Second byte of DNS header flags. */ static inline void knot_wire_flags_clear_cd(uint8_t *flags2) { assert(flags2); *flags2 &= ~KNOT_WIRE_CD_MASK; } /*! * \brief Returns the AD bit from the second byte of flags. * * \param flags2 Second byte of DNS header flags. * * \return Flags byte with only the AD bit according to its setting in * \a flags2. */ static inline uint8_t knot_wire_flags_get_ad(uint8_t flags2) { return flags2 & KNOT_WIRE_AD_MASK; } /*! * \brief Sets the AD bit in the second byte of flags. * * \param flags2 Second byte of DNS header flags. */ static inline void knot_wire_flags_set_ad(uint8_t *flags2) { assert(flags2); *flags2 |= KNOT_WIRE_AD_MASK; } /*! * \brief Clears the AD bit in the second byte of flags. * * \param flags2 Second byte of DNS header flags. */ static inline void knot_wire_flags_clear_ad(uint8_t *flags2) { assert(flags2); *flags2 &= ~KNOT_WIRE_AD_MASK; } /*! * \brief Returns the Zero bit from the second byte of flags. * * \param flags2 Second byte of DNS header flags. * * \return Flags byte with only the Zero bit according to its setting in * \a flags2. */ static inline uint8_t knot_wire_flags_get_z(uint8_t flags2) { return flags2 & KNOT_WIRE_Z_MASK; } /*! * \brief Sets the Zero bit in the second byte of flags. * * \param flags2 Second byte of DNS header flags. */ static inline void knot_wire_flags_set_z(uint8_t *flags2) { assert(flags2); *flags2 |= KNOT_WIRE_Z_MASK; } /*! * \brief Clears the Zero bit in the second byte of flags. * * \param flags2 Second byte of DNS header flags. */ static inline void knot_wire_flags_clear_z(uint8_t *flags2) { assert(flags2); *flags2 &= ~KNOT_WIRE_Z_MASK; } /*! * \brief Returns the RA bit from the second byte of flags. * * \param flags2 Second byte of DNS header flags. * * \return Flags byte with only the RA bit according to its setting in * \a flags2. */ static inline uint8_t knot_wire_flags_get_ra(uint8_t flags2) { return flags2 & KNOT_WIRE_RA_MASK; } /*! * \brief Sets the RA bit in the second byte of flags. * * \param flags2 Second byte of DNS header flags. */ static inline void knot_wire_flags_set_ra(uint8_t *flags2) { assert(flags2); *flags2 |= KNOT_WIRE_RA_MASK; } /*! * \brief Clears the RA bit in the second byte of flags. * * \param flags2 Second byte of DNS header flags. */ static inline void knot_wire_flags_clear_ra(uint8_t *flags2) { assert(flags2); *flags2 &= ~KNOT_WIRE_RA_MASK; } /* * Pointer manipulation */ enum knot_wire_pointer_consts { /*! \brief DNS packet pointer designation (first two bits set to 1). */ KNOT_WIRE_PTR = (uint8_t)0xC0, /*! \brief DNS packet minimal pointer (KNOT_WIRE_PTR + 1 zero byte). */ KNOT_WIRE_PTR_BASE = (uint16_t)0xC000, /*! \brief DNS packet maximal offset (KNOT_WIRE_BASE complement). */ KNOT_WIRE_PTR_MAX = (uint16_t)0x3FFF }; static inline int knot_wire_is_pointer(const uint8_t *pos) { return pos && ((pos[0] & KNOT_WIRE_PTR) == KNOT_WIRE_PTR); } /*! * \brief Creates a DNS packet pointer and stores it in wire format. * * \param pos Position where tu put the pointer. * \param ptr Relative position of the item to which the pointer should point in * the wire format of the packet. */ static inline void knot_wire_put_pointer(uint8_t *pos, uint16_t ptr) { knot_wire_write_u16(pos, ptr); // Write pointer offset. assert((pos[0] & KNOT_WIRE_PTR) == 0); // Check for maximal offset. pos[0] |= KNOT_WIRE_PTR; // Add pointer mark. } static inline uint16_t knot_wire_get_pointer(const uint8_t *pos) { assert(knot_wire_is_pointer(pos)); // Check pointer. return (knot_wire_read_u16(pos) - KNOT_WIRE_PTR_BASE); // Return offset. } _pure_ _mustcheck_ static inline const uint8_t *knot_wire_seek_label(const uint8_t *lp, const uint8_t *wire) { while (knot_wire_is_pointer(lp)) { if (!wire) return NULL; lp = wire + knot_wire_get_pointer(lp); } return lp; } _pure_ _mustcheck_ static inline const uint8_t *knot_wire_next_label(const uint8_t *lp, const uint8_t *wire) { if (!lp || !lp[0]) /* No label after final label. */ return NULL; return knot_wire_seek_label(lp + (lp[0] + sizeof(uint8_t)), wire); } /*! @} */