/* * Copyright (c) 2022-2023 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef DNS_OBJ_COMMON_H #define DNS_OBJ_COMMON_H //====================================================================================================================== // MARK: - Headers #include "ref_count.h" #include #include #include #include "nullability.h" //====================================================================================================================== // MARK: - Macro Helpers #ifndef MIN #define MIN(A, B) (((A) < (B)) ? (A) : (B)) #endif #ifndef MAX #define MAX(A, B) (((A) > (B)) ? (A) : (B)) #endif #ifndef countof #define countof(X) (sizeof(X) / sizeof(X[0])) #endif #ifndef countof_field #define countof_field(TYPE, FIELD) countof(((TYPE *)0)->FIELD) #endif #ifndef likely #define likely(EXPRESSSION) __builtin_expect(!!(EXPRESSSION), 1) #endif #ifndef unlikely #define unlikely(EXPRESSSION) __builtin_expect(!!(EXPRESSSION), 0) #endif #ifndef isdigit_safe #define isdigit_safe(X) isdigit(((unsigned char)((X) & 0xFF))) #endif #if (defined(__clang__) && __clang__) #define DNS_OBJ_CLANG_WARNING_HELPER_0(X) #X #define DNS_OBJ_CLANG_WARNING_HELPER_1(X) DNS_OBJ_CLANG_WARNING_HELPER_0(clang diagnostic ignored X) #define DNS_OBJ_CLANG_WARNING_HELPER_2(Y) DNS_OBJ_CLANG_WARNING_HELPER_1(#Y) #define DNS_OBJ_CLANG_WARNING(X) _Pragma(DNS_OBJ_CLANG_WARNING_HELPER_2(X)) #define DNS_OBJ_CLANG_WARNING_IGNORE_BEGIN(X) \ _Pragma( "clang diagnostic push" ) \ DNS_OBJ_CLANG_WARNING(X) \ do {} while( 0 ) #else #define DNS_OBJ_CLANG_WARNING_IGNORE_BEGIN(X) do {} while(0) #endif #if (defined(__clang__) && __clang__) #define DNS_OBJ_CLANG_WARNING_IGNORE_END() _Pragma( "clang diagnostic pop" ) do {} while(0) #else #define DNS_OBJ_CLANG_WARNING_IGNORE_END() do {} while(0) #endif //====================================================================================================================== // MARK: - Constants typedef int32_t dns_obj_error_t; #define DNS_OBJ_ERROR_NO_ERROR 0 // No error occurred. #define DNS_OBJ_ERROR_GENERIC_ERROR_BASE -6700 // Starting error code for all generic errors. #define DNS_OBJ_ERROR_UNKNOWN_ERR -6700 // Unknown error occurred. #define DNS_OBJ_ERROR_PARAM_ERR -6705 // Parameter is incorrect, missing, or not appropriate. #define DNS_OBJ_ERROR_STATE_ERR -6709 // Not in appropriate state to perform operation. #define DNS_OBJ_ERROR_RANGE_ERR -6710 // Index is out of range or not valid. #define DNS_OBJ_ERROR_REQUEST_ERR -6711 // Request was improperly formed or not appropriate. #define DNS_OBJ_ERROR_NOT_INITIALIZED_ERR -6718 // Action request before needed services were initialized. #define DNS_OBJ_ERROR_ALREADY_INITIALIZED_ERR -6719 // Attempt made to initialize when already initialized. #define DNS_OBJ_ERROR_NOT_IN_USE_ERR -6720 // Object not in use (e.g. cannot abort if not already in use). #define DNS_OBJ_ERROR_NOT_FOUND_ERR -6727 // Something was not found. #define DNS_OBJ_ERROR_NO_MEMORY -6728 // Not enough memory was available to perform the operation. #define DNS_OBJ_ERROR_NO_RESOURCES -6729 // Resources unavailable to perform the operation. #define DNS_OBJ_ERROR_DUPLICATE_ERR -6730 // Duplicate found or something is a duplicate. #define DNS_OBJ_ERROR_UNSUPPORTED_ERR -6735 // Feature or option is not supported. #define DNS_OBJ_ERROR_UNEXPECTED_ERR -6736 // Error occurred that was not expected. #define DNS_OBJ_ERROR_MALFORMED_ERR -6742 // Something was not formed correctly. #define DNS_OBJ_ERROR_NOT_READY_ERR -6745 // Device or service is not ready. #define DNS_OBJ_ERROR_MISMATCH_ERR -6748 // Something does not match. #define DNS_OBJ_ERROR_DATE_ERR -6749 // Date is invalid or out-of-range. #define DNS_OBJ_ERROR_AUTHENTICATION_ERR -6754 // Authentication failed or is not supported. #define DNS_OBJ_ERROR_UNDER_RUN -6750 // Less data than expected. #define DNS_OBJ_ERROR_OVER_RUN -6751 // More data than expected. #define DNS_OBJ_ERROR_TYPE_ERR -6756 // Incorrect or incompatible type (e.g. file, data, etc.). #define DNS_OBJ_ERROR_GENERIC_ERROR_END -6779 // Last generic error code (inclusive) //====================================================================================================================== // MARK: - DNS Message Common Values #ifndef MAX_ESCAPED_DOMAIN_NAME #define MAX_ESCAPED_DOMAIN_NAME 1009 #endif #ifndef MAX_DOMAIN_NAME #define MAX_DOMAIN_NAME 256 #endif #ifndef MAX_DOMAIN_LABEL #define MAX_DOMAIN_LABEL 63 #endif #define MAX_UNICAST_TTL_IN_SECONDS ((uint32_t)3600) // Record types #ifndef kDNSRecordType_Enum #define kDNSRecordType_Enum typedef enum { kDNSRecordType_Invalid = 0, kDNSRecordType_A = 1, kDNSRecordType_NS = 2, kDNSRecordType_MD = 3, kDNSRecordType_MF = 4, kDNSRecordType_CNAME = 5, kDNSRecordType_SOA = 6, kDNSRecordType_MB = 7, kDNSRecordType_MG = 8, kDNSRecordType_MR = 9, kDNSRecordType_NULL = 10, kDNSRecordType_WKS = 11, kDNSRecordType_PTR = 12, kDNSRecordType_HINFO = 13, kDNSRecordType_MINFO = 14, kDNSRecordType_MX = 15, kDNSRecordType_TXT = 16, kDNSRecordType_RP = 17, kDNSRecordType_AFSDB = 18, kDNSRecordType_X25 = 19, kDNSRecordType_ISDN = 20, kDNSRecordType_RT = 21, kDNSRecordType_NSAP = 22, kDNSRecordType_NSAP_PTR = 23, kDNSRecordType_SIG = 24, kDNSRecordType_KEY = 25, kDNSRecordType_PX = 26, kDNSRecordType_GPOS = 27, kDNSRecordType_AAAA = 28, kDNSRecordType_LOC = 29, kDNSRecordType_NXT = 30, kDNSRecordType_EID = 31, kDNSRecordType_NIMLOC = 32, kDNSRecordType_SRV = 33, kDNSRecordType_ATMA = 34, kDNSRecordType_NAPTR = 35, kDNSRecordType_KX = 36, kDNSRecordType_CERT = 37, kDNSRecordType_A6 = 38, kDNSRecordType_DNAME = 39, kDNSRecordType_SINK = 40, kDNSRecordType_OPT = 41, kDNSRecordType_APL = 42, kDNSRecordType_DS = 43, kDNSRecordType_SSHFP = 44, kDNSRecordType_IPSECKEY = 45, kDNSRecordType_RRSIG = 46, kDNSRecordType_NSEC = 47, kDNSRecordType_DNSKEY = 48, kDNSRecordType_DHCID = 49, kDNSRecordType_NSEC3 = 50, kDNSRecordType_NSEC3PARAM = 51, kDNSRecordType_TLSA = 52, kDNSRecordType_SMIMEA = 53, kDNSRecordType_HIP = 55, kDNSRecordType_NINFO = 56, kDNSRecordType_RKEY = 57, kDNSRecordType_TALINK = 58, kDNSRecordType_CDS = 59, kDNSRecordType_CDNSKEY = 60, kDNSRecordType_OPENPGPKEY = 61, kDNSRecordType_CSYNC = 62, kDNSRecordType_ZONEMD = 63, kDNSRecordType_SVCB = 64, kDNSRecordType_HTTPS = 65, kDNSRecordType_SPF = 99, kDNSRecordType_UINFO = 100, kDNSRecordType_UID = 101, kDNSRecordType_GID = 102, kDNSRecordType_UNSPEC = 103, kDNSRecordType_NID = 104, kDNSRecordType_L32 = 105, kDNSRecordType_L64 = 106, kDNSRecordType_LP = 107, kDNSRecordType_EUI48 = 108, kDNSRecordType_EUI64 = 109, kDNSRecordType_TKEY = 249, kDNSRecordType_TSIG = 250, kDNSRecordType_IXFR = 251, kDNSRecordType_AXFR = 252, kDNSRecordType_MAILB = 253, kDNSRecordType_MAILA = 254, kDNSRecordType_ANY = 255, kDNSRecordType_URI = 256, kDNSRecordType_CAA = 257, kDNSRecordType_AVC = 258, kDNSRecordType_DOA = 259, kDNSRecordType_AMTRELAY = 260, kDNSRecordType_TA = 32768, kDNSRecordType_DLV = 32769, kDNSRecordType_Reserved = 65535, } dns_record_type_t; #endif // #ifndef kDNSRecordType_Enum // Record class #ifndef kDNSClassType_Enum #define kDNSClassType_Enum typedef enum { kDNSClassType_INVALID = 0, kDNSClassType_IN = 1, kDNSClassType_CHAOS = 3 } dns_class_type_t; #endif //#ifndef kDNSClassType_Enum //====================================================================================================================== // MARK: - Resource Record Constants #ifndef NSEC3_FLAG_TYPE_ENUM #define NSEC3_FLAG_TYPE_ENUM // NSEC3 hash flags // Taken from https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml. typedef enum nsec3_flag_type { // Unassigned 0 - 6 NSEC3_FLAG_OPT_OUT = 0x01 } nsec3_flag_type_t; #endif #ifndef NSEC3_HASH_ALGORITHM_ENUM #define NSEC3_HASH_ALGORITHM_ENUM // NSEC3 hash algorithms // Taken from https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml. typedef enum nsec3_hash_algorithm_type { // Reserved 0 NSEC3_HASH_ALGORITHM_SHA_1 = 1 // Unassigned 2 - 255 } nsec3_hash_algorithm_type_t; #endif //====================================================================================================================== // MARK: - Functions /*! * @brief * Get the uint16_t integer from the network-byte-order bytes. * * @param bytes * The bytes that encode an uint16_t integer. * * @result * The uint16_t integer. */ uint16_t get_uint16_from_bytes(const uint8_t * NONNULL bytes); /*! * @brief * Get the uint32_t integer from the network-byte-order bytes. * * @param bytes * The bytes that encode an uint32_t integer. * * @result * The uint32_t integer. */ uint32_t get_uint32_from_bytes(const uint8_t * NONNULL bytes); /*! * @brief * Put the uint16_t integer into network-byte-order bytes. * * @param u16 * The uint16_t integer. * * @param ptr * The pointer to the buffer that stores the bytes in network byte order. */ void put_uint16_to_bytes(uint16_t u16, uint8_t * NULLABLE * NONNULL ptr); /*! * @brief * Put the uint32_t integer into network-byte-order bytes. * * @param u32 * The uint32_t integer. * * @param ptr * The pointer to the buffer that stores the bytes in network byte order. */ void put_uint32_to_bytes(uint32_t u32, uint8_t * NULLABLE * NONNULL ptr); /*! * @brief * Convert the bytes to its hex representation in C string. * * @param bytes * The bytes to be converted. * * @param len * The length of the bytes. * * @param buffer * The output buffer that holds the hex C string. * * @param buffer_len * The max size of the buffer. * * @result * If no error occurs, the next position of the hex C string end is returned. Otherwise, the value of buffer is returned. * * @discussion * To do conversion successfully, the length of the buffer has to be greater than 2 times of the bytes length. * */ char * NULLABLE put_hex_from_bytes(const uint8_t * NULLABLE bytes, size_t len, char * const NONNULL buffer, size_t buffer_len); /*! * @brief * Get the string description of the DNS record type. * * @param type * The DNS record type. * * @result * The string description. */ const char * NULLABLE dns_record_type_value_to_string(uint16_t type); /*! * @brief * Convert the integer error code to a string description. * * @param error * The error to convert. * * @result * The string description of the error. */ const char * NONNULL dns_obj_error_get_error_description(dns_obj_error_t error); #endif // DNS_OBJ_COMMON_H