/*
 * Copyright (c) 2008-2026 OARC, Inc.
 * Copyright (c) 2007-2008, Internet Systems Consortium, Inc.
 * Copyright (c) 2003-2007, The Measurement Factory, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __dsc_dns_message_h
#define __dsc_dns_message_h

typedef struct transport_message transport_message;
typedef struct dns_message       dns_message;

#include "inX_addr.h"
#include "dataset_opt.h"
#include "md_array.h"

#include <stdio.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif

#define MAX_QNAME_SZ 512

enum transport_encryption {
    TRANSPORT_ENCRYPTION_UNENCRYPTED = 0,
    TRANSPORT_ENCRYPTION_DOT         = 1,
    TRANSPORT_ENCRYPTION_DOH         = 2,
    TRANSPORT_ENCRYPTION_DNSCrypt    = 3,
    TRANSPORT_ENCRYPTION_DOQ         = 4,
};

struct transport_message {
    struct timeval            ts;
    inX_addr                  src_ip_addr;
    inX_addr                  dst_ip_addr;
    unsigned short            src_port;
    unsigned short            dst_port;
    unsigned char             ip_version;
    unsigned char             proto;
    enum transport_encryption encryption;
};

struct dns_message {
    transport_message* tm;
    unsigned short     id;
    unsigned short     qtype;
    unsigned short     qclass;
    unsigned short     msglen;
    char               qname[MAX_QNAME_SZ];
    const char*        tld;
    unsigned char      opcode;
    unsigned char      rcode;
    unsigned int       malformed : 1;
    unsigned int       qr : 1;
    unsigned int       rd : 1; /* set if RECUSION DESIRED bit is set */
    unsigned int       aa : 1; /* set if AUTHORITATIVE ANSWER bit is set */
    unsigned int       tc : 1; /* set if TRUNCATED RESPONSE bit is set */
    unsigned int       ad : 1; /* set if AUTHENTIC DATA bit is set */
    struct
    {
        unsigned int   found : 1; /* set if we found an OPT RR */
        unsigned int   DO : 1; /* set if DNSSEC DO bit is set */
        unsigned char  version; /* version field from OPT RR */
        unsigned short bufsiz; /* class field from OPT RR */

        // bitmap of found EDNS(0) options
        struct {
            unsigned int cookie : 1;
            unsigned int nsid : 1;
            unsigned int ede : 1;
            unsigned int ecs : 1;
        } option;

        // cookie rfc 7873
        struct {
            const u_char*  client; // pointer to 8 byte client part
            const u_char*  server; // pointer to server part, may be null
            unsigned short server_len; // length of server part, if any
        } cookie;

        // nsid rfc 5001
        struct {
            const u_char*  data; // pointer to nsid payload, may be null
            unsigned short len; // length of nsid, if any
        } nsid;

        // extended error codes rfc 8914
        struct {
            unsigned short code;
            const u_char*  text; // pointer to EXTRA-TEXT, may be null
            unsigned short len; // length of text, if any
        } ede;

        // client subnet rfc 7871
        struct {
            unsigned short family;
            unsigned char  source_prefix;
            unsigned char  scope_prefix;
            const u_char*  address; // pointer to address, may be null
            unsigned short len; // length of address, if any
        } ecs;
    } edns;
};

void        dns_message_handle(dns_message* m);
int         dns_message_add_array(const char* name, const char* fn, const char* fi, const char* sn, const char* si, const char* f, dataset_opt opts);
void        dns_message_flush_arrays(void);
void        dns_message_report(FILE* fp, md_array_printer* printer);
void        dns_message_clear_arrays(void);
const char* dns_message_QnameToNld(const char* qname, int nld);
const char* dns_message_tld(dns_message* m);
void        dns_message_filters_init(void);
void        dns_message_indexers_init(void);
int         add_qname_filter(const char* name, const char* pat);

void indexer_want_edns(void);
void indexer_want_edns_options(void);

#include <arpa/nameser.h>
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
#include <arpa/nameser_compat.h>
#endif

/* Make sure DNS types are defined */

