/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ #pragma once /*** This file is part of systemd. Copyright 2014 Lennart Poettering systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ #include #include "bitmap.h" #include "dns-type.h" #include "hashmap.h" #include "in-addr-util.h" #include "list.h" typedef struct DnsResourceKey DnsResourceKey; typedef struct DnsResourceRecord DnsResourceRecord; typedef struct DnsTxtItem DnsTxtItem; /* DNS record classes, see RFC 1035 */ enum { DNS_CLASS_IN = 0x01, DNS_CLASS_ANY = 0xFF, _DNS_CLASS_MAX, _DNS_CLASS_INVALID = -1 }; /* DNSKEY RR flags */ #define DNSKEY_FLAG_ZONE_KEY (UINT16_C(1) << 8) #define DNSKEY_FLAG_SEP (UINT16_C(1) << 0) /* mDNS RR flags */ #define MDNS_RR_CACHE_FLUSH (UINT16_C(1) << 15) /* DNSSEC algorithm identifiers, see * http://tools.ietf.org/html/rfc4034#appendix-A.1 and * https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */ enum { DNSSEC_ALGORITHM_RSAMD5 = 1, DNSSEC_ALGORITHM_DH, DNSSEC_ALGORITHM_DSA, DNSSEC_ALGORITHM_ECC, DNSSEC_ALGORITHM_RSASHA1, DNSSEC_ALGORITHM_DSA_NSEC3_SHA1, DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1, DNSSEC_ALGORITHM_RSASHA256 = 8, /* RFC 5702 */ DNSSEC_ALGORITHM_RSASHA512 = 10, /* RFC 5702 */ DNSSEC_ALGORITHM_INDIRECT = 252, DNSSEC_ALGORITHM_PRIVATEDNS, DNSSEC_ALGORITHM_PRIVATEOID, _DNSSEC_ALGORITHM_MAX_DEFINED }; /* DNSSEC digest identifiers, see * https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */ enum { DNSSEC_DIGEST_SHA1 = 1, DNSSEC_DIGEST_SHA256 = 2, _DNSSEC_DIGEST_MAX_DEFINED }; struct DnsResourceKey { unsigned n_ref; uint16_t class, type; char *_name; /* don't access directy, use DNS_RESOURCE_KEY_NAME()! */ bool cache_flush:1; }; /* Creates a temporary resource key. This is only useful to quickly * look up something, without allocating a full DnsResourceKey object * for it. Note that it is not OK to take references to this kind of * resource key object. */ #define DNS_RESOURCE_KEY_CONST(c, t, n) \ ((DnsResourceKey) { \ .n_ref = (unsigned) -1, \ .class = c, \ .type = t, \ ._name = (char*) n, \ }) struct DnsTxtItem { size_t length; LIST_FIELDS(DnsTxtItem, items); uint8_t data[]; }; struct DnsResourceRecord { unsigned n_ref; DnsResourceKey *key; uint32_t ttl; bool unparseable:1; bool wire_format_canonical:1; void *wire_format; size_t wire_format_size; size_t wire_format_rdata_offset; union { struct { void *data; size_t size; } generic, opt; struct { uint16_t priority; uint16_t weight; uint16_t port; char *name; } srv; struct { char *name; } ptr, ns, cname, dname; struct { char *cpu; char *os; } hinfo; struct { DnsTxtItem *items; } txt, spf; struct { struct in_addr in_addr; } a; struct { struct in6_addr in6_addr; } aaaa; struct { char *mname; char *rname; uint32_t serial; uint32_t refresh; uint32_t retry; uint32_t expire; uint32_t minimum; } soa; struct { uint16_t priority; char *exchange; } mx; struct { uint8_t version; uint8_t size; uint8_t horiz_pre; uint8_t vert_pre; uint32_t latitude; uint32_t longitude; uint32_t altitude; } loc; struct { uint16_t key_tag; uint8_t algorithm; uint8_t digest_type; void *digest; size_t digest_size; } ds; /* https://tools.ietf.org/html/rfc4255#section-3.1 */ struct { uint8_t algorithm; uint8_t fptype; void *fingerprint; size_t fingerprint_size; } sshfp; /* http://tools.ietf.org/html/rfc4034#section-2.1 */ struct { uint16_t flags; uint8_t protocol; uint8_t algorithm; void* key; size_t key_size; } dnskey; /* http://tools.ietf.org/html/rfc4034#section-3.1 */ struct { uint16_t type_covered; uint8_t algorithm; uint8_t labels; uint32_t original_ttl; uint32_t expiration; uint32_t inception; uint16_t key_tag; char *signer; void *signature; size_t signature_size; } rrsig; /* https://tools.ietf.org/html/rfc4034#section-4.1 */ struct { char *next_domain_name; Bitmap *types; } nsec; struct { uint8_t algorithm; uint8_t flags; uint16_t iterations; void *salt; size_t salt_size; void *next_hashed_name; size_t next_hashed_name_size; Bitmap *types; } nsec3; }; }; static inline const char* DNS_RESOURCE_KEY_NAME(const DnsResourceKey *key) { if (_unlikely_(!key)) return NULL; if (key->_name) return key->_name; return (char*) key + sizeof(DnsResourceKey); } DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name); DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname); int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name); DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name); DnsResourceKey* dns_resource_key_ref(DnsResourceKey *key); DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key); bool dns_resource_key_is_address(const DnsResourceKey *key); int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b); int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr, const char *search_domain); int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr, const char *search_domain); int dns_resource_key_to_string(const DnsResourceKey *key, char **ret); DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref); static inline bool dns_key_is_shared(const DnsResourceKey *key) { return IN_SET(key->type, DNS_TYPE_PTR); } DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key); DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name); DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr); DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr); int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name); int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name); int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b); int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret); DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref); int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical); DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i); bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b); const char *dns_class_to_string(uint16_t type); int dns_class_from_string(const char *name, uint16_t *class); extern const struct hash_ops dns_resource_key_hash_ops; const char* dnssec_algorithm_to_string(int i) _const_; int dnssec_algorithm_from_string(const char *s) _pure_; const char *dnssec_digest_to_string(int i) _const_; int dnssec_digest_from_string(const char *s) _pure_;