/*
 * Part of DNS zone file validator `validns`.
 *
 * Copyright 2011-2014 Anton Berezin <tobez@tobez.org>
 * Modified BSD license.
 * (See LICENSE file in the distribution.)
 *
 */
#ifndef _RR_H
#define _RR_H 1

#define T_A     1
#define T_NS    2
#define T_CNAME 5
#define T_SOA   6
#define T_MB    7
#define T_MG    8
#define T_MR    9
#define T_PTR   12
#define T_HINFO 13
#define T_MINFO 14
#define T_MX    15
#define T_TXT   16
#define T_RP    17
#define T_AFSDB 18
#define T_X25   19
#define T_ISDN  20
#define T_RT    21
#define T_NSAP  22
#define T_PX    26
#define T_AAAA  28
#define T_LOC   29
#define T_SRV   33
#define T_NAPTR 35
#define T_KX    36
#define T_CERT  37
#define T_DNAME 39
#define T_DS    43
#define T_SSHFP 44
#define T_IPSECKEY  45
#define T_RRSIG 46
#define T_NSEC  47
#define T_DNSKEY    48
#define T_DHCID 49
#define T_NSEC3 50
#define T_NSEC3PARAM    51
#define T_TLSA  52
#define T_SMIMEA  53
#define T_CDS   59
#define T_CDNSKEY 60
#define T_SPF   99
#define T_NID   104
#define T_L32   105
#define T_L64   106
#define T_LP    107
#define T_CAA   257
#define T_DLV   32769
#define T_MAX   32769

#define ALG_DSA                  3
#define ALG_RSASHA1              5
#define ALG_DSA_NSEC3_SHA1       6
#define ALG_RSASHA1_NSEC3_SHA1   7
#define ALG_RSASHA256            8
#define ALG_RSASHA512           10
#define ALG_ECCGOST             12
#define ALG_ECDSAP256SHA256     13
#define ALG_ECDSAP384SHA384     14
#define ALG_ED25519             15
#define ALG_ED448               16
#define ALG_PRIVATEDNS         253
#define ALG_PRIVATEOID         254

#define ALG_UNSUPPORTED     0
#define ALG_DSA_FAMILY      1
#define ALG_RSA_FAMILY      2
#define ALG_PRIVATE_FAMILY  3
#define ALG_ECC_FAMILY      4

#define RRCAST(t) struct rr_ ## t *rr = (struct rr_ ## t *)rrv

struct cbtree;
extern struct cbtree zone_data;
extern char *zone_apex;
extern int zone_apex_l;

struct named_rr;
struct rr_set;
struct rr;

typedef struct rr* (*rr_parse_func)(char *, long, int, char *);
typedef char* (*rr_human_func)(struct rr*);
typedef struct binary_data (*rr_wire_func)(struct rr*);
typedef void* (*rr_validate_set_func)(struct rr_set*);
typedef void* (*rr_validate_func)(struct rr*);
struct rr_methods {
    rr_parse_func        rr_parse;
    rr_human_func        rr_human;
    rr_wire_func         rr_wire;
    rr_validate_set_func rr_validate_set;
    rr_validate_func     rr_validate;
};
extern struct rr_methods rr_methods[T_MAX+1];
extern struct rr_methods unknown_methods;
extern int rr_counts[T_MAX+1];

struct binary_data call_get_wired(struct rr *rr);
struct rr *rr_parse_any(char *name, long ttl, int type, char *s);
char* any_human(struct rr *rrv);
struct binary_data any_wirerdata(struct rr *rrv);

int name_belongs_to_zone(const char *name);
void validate_record(struct rr *rr);
void validate_zone(void);
struct rr *store_record(int rdtype, char *name, long ttl, void *rrptr);
int str2rdtype(char *rdtype, int *is_generic);
char *rdtype2str(int type);
struct named_rr *find_named_rr(char *name);
struct named_rr *find_next_named_rr(struct named_rr *named_rr);
struct rr_set *find_rr_set(int rdtype, char *name);
struct rr_set *find_rr_set_in_named_rr(struct named_rr *named_rr, int rdtype);
uint32_t get_rr_set_count(struct named_rr *named_rr);
struct binary_data name2wire_name(char *s);
int algorithm_type(int alg);
int extract_algorithm(char **s, char *what);

#define NAME_FLAG_APEX                  1
#define NAME_FLAG_HAS_RECORDS           2
#define NAME_FLAG_DELEGATION            4
#define NAME_FLAG_NOT_AUTHORITATIVE     8
#define NAME_FLAG_NSEC3_ONLY           16
#define NAME_FLAG_KIDS_WITH_RECORDS    32
#define NAME_FLAG_SIGNED_DELEGATION    64
#define NAME_FLAG_APEX_PARENT         128
#define NAME_FLAG_THIS_WITH_RECORDS   256
#define NAME_FLAG_CONTAINS_SLASH      512

