/** @file * @brief IRC resolver API. * @version $Id: res.h 1823 2007-08-09 03:41:18Z entrope $ */ #ifndef INCLUDED_res_h #define INCLUDED_res_h #ifndef INCLUDED_config_h #include "config.h" #endif #ifndef INCLUDED_sys_types_h #include #define INCLUDED_sys_types_h #endif #ifndef INCLUDED_sys_socket_h #include #define INCLUDED_sys_socket_h #endif #include #ifndef INCLUDED_netinet_in_h #include #define INCLUDED_netinet_in_h #endif #ifdef HAVE_STDINT_H #ifndef INCLUDED_stdint_h #include #define INCLUDED_stdint_h #endif #endif struct Client; struct StatDesc; /* Here we define some values lifted from nameser.h */ #define NS_INT16SZ 2 /**< Size of a 16-bit value. */ #define NS_INT32SZ 4 /**< Size of a 32-bit value. */ #define NS_CMPRSFLGS 0xc0 /**< Prefix flags that indicate special types */ #define NS_MAXCDNAME 255 /**< Maximum length of a compressed domain name. */ #define QUERY 0 /**< Forward (normal) DNS query operation. */ #define NO_ERRORS 0 /**< No errors processing a query. */ #define SERVFAIL 2 /**< Server error while processing a query. */ #define NXDOMAIN 3 /**< Domain name in query does not exist. */ #define T_A 1 /**< Hostname -> IPv4 query type. */ #define T_AAAA 28 /**< Hostname -> IPv6 query type. */ #define T_PTR 12 /**< IP(v4 or v6) -> hostname query type. */ #define T_CNAME 5 /**< Canonical name resolution query type. */ #define C_IN 1 /**< Internet query class. */ #define QFIXEDSZ 4 /**< Length of fixed-size part of query. */ #define HFIXEDSZ 12 /**< Length of fixed-size DNS header. */ /** Structure to store an IP address. */ struct irc_in_addr { unsigned short in6_16[8]; /**< IPv6 encoded parts, little-endian. */ }; /** Structure to store an IP address and port number. */ struct irc_sockaddr { struct irc_in_addr addr; /**< IP address. */ unsigned short port; /**< Port number, host-endian. */ }; /** DNS callback function signature. */ typedef void (*dns_callback_f)(void *vptr, const struct irc_in_addr *addr, const char *h_name); /** DNS query and response header. */ typedef struct { unsigned id :16; /**< query identification number */ #ifdef WORDS_BIGENDIAN /* fields in third byte */ unsigned qr: 1; /**< response flag */ unsigned opcode: 4; /**< purpose of message */ unsigned aa: 1; /**< authoritive answer */ unsigned tc: 1; /**< truncated message */ unsigned rd: 1; /**< recursion desired */ /* fields in fourth byte */ unsigned ra: 1; /**< recursion available */ unsigned unused :1; /**< unused bits (MBZ as of 4.9.3a3) */ unsigned ad: 1; /**< authentic data from named */ unsigned cd: 1; /**< checking disabled by resolver */ unsigned rcode :4; /**< response code */ #else /* fields in third byte */ unsigned rd :1; /**< recursion desired */ unsigned tc :1; /**< truncated message */ unsigned aa :1; /**< authoritive answer */ unsigned opcode :4; /**< purpose of message */ unsigned qr :1; /**< response flag */ /* fields in fourth byte */ unsigned rcode :4; /**< response code */ unsigned cd: 1; /**< checking disabled by resolver */ unsigned ad: 1; /**< authentic data from named */ unsigned unused :1; /**< unused bits (MBZ as of 4.9.3a3) */ unsigned ra :1; /**< recursion available */ #endif /* remaining bytes */ unsigned qdcount :16; /**< number of question entries */ unsigned ancount :16; /**< number of answer entries */ unsigned nscount :16; /**< number of authority entries */ unsigned arcount :16; /**< number of resource entries */ } HEADER; extern void restart_resolver(void); extern void clear_nameservers(void); extern void add_nameserver(const char *ipaddr); extern void add_local_domain(char *hname, size_t size); extern size_t cres_mem(struct Client* cptr); extern void delete_resolver_queries(const void *vptr); extern void report_dns_servers(struct Client *source_p, const struct StatDesc *sd, char *param); extern void gethost_byname(const char *name, dns_callback_f callback, void *ctx); extern void gethost_byaddr(const struct irc_in_addr *addr, dns_callback_f callback, void *ctx); /** Evaluate to non-zero if \a ADDR is an unspecified (all zeros) address. */ #define irc_in_addr_unspec(ADDR) (((ADDR)->in6_16[0] == 0) \ && ((ADDR)->in6_16[1] == 0) \ && ((ADDR)->in6_16[2] == 0) \ && ((ADDR)->in6_16[3] == 0) \ && ((ADDR)->in6_16[4] == 0) \ && ((ADDR)->in6_16[6] == 0) \ && ((ADDR)->in6_16[7] == 0) \ && ((ADDR)->in6_16[5] == 0 \ || (ADDR)->in6_16[5] == 65535)) /** Evaluate to non-zero if \a ADDR is a valid address (not all 0s and not all 1s). */ #define irc_in_addr_valid(ADDR) (((ADDR)->in6_16[0] && ~(ADDR)->in6_16[0]) \ || (ADDR)->in6_16[1] != (ADDR)->in6_16[0] \ || (ADDR)->in6_16[2] != (ADDR)->in6_16[0] \ || (ADDR)->in6_16[3] != (ADDR)->in6_16[0] \ || (ADDR)->in6_16[4] != (ADDR)->in6_16[0] \ || (ADDR)->in6_16[5] != (ADDR)->in6_16[0] \ || (ADDR)->in6_16[6] != (ADDR)->in6_16[0] \ || (ADDR)->in6_16[7] != (ADDR)->in6_16[0]) /** Evaluate to non-zero if \a ADDR (of type struct irc_in_addr) is an IPv4 address. */ #define irc_in_addr_is_ipv4(ADDR) (!(ADDR)->in6_16[0] && !(ADDR)->in6_16[1] && !(ADDR)->in6_16[2] \ && !(ADDR)->in6_16[3] && !(ADDR)->in6_16[4] \ && ((!(ADDR)->in6_16[5] && (ADDR)->in6_16[6]) \ || (ADDR)->in6_16[5] == 65535)) /** Evaluate to non-zero if \a A is a different IP than \a B. */ #define irc_in_addr_cmp(A,B) (irc_in_addr_is_ipv4(A) ? ((A)->in6_16[6] != (B)->in6_16[6] \ || (A)->in6_16[7] != (B)->in6_16[7] || !irc_in_addr_is_ipv4(B)) \ : memcmp((A), (B), sizeof(struct irc_in_addr))) /** Evaluate to non-zero if \a ADDR is a loopback address. */ #define irc_in_addr_is_loopback(ADDR) (!(ADDR)->in6_16[0] && !(ADDR)->in6_16[1] && !(ADDR)->in6_16[2] \ && !(ADDR)->in6_16[3] && !(ADDR)->in6_16[4] \ && ((!(ADDR)->in6_16[5] \ && ((!(ADDR)->in6_16[6] && (ADDR)->in6_16[7] == htons(1)) \ || (ntohs((ADDR)->in6_16[6]) & 0xff00) == 0x7f00)) \ || (((ADDR)->in6_16[5] == 65535) \ && (ntohs((ADDR)->in6_16[6]) & 0xff00) == 0x7f00))) /** Evaluate to non-zero if \a A is the same type of IP address (IPv4 or IPv6) as \a B. */ #define irc_in_addr_type_cmp(A,B) ((irc_in_addr_is_ipv4(A) && irc_in_addr_is_ipv4(B)) || \ (!irc_in_addr_is_ipv4(A) && !irc_in_addr_is_ipv4(B))) #endif