/* autogenerated by mk-iana-dns-types.sh at 2026-06-10T09:20:05+00:00 */
#ifndef T_A
#define T_A 1
#endif
#ifndef T_NS
#define T_NS 2
#endif
#ifndef T_MD
#define T_MD 3
#endif
#ifndef T_MF
#define T_MF 4
#endif
#ifndef T_CNAME
#define T_CNAME 5
#endif
#ifndef T_SOA
#define T_SOA 6
#endif
#ifndef T_MB
#define T_MB 7
#endif
#ifndef T_MG
#define T_MG 8
#endif
#ifndef T_MR
#define T_MR 9
#endif
#ifndef T_NULL
#define T_NULL 10
#endif
#ifndef T_WKS
#define T_WKS 11
#endif
#ifndef T_PTR
#define T_PTR 12
#endif
#ifndef T_HINFO
#define T_HINFO 13
#endif
#ifndef T_MINFO
#define T_MINFO 14
#endif
#ifndef T_MX
#define T_MX 15
#endif
#ifndef T_TXT
#define T_TXT 16
#endif
#ifndef T_RP
#define T_RP 17
#endif
#ifndef T_AFSDB
#define T_AFSDB 18
#endif
#ifndef T_X25
#define T_X25 19
#endif
#ifndef T_ISDN
#define T_ISDN 20
#endif
#ifndef T_RT
#define T_RT 21
#endif
#ifndef T_NSAP
#define T_NSAP 22
#endif
#ifndef T_SIG
#define T_SIG 24
#endif
#ifndef T_KEY
#define T_KEY 25
#endif
#ifndef T_PX
#define T_PX 26
#endif
#ifndef T_GPOS
#define T_GPOS 27
#endif
#ifndef T_AAAA
#define T_AAAA 28
#endif
#ifndef T_LOC
#define T_LOC 29
#endif
#ifndef T_NXT
#define T_NXT 30
#endif
#ifndef T_EID
#define T_EID 31
#endif
#ifndef T_NIMLOC
#define T_NIMLOC 32
#endif
#ifndef T_SRV
#define T_SRV 33
#endif
#ifndef T_ATMA
#define T_ATMA 34
#endif
#ifndef T_NAPTR
#define T_NAPTR 35
#endif
#ifndef T_KX
#define T_KX 36
#endif
#ifndef T_CERT
#define T_CERT 37
#endif
#ifndef T_A6
#define T_A6 38
#endif
#ifndef T_DNAME
#define T_DNAME 39
#endif
#ifndef T_SINK
#define T_SINK 40
#endif
#ifndef T_OPT
#define T_OPT 41
#endif
#ifndef T_APL
#define T_APL 42
#endif
#ifndef T_DS
#define T_DS 43
#endif
#ifndef T_SSHFP
#define T_SSHFP 44
#endif
#ifndef T_IPSECKEY
#define T_IPSECKEY 45
#endif
#ifndef T_RRSIG
#define T_RRSIG 46
#endif
#ifndef T_NSEC
#define T_NSEC 47
#endif
#ifndef T_DNSKEY
#define T_DNSKEY 48
#endif
#ifndef T_DHCID
#define T_DHCID 49
#endif
#ifndef T_NSEC3
#define T_NSEC3 50
#endif
#ifndef T_NSEC3PARAM
#define T_NSEC3PARAM 51
#endif
#ifndef T_TLSA
#define T_TLSA 52
#endif
#ifndef T_SMIMEA
#define T_SMIMEA 53
#endif
#ifndef T_HIP
#define T_HIP 55
#endif
#ifndef T_NINFO
#define T_NINFO 56
#endif
#ifndef T_RKEY
#define T_RKEY 57
#endif
#ifndef T_TALINK
#define T_TALINK 58
#endif
#ifndef T_CDS
#define T_CDS 59
#endif
#ifndef T_CDNSKEY
#define T_CDNSKEY 60
#endif
#ifndef T_OPENPGPKEY
#define T_OPENPGPKEY 61
#endif
#ifndef T_CSYNC
#define T_CSYNC 62
#endif
#ifndef T_ZONEMD
#define T_ZONEMD 63
#endif
#ifndef T_SVCB
#define T_SVCB 64
#endif
#ifndef T_HTTPS
#define T_HTTPS 65
#endif
#ifndef T_DSYNC
#define T_DSYNC 66
#endif
#ifndef T_HHIT
#define T_HHIT 67
#endif
#ifndef T_BRID
#define T_BRID 68
#endif
#ifndef T_SPF
#define T_SPF 99
#endif
#ifndef T_UINFO
#define T_UINFO 100
#endif
#ifndef T_UID
#define T_UID 101
#endif
#ifndef T_GID
#define T_GID 102
#endif
#ifndef T_UNSPEC
#define T_UNSPEC 103
#endif
#ifndef T_NID
#define T_NID 104
#endif
#ifndef T_L32
#define T_L32 105
#endif
#ifndef T_L64
#define T_L64 106
#endif
#ifndef T_LP
#define T_LP 107
#endif
#ifndef T_EUI48
#define T_EUI48 108
#endif
#ifndef T_EUI64
#define T_EUI64 109
#endif
#ifndef T_NXNAME
#define T_NXNAME 128
#endif
#ifndef T_TKEY
#define T_TKEY 249
#endif
#ifndef T_TSIG
#define T_TSIG 250
#endif
#ifndef T_IXFR
#define T_IXFR 251
#endif
#ifndef T_AXFR
#define T_AXFR 252
#endif
#ifndef T_MAILB
#define T_MAILB 253
#endif
#ifndef T_MAILA
#define T_MAILA 254
#endif
#ifndef T_ANY
#define T_ANY 255
#endif
#ifndef T_URI
#define T_URI 256
#endif
#ifndef T_CAA
#define T_CAA 257
#endif
#ifndef T_AVC
#define T_AVC 258
#endif
#ifndef T_DOA
#define T_DOA 259
#endif
#ifndef T_AMTRELAY
#define T_AMTRELAY 260
#endif
#ifndef T_RESINFO
#define T_RESINFO 261
#endif
#ifndef T_WALLET
#define T_WALLET 262
#endif
#ifndef T_CLA
#define T_CLA 263
#endif
#ifndef T_IPN
#define T_IPN 264
#endif
#ifndef T_TA
#define T_TA 32768
#endif
#ifndef T_DLV
#define T_DLV 32769
#endif

/* DNS classes that may be missing */

#ifndef C_CHAOS
#define C_CHAOS 3
#endif
#ifndef C_NONE
#define C_NONE 254
#endif

#endif /* __dsc_dns_message_h */