struct named_rr
{
    char *name;
    void *rr_sets;

    int line;
    char *file_name;
    uint32_t flags;
    struct named_rr *parent;
};

struct rr_set
{
    struct rr* head;
    struct rr* tail;
    struct named_rr *named_rr;
    int rdtype;
    int count;
};

struct rr
{
    struct rr* next;
    struct rr* prev;
    struct rr_set *rr_set;

    int ttl;
    int rdtype;

    int line;
    int is_generic;
    char *file_name;
};

struct rr_any
{
    struct rr rr;
    struct binary_data data;
};

struct rr_a
{
    struct rr rr;
    struct in_addr address;
};
extern struct rr_methods a_methods;

struct rr_soa
{
    struct rr rr;
    uint32_t serial;
    int refresh, retry, expire, minimum;
    char *rname;
    char *mname;
};
extern struct rr_methods soa_methods;

struct rr_ns
{
    struct rr rr;
    char *nsdname;
};
extern struct rr_methods ns_methods;

struct rr_dhcid
{
    struct rr rr;
    int id_type;
    int digest_type;
    struct binary_data digest;
};
extern struct rr_methods dhcid_methods;

struct rr_txt_segment {
    struct binary_data txt;
    struct rr_txt_segment *next;
};
struct rr_txt
{
    struct rr rr;
    int count;
    struct rr_txt_segment *txt;
};
extern struct rr_methods txt_methods;

struct rr_tlsa_smimea
{
    struct rr rr;
    uint8_t cert_usage;
    uint8_t selector;
    uint8_t matching_type;
    struct binary_data association_data;
};
extern struct rr_methods tlsa_methods;
extern struct rr_methods smimea_methods;

struct rr_ipseckey
{
    struct rr rr;
    uint8_t precedence;
    uint8_t gateway_type;
    uint8_t algorithm;
    union {
        char           *gateway_none; /* gateway_type == 0 */
        struct in_addr  gateway_ipv4; /* gateway_type == 1 */
        struct in6_addr gateway_ipv6; /* gateway_type == 2 */
        char           *gateway_name; /* gateway_type == 3 */
    } gateway;
    struct binary_data public_key;
};
extern struct rr_methods ipseckey_methods;

struct rr_nid
{
    struct rr rr;
    uint16_t preference;
    uint64_t node_id;
};
extern struct rr_methods nid_methods;

struct rr_l32
{
    struct rr rr;
    uint16_t preference;
    uint32_t locator32;
};
extern struct rr_methods l32_methods;

struct rr_l64
{
    struct rr rr;
    uint16_t preference;
    uint64_t locator64;
};
extern struct rr_methods l64_methods;

struct rr_lp
{
    struct rr rr;
    uint16_t preference;
    char *fqdn;
};
extern struct rr_methods lp_methods;

struct rr_naptr
{
    struct rr rr;
    uint16_t order;
    uint16_t preference;
    struct binary_data flags;
    struct binary_data services;
    struct binary_data regexp;
    char *replacement;
};
extern struct rr_methods naptr_methods;

struct rr_nsec
{
    struct rr rr;
    char *next_domain;
    struct binary_data type_bitmap;
};
extern struct rr_methods nsec_methods;

void validate_nsec_chain(void);

struct rr_nsec3
{
    struct rr rr;
    uint8_t hash_algorithm;
    uint8_t flags;
    uint16_t iterations;
    struct binary_data salt;
    struct binary_data next_hashed_owner;
    struct binary_data type_bitmap;
    struct binary_data this_hashed_name;
    struct named_rr *corresponding_name;
    struct rr_nsec3 *next_nsec3;
};
extern struct rr_methods nsec3_methods;

struct rr_nsec3param
{
    struct rr rr;
    uint8_t hash_algorithm;
    uint8_t flags;
    uint16_t iterations;
    struct binary_data salt;
};
extern struct rr_methods nsec3param_methods;
extern struct rr *nsec3param;

struct rr_rrsig
{
    struct rr rr;
    uint16_t type_covered;
    int algorithm;
    int labels;
    int orig_ttl;
    uint32_t sig_expiration;
    uint32_t sig_inception;
    uint16_t key_tag;
    char *signer;
    struct binary_data signature;
};
extern struct rr_methods rrsig_methods;

struct rr_srv
{
    struct rr rr;
    uint16_t priority;
    uint16_t weight;
    uint16_t port;
    char *target;
};
extern struct rr_methods srv_methods;

struct rr_cname
{
    struct rr rr;
    char *cname;
};
extern struct rr_methods cname_methods;

struct rr_mb
{
    struct rr rr;
    char *madname;
};
extern struct rr_methods mb_methods;

