src/lib/libc/asr/asr_private.h

360 lines
7.9 KiB
C

/* $OpenBSD: asr_private.h,v 1.49 2023/11/20 12:15:16 florian Exp $ */
/*
* Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#define QR_MASK (0x1 << 15)
#define OPCODE_MASK (0xf << 11)
#define AA_MASK (0x1 << 10)
#define TC_MASK (0x1 << 9)
#define RD_MASK (0x1 << 8)
#define RA_MASK (0x1 << 7)
#define Z_MASK (0x1 << 6)
#define AD_MASK (0x1 << 5)
#define CD_MASK (0x1 << 4)
#define RCODE_MASK (0xf)
#define OPCODE(v) ((v) & OPCODE_MASK)
#define RCODE(v) ((v) & RCODE_MASK)
struct asr_pack {
char *buf;
size_t len;
size_t offset;
int err;
};
struct asr_unpack {
const char *buf;
size_t len;
size_t offset;
int err;
};
struct asr_dns_header {
uint16_t id;
uint16_t flags;
uint16_t qdcount;
uint16_t ancount;
uint16_t nscount;
uint16_t arcount;
};
struct asr_dns_query {
char q_dname[MAXDNAME];
uint16_t q_type;
uint16_t q_class;
};
struct asr_dns_rr {
char rr_dname[MAXDNAME];
uint16_t rr_type;
uint16_t rr_class;
uint32_t rr_ttl;
union {
struct {
char cname[MAXDNAME];
} cname;
struct {
uint16_t preference;
char exchange[MAXDNAME];
} mx;
struct {
char nsname[MAXDNAME];
} ns;
struct {
char ptrname[MAXDNAME];
} ptr;
struct {
char mname[MAXDNAME];
char rname[MAXDNAME];
uint32_t serial;
uint32_t refresh;
uint32_t retry;
uint32_t expire;
uint32_t minimum;
} soa;
struct {
struct in_addr addr;
} in_a;
struct {
struct in6_addr addr6;
} in_aaaa;
struct {
uint16_t rdlen;
const void *rdata;
} other;
} rr;
};
#define ASR_MAXNS 5
#define ASR_MAXDB 3
#define ASR_MAXDOM 10
enum async_type {
ASR_SEND,
ASR_SEARCH,
ASR_GETRRSETBYNAME,
ASR_GETHOSTBYNAME,
ASR_GETHOSTBYADDR,
ASR_GETADDRINFO,
ASR_GETNAMEINFO,
};
#define ASR_DB_FILE 'f'
#define ASR_DB_DNS 'b'
struct asr_ctx {
int ac_refcount;
int ac_options;
int ac_ndots;
char *ac_domain;
int ac_domcount;
char *ac_dom[ASR_MAXDOM];
int ac_dbcount;
char ac_db[ASR_MAXDB + 1];
int ac_family[3];
int ac_nscount;
int ac_nstimeout;
int ac_nsretries;
struct sockaddr *ac_ns[ASR_MAXNS];
};
struct asr {
pid_t a_pid;
time_t a_mtime;
time_t a_rtime;
struct asr_ctx *a_ctx;
};
#define ASYNC_COND 0
#define ASYNC_DONE 1
#define ASYNC_DOM_FQDN 0x00000001
#define ASYNC_DOM_NDOTS 0x00000002
#define ASYNC_DOM_DOMAIN 0x00000004
#define ASYNC_DOM_ASIS 0x00000008
#define ASYNC_NODATA 0x00000100
#define ASYNC_AGAIN 0x00000200
#define ASYNC_GETNET 0x00001000
#define ASYNC_EXTOBUF 0x00002000
#define ASYNC_NO_INET 0x00010000
#define ASYNC_NO_INET6 0x00020000
struct asr_query {
int (*as_run)(struct asr_query *, struct asr_result *);
struct asr_ctx *as_ctx;
int as_type;
int as_flags;
int as_state;
/* cond */
int as_timeout;
int as_fd;
struct asr_query *as_subq;
/* loop indices in ctx */
int as_dom_step;
int as_dom_idx;
int as_dom_flags;
int as_family_idx;
int as_db_idx;
int as_count;
union {
struct {
uint16_t reqid;
int class;
int type;
char *dname; /* not fqdn! */
int rcode; /* response code */
int ancount; /* answer count */
int nsidx;
int nsloop;
/* io buffers for query/response */
unsigned char *obuf;
size_t obuflen;
size_t obufsize;
unsigned char *ibuf;
size_t ibuflen;
size_t ibufsize;
size_t datalen; /* for tcp io */
uint16_t pktlen;
} dns;
struct {
int class;
int type;
char *name;
int saved_h_errno;
} search;
struct {
int flags;
int class;
int type;
char *name;
} rrset;
struct {
char *name;
int family;
char addr[16];
int addrlen;
int subq_h_errno;
} hostnamadr;
struct {
char *hostname;
char *servname;
int port_tcp;
int port_udp;
union {
struct sockaddr sa;
struct sockaddr_in sain;
struct sockaddr_in6 sain6;
} sa;
struct addrinfo hints;
char *fqdn;
struct addrinfo *aifirst;
struct addrinfo *ailast;
} ai;
struct {
char *hostname;
char *servname;
size_t hostnamelen;
size_t servnamelen;
union {
struct sockaddr sa;
struct sockaddr_in sain;
struct sockaddr_in6 sain6;
} sa;
int flags;
} ni;
#define MAXTOKEN 10
} as;
};
#define AS_DB(p) ((p)->as_ctx->ac_db[(p)->as_db_idx - 1])
#define AS_FAMILY(p) ((p)->as_ctx->ac_family[(p)->as_family_idx])
enum asr_state {
ASR_STATE_INIT,
ASR_STATE_NEXT_DOMAIN,
ASR_STATE_NEXT_DB,
ASR_STATE_SAME_DB,
ASR_STATE_NEXT_FAMILY,
ASR_STATE_NEXT_NS,
ASR_STATE_UDP_SEND,
ASR_STATE_UDP_RECV,
ASR_STATE_TCP_WRITE,
ASR_STATE_TCP_READ,
ASR_STATE_PACKET,
ASR_STATE_SUBQUERY,
ASR_STATE_NOT_FOUND,
ASR_STATE_HALT,
};
#define MAXPACKETSZ 4096
__BEGIN_HIDDEN_DECLS
/* asr_utils.c */
void _asr_pack_init(struct asr_pack *, char *, size_t);
int _asr_pack_header(struct asr_pack *, const struct asr_dns_header *);
int _asr_pack_query(struct asr_pack *, uint16_t, uint16_t, const char *);
int _asr_pack_edns0(struct asr_pack *, uint16_t, int);
void _asr_unpack_init(struct asr_unpack *, const char *, size_t);
int _asr_unpack_header(struct asr_unpack *, struct asr_dns_header *);
int _asr_unpack_query(struct asr_unpack *, struct asr_dns_query *);
int _asr_unpack_rr(struct asr_unpack *, struct asr_dns_rr *);
int _asr_sockaddr_from_str(struct sockaddr *, int, const char *);
ssize_t _asr_dname_from_fqdn(const char *, char *, size_t);
ssize_t _asr_addr_as_fqdn(const char *, int, char *, size_t);
int hnok_lenient(const char *);
int _asr_is_localhost(const char*);
/* asr.c */
void _asr_resolver_done(void *);
struct asr_ctx *_asr_use_resolver(void *);
struct asr_ctx *_asr_no_resolver(void);
void _asr_ctx_unref(struct asr_ctx *);
struct asr_query *_asr_async_new(struct asr_ctx *, int);
void _asr_async_free(struct asr_query *);
size_t _asr_make_fqdn(const char *, const char *, char *, size_t);
char *_asr_strdname(const char *, char *, size_t);
int _asr_iter_db(struct asr_query *);
int _asr_parse_namedb_line(FILE *, char **, int, char *, size_t);
/* *_async.c */
struct asr_query *_res_query_async_ctx(const char *, int, int, struct asr_ctx *);
struct asr_query *_res_search_async_ctx(const char *, int, int, struct asr_ctx *);
struct asr_query *_gethostbyaddr_async_ctx(const void *, socklen_t, int,
struct asr_ctx *);
int _asr_iter_domain(struct asr_query *, const char *, char *, size_t);
#ifdef DEBUG
#define DPRINT(...) do { if(_asr_debug) { \
fprintf(_asr_debug, __VA_ARGS__); \
} } while (0)
#define DPRINT_PACKET(n, p, s) do { if(_asr_debug) { \
fprintf(_asr_debug, "----- %s -----\n", n); \
_asr_dump_packet(_asr_debug, (p), (s)); \
fprintf(_asr_debug, "--------------\n"); \
} } while (0)
#else /* DEBUG */
#define DPRINT(...)
#define DPRINT_PACKET(...)
#endif /* DEBUG */
const char *_asr_querystr(int);
const char *_asr_statestr(int);
const char *_asr_transitionstr(int);
const char *_asr_print_sockaddr(const struct sockaddr *, char *, size_t);
void _asr_dump_config(FILE *, struct asr *);
void _asr_dump_packet(FILE *, const void *, size_t);
extern FILE *_asr_debug;
#define async_set_state(a, s) do { \
DPRINT("asr: [%s@%p] %s -> %s\n", \
_asr_querystr((a)->as_type), \
as, \
_asr_statestr((a)->as_state), \
_asr_statestr((s))); \
(a)->as_state = (s); } while (0)
__END_HIDDEN_DECLS