/* * Copyright (c) 2022 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_RR_H #define DNS_OBJ_RR_H //====================================================================================================================== // MARK: - Headers #include "dns_obj.h" #include "dns_obj_domain_name.h" #include "dns_common.h" #include #include #include "nullability.h" //====================================================================================================================== // MARK: - Object Reference Definition DNS_OBJECT_TYPEDEF_OPAQUE_POINTER(rr); //====================================================================================================================== // MARK: - The Resource Record and Its Subkind. // All the subkind of resource record object needs to add `DNS_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, )` // to let the subkind be able to use the resource record method declared here. typedef union { DNS_OBJECT_DECLARE_SUPPORTED_OBJECT(rr); DNS_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, cname); DNS_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, soa); DNS_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, srv); DNS_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, ds); DNS_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, nsec); DNS_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, rrsig); DNS_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, dnskey); DNS_OBJECT_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, nsec3); } dns_obj_rr_any_t __attribute__((__transparent_union__)); typedef union { DNS_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT(rr); DNS_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, nsec); DNS_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, dnskey); DNS_OBJECT_ARRAY_DECLARE_SUPPORTED_OBJECT_SUBKIND(rr, nsec3); } dns_objs_rr_any_t __attribute__((__transparent_union__)); //====================================================================================================================== // MARK: - Object Methods /*! * @brief * Create a resource record object. * * @param name * The name of the resource record in domain name labels. * * @param type * The type of the record. * * @param class * The class of the record. * * @param rdata * The pointer to the rdata of the record, when it is NULL, it is negative response. * * @param rdata_len * The length of the rdata, when rdata is NULL, it should be zero. * * @param allocate_memory * The boolean value to indicate whether to allocate new memory and copy all rdata from the memory region pointed by name, * rdata. If it is false, the caller is required to ensure that name and rdata are always valid during the life time * of this resource record object. * * @param out_error * The pointer to the error value indicates the success of the function call or the error encountered. * * @result * The resource record object created, or NULL if error happens during creation. out_error will be set to the error encountered if it is not NULL. */ dns_obj_rr_t NULLABLE dns_obj_rr_create(const uint8_t * NONNULL name, uint16_t type, uint16_t class, const uint8_t * NULLABLE rdata, uint16_t rdata_len, bool allocate_memory, dns_obj_error_t * NULLABLE out_error); /*! * @brief * Get the name of the resource record in domain name object format. * * @param record * The resource record object. * * @result * The domain name object. It is ensured to be valid as long as the resource record object is valid. */ dns_obj_domain_name_t NONNULL dns_obj_rr_get_name(dns_obj_rr_any_t record); /*! * @brief * Get the name of the resource record in domain name labels format. * * @param record * The resource record object. * * @result * The domain name labels. If allocate_memory is set to false, the pointer returned will be the same as the one when creating this resource * record. */ const uint8_t * NONNULL dns_obj_rr_get_name_in_labels(dns_obj_rr_any_t record); /*! * @brief * Get the type of the resource record. * * @param record * The resource record object. * * @result * The DNS record type. */ uint16_t dns_obj_rr_get_type(dns_obj_rr_any_t record); /*! * @brief * Get the class of the resource record. * * @param record * The resource record object. * * @result * The DNS record class. */ uint16_t dns_obj_rr_get_class(dns_obj_rr_any_t record); /*! * @brief * Get the rdata length of the resource record. * * @param record * The resource record object. * * @result * The rdata length. */ uint16_t dns_obj_rr_get_rdata_len(dns_obj_rr_any_t record); /*! * @brief * Get the rdata pointer associated with this resource record object. * * @param record * The resource record object. * * @result * The pointer to the rdata. If allocate_memory is set to false, the pointer returned will be the same as the one when creating this resource * record. */ const uint8_t * NULLABLE dns_obj_rr_get_rdata(dns_obj_rr_any_t record); /*! * @brief * Get the TTL of the resource record. * * @param record * The resource record object. * * @result * The TTL in seconds. */ uint32_t dns_obj_rr_get_ttl(dns_obj_rr_any_t record); /*! * @brief * Get the signed data of the resource record object that can be used to sort the object in canonical order or reconstruct the signed data for DNSSEC * validation. * * @param record * The resource record object. * * @result * The pointer to the signed data. This allocated memory region can be released by calling dns_obj_rr_clear_comparison_attributes(). * * @discussion * Note that dns_obj_rr_set_comparison_attributes() has to be called before calling this function since the signed data needs the RRSIG * values to be calculated correctly. */ const uint8_t * NULLABLE dns_obj_rr_get_signed_data(dns_obj_rr_any_t record); /*! * @brief * Get the length of the signed data of the resource record object. * * @param record * The resource record object. * * @result * The length of the signed data. */ size_t dns_obj_rr_get_signed_data_len(dns_obj_rr_any_t record); /*! * @brief * Get an allocated string description of the corresponding resource record object's rdata. The format follows what is described in: * https://datatracker.ietf.org/doc/html/rfc8499#section-5 * * @param record * The resource record object. * * @param out_error * The pointer to the error value indicates the success of the function call or the error encountered. * * @result * The string description of the rdata if no error occurs. Otherwise, NULL will be returned, if out_error is non-null, an error code * will be set to *out_error. * * @discussion * This function returns an allocated C string, the caller is responsible for releasing it. */ char * NULLABLE dns_obj_rr_copy_rdata_rfc_description(dns_obj_rr_any_t record, dns_obj_error_t * NULLABLE out_error); /*! * @brief * Set the Original TTL and RRSIG labels value for the resource record object so that it can be comparable. dns_obj_rr_get_signed_data * also requires this function call because the signed data contains these two values. * * @param record * The resource record object * * @param original_ttl * The original TTL value of the RRSIG that covers this resource record. * * @param rrsig_labels * The labels value of the RRSIG that covers this resource record. */ void dns_obj_rr_set_comparison_attributes(dns_obj_rr_any_t record, uint32_t original_ttl, uint8_t rrsig_labels); /*! * @brief * Clear the comparison attributes set by dns_obj_rr_set_comparison_attributes(), also free the memory allocated for the signed data returned * by dns_obj_rr_get_signed_data(). * * @param record * The resource record object. */ void dns_obj_rr_clear_comparison_attributes(dns_obj_rr_any_t record); /*! * @brief * Set the Original TTL and RRSIG labels value for the resource record objects so that they can be comparable. dns_obj_rr_get_signed_data * also requires this function call because the signed data of the resource record objects contains these two values. * * @param records * The resource record objects array. * * @param original_ttl * The original TTL value of the RRSIG that covers this resource record. * * @param rrsig_labels * The labels value of the RRSIG that covers this resource record. */ void dns_obj_rrs_set_comparison_attributes(dns_objs_rr_any_t records, size_t rr_count, uint32_t original_ttl, uint8_t rrsig_labels); /*! * @brief * Clear the comparison attributes set by dns_obj_rrs_set_comparison_attributes(), also free the memory allocated for the signed data returned * by dns_obj_rr_get_signed_data(). * * @param records * The resource record objects array. */ void dns_obj_rrs_clear_comparison_attributes(dns_objs_rr_any_t records, size_t rr_count); /*! * @brief * Check if the resource record object is equal to a raw record with name, type and rdata. * * @param record * The resource record object to be checked. * * @param name * The name of the record. * * @param type * The type of the record. * * @param class * The class of the record. * * @param rdata * The pointer to the rdata. * * @param rdata_len * The length of the rdata. * * @result * True, if they are equal, otherwise, false. */ bool dns_obj_rr_equal_to_raw_data(dns_obj_rr_any_t record, const uint8_t * NONNULL name, uint16_t type, uint16_t class, const uint8_t * NULLABLE rdata, uint16_t rdata_len); /*! * @brief * Check if the resource records in the array come from the same RRSET. * * @param records * The resource record objects array. * * @param count * The number of records in the array. * * @result * True if they come from the same RRSET, otherwise, false. */ bool dns_obj_rrs_belong_to_one_rrset(dns_objs_rr_any_t records, size_t count); #endif // DNS_OBJ_RR_H