struct rr_mg
{
    struct rr rr;
    char *mgmname;
};
extern struct rr_methods mg_methods;

struct rr_minfo
{
    struct rr rr;
    char *rmailbx;
    char *emailbx;
};
extern struct rr_methods minfo_methods;

struct rr_mr
{
    struct rr rr;
    char *newname;
};
extern struct rr_methods mr_methods;

struct rr_dname
{
    struct rr rr;
    char *target;
};
extern struct rr_methods dname_methods;

struct rr_aaaa
{
    struct rr rr;
    struct in6_addr address;
};
extern struct rr_methods aaaa_methods;

struct rr_mx
{
    struct rr rr;
    int   preference;
    char *exchange;
};
extern struct rr_methods mx_methods;

struct rr_rt
{
    struct rr rr;
    int   preference;
    char *intermediate_host;
};
extern struct rr_methods rt_methods;

struct rr_afsdb
{
    struct rr rr;
    int   subtype;
    char *hostname;
};
extern struct rr_methods afsdb_methods;

struct rr_x25
{
    struct rr rr;
    struct binary_data psdn_address;
};
extern struct rr_methods x25_methods;

struct rr_isdn
{
    struct rr rr;
    struct binary_data isdn_address;
    struct binary_data sa;
    int sa_present;
};
extern struct rr_methods isdn_methods;

struct rr_px
{
    struct rr rr;
    int   preference;
    char *map822;
    char *mapx400;
};
extern struct rr_methods px_methods;

struct rr_kx
{
    struct rr rr;
    int   preference;
    char *exchanger;
};
extern struct rr_methods kx_methods;

struct rr_dnskey
{
    struct rr rr;
    uint16_t flags;
    uint8_t protocol;
    uint8_t algorithm;
    struct binary_data pubkey;
    /* calculated */
    uint16_t key_tag;
    int pkey_built;
    void *pkey;
    /* extras */
    int key_type;
    struct rr_dnskey *next_key;
};
extern struct rr_methods dnskey_methods;
extern struct rr_methods cdnskey_methods;

#define KEY_TYPE_UNUSED 0
#define KEY_TYPE_KSK    1
#define KEY_TYPE_ZSK    2

int dnskey_build_pkey(struct rr_dnskey *rr);
void dnskey_ksk_policy_check(void);

struct rr_ds
{
    struct rr rr;
    uint16_t key_tag;
    uint8_t algorithm;
    uint8_t digest_type;
    struct binary_data digest;
};
extern struct rr_methods ds_methods;
extern struct rr_methods cds_methods;

struct rr_dlv
{
    struct rr rr;
    uint16_t key_tag;
    uint8_t algorithm;
    uint8_t digest_type;
    struct binary_data digest;
};
extern struct rr_methods dlv_methods;

struct rr_nsap
{
    struct rr rr;
    struct binary_data data;
};
extern struct rr_methods nsap_methods;

struct rr_hinfo
{
    struct rr rr;
    struct binary_data cpu;
    struct binary_data os;
};
extern struct rr_methods hinfo_methods;

struct rr_rp
{
    struct rr rr;
    char *mbox_dname;
    char *txt_dname;
};
extern struct rr_methods rp_methods;

struct rr_loc
{
    struct rr rr;
    uint8_t version;
    uint8_t size;
    uint8_t horiz_pre;
    uint8_t vert_pre;
    uint32_t latitude;
    uint32_t longitude;
    uint32_t altitude;
};
extern struct rr_methods loc_methods;

struct rr_ptr
{
    struct rr rr;
    char *ptrdname;
};
extern struct rr_methods ptr_methods;

struct rr_sshfp
{
    struct rr rr;
    uint8_t algorithm;
    uint8_t fp_type;
    struct binary_data fingerprint;
};
extern struct rr_methods sshfp_methods;

struct rr_spf
{
    struct rr rr;
    int count;
    struct binary_data spf[1];
};
extern struct rr_methods spf_methods;

struct rr_cert
{
    struct rr rr;
    uint16_t type;
    uint16_t key_tag;
    int algorithm;
    struct binary_data certificate;
};
extern struct rr_methods cert_methods;

struct rr_caa
{
    struct rr rr;
    uint8_t flags;
    struct binary_data tag;
    struct binary_data value;
};
extern struct rr_methods caa_methods;

extern struct rr_nsec3 *first_nsec3;
extern struct rr_nsec3 *latest_nsec3;

extern void verify_all_keys(void);
extern void* nsec3_validate(struct rr *rrv);
extern void *remember_nsec3(char *name, struct rr_nsec3 *rr);
extern void perform_remaining_nsec3checks(void);
extern void *check_typemap(struct binary_data type_bitmap, struct named_rr *named_rr, struct rr *reference_rr);

#endif
