MEDIUM: resolvers/dns: split dns.c into dns.c and resolvers.c

This patch splits current dns.c into two files:

The first dns.c contains code related to DNS message exchange over UDP
and in future other TCP. We try to remove depencies to resolving
to make it usable by other stuff as DNS load balancing.

The new resolvers.c inherit of the code specific to the actual
resolvers.

Note:
It was really difficult to obtain a clean diff dur to the amount
of moved code.

Note2:
Counters and stuff related to stats is not cleany separated because
currently counters for both layers are merged and hard to separate
for now.
This commit is contained in:
Emeric Brun 2021-02-12 19:42:55 +01:00 committed by Willy Tarreau
parent d26a6237ad
commit c943799c86
15 changed files with 3597 additions and 3461 deletions

View File

@ -845,7 +845,7 @@ OBJS += src/mux_h2.o src/mux_fcgi.o src/http_ana.o src/stream.o \
src/mux_h1.o src/stats.o src/flt_spoe.o src/backend.o \
src/tcpcheck.o src/server.o src/tools.o src/cli.o \
src/cfgparse.o src/log.o src/cfgparse-listen.o src/check.o \
src/stick_table.o src/peers.o src/dns.o src/stream_interface.o \
src/stick_table.o src/peers.o src/resolvers.o src/stream_interface.o \
src/sample.o src/http_htx.o src/haproxy.o src/http_act.o \
src/proxy.o src/pattern.o src/listener.o src/cache.o \
src/http_fetch.o src/session.o src/connection.o src/sink.o \
@ -871,7 +871,7 @@ OBJS += src/mux_h2.o src/mux_fcgi.o src/http_ana.o src/stream.o \
src/ebimtree.o src/uri_auth.o src/freq_ctr.o src/ebsttree.o \
src/ebistree.o src/auth.o src/wdt.o src/http_acl.o \
src/hpack-enc.o src/hpack-huff.o src/ebtree.o src/base64.o \
src/hash.o src/dgram.o src/version.o src/fix.o src/mqtt.o
src/hash.o src/dgram.o src/version.o src/fix.o src/mqtt.o src/dns.o
ifneq ($(TRACE),)
OBJS += src/calltrace.o

View File

@ -25,73 +25,14 @@
#include <import/eb32tree.h>
#include <haproxy/connection-t.h>
#include <haproxy/buf-t.h>
#include <haproxy/dgram-t.h>
#include <haproxy/obj_type-t.h>
#include <haproxy/ring-t.h>
#include <haproxy/stats-t.h>
#include <haproxy/task-t.h>
#include <haproxy/thread.h>
extern struct pool_head *resolv_requester_pool;
/*DNS maximum values */
/*
* Maximum issued from RFC:
* RFC 1035: https://www.ietf.org/rfc/rfc1035.txt chapter 2.3.4
* RFC 2671: http://tools.ietf.org/html/rfc2671
*/
#define DNS_MAX_LABEL_SIZE 63
#define DNS_MAX_NAME_SIZE 255
#define DNS_MAX_UDP_MESSAGE 8192
/* DNS minimum record size: 1 char + 1 NULL + type + class */
#define DNS_MIN_RECORD_SIZE (1 + 1 + 2 + 2)
/* DNS smallest fqdn 'a.gl' size */
# define DNS_SMALLEST_FQDN_SIZE 4
/* maximum number of query records in a DNS response
* For now, we allow only one */
#define DNS_MAX_QUERY_RECORDS 1
/* maximum number of answer record in a DNS response */
#define DNS_MAX_ANSWER_RECORDS ((DNS_MAX_UDP_MESSAGE - DNS_HEADER_SIZE) / DNS_MIN_RECORD_SIZE)
/* size of dns_buffer used to store responses from the buffer
* dns_buffer is used to store data collected from records found in a response.
* Before using it, caller will always check that there is at least DNS_MAX_NAME_SIZE bytes
* available */
#define DNS_ANALYZE_BUFFER_SIZE DNS_MAX_UDP_MESSAGE + DNS_MAX_NAME_SIZE
/* DNS error messages */
#define DNS_TOO_LONG_FQDN "hostname too long"
#define DNS_LABEL_TOO_LONG "one label too long"
#define DNS_INVALID_CHARACTER "found an invalid character"
/* dns query class */
#define DNS_RCLASS_IN 1 /* internet class */
/* dns record types (non exhaustive list) */
#define DNS_RTYPE_A 1 /* IPv4 address */
#define DNS_RTYPE_CNAME 5 /* canonical name */
#define DNS_RTYPE_AAAA 28 /* IPv6 address */
#define DNS_RTYPE_SRV 33 /* SRV record */
#define DNS_RTYPE_OPT 41 /* OPT */
#define DNS_RTYPE_ANY 255 /* all records */
/* dns rcode values */
#define DNS_RCODE_NO_ERROR 0 /* no error */
#define DNS_RCODE_NX_DOMAIN 3 /* non existent domain */
#define DNS_RCODE_REFUSED 5 /* query refused */
/* dns flags masks */
#define DNS_FLAG_TRUNCATED 0x0200 /* mask for truncated flag */
#define DNS_FLAG_REPLYCODE 0x000F /* mask for reply code */
/* max number of network preference entries are available from the
* configuration file.
*/
#define SRV_MAX_PREF_NET 5
/* DNS header size */
#define DNS_HEADER_SIZE ((int)sizeof(struct dns_header))
@ -115,13 +56,6 @@ struct dns_question {
unsigned short qclass; /* query class */
} __attribute__ ((packed));
/* NOTE: big endian structure */
struct resolv_query_item {
char name[DNS_MAX_NAME_SIZE+1]; /* query name */
unsigned short type; /* question type */
unsigned short class; /* query class */
struct list list;
};
/* NOTE: big endian structure */
struct dns_additional_record {
@ -136,77 +70,13 @@ struct dns_additional_record {
* extension set (client subnet, tcp keepalive, etc...)*/
} __attribute__ ((packed));
/* NOTE: big endian structure */
struct resolv_answer_item {
/*For SRV type, name also includes service and protocol value */
char name[DNS_MAX_NAME_SIZE+1]; /* answer name */
int16_t type; /* question type */
int16_t class; /* query class */
int32_t ttl; /* response TTL */
int16_t priority; /* SRV type priority */
uint16_t weight; /* SRV type weight */
uint16_t port; /* SRV type port */
uint16_t data_len; /* number of bytes in target below */
struct sockaddr address; /* IPv4 or IPv6, network format */
char target[DNS_MAX_NAME_SIZE+1]; /* Response data: SRV or CNAME type target */
time_t last_seen; /* When was the answer was last seen */
struct resolv_answer_item *ar_item; /* pointer to a RRset from the additional section, if exists */
struct list list;
};
struct resolv_response {
struct dns_header header;
struct list query_list;
struct list answer_list;
/* authority ignored for now */
};
/* Resolvers section and parameters. It is linked to the name servers
* servers points to it.
* current resolution are stored in a FIFO list.
*/
struct resolvers {
__decl_thread(HA_SPINLOCK_T lock);
unsigned int accepted_payload_size; /* maximum payload size we accept for responses */
int nb_nameservers; /* total number of active nameservers in a resolvers section */
int resolve_retries; /* number of retries before giving up */
struct { /* time to: */
int resolve; /* wait between 2 queries for the same resolution */
int retry; /* wait for a response before retrying */
} timeout;
struct { /* time to hold current data when */
int valid; /* a response is valid */
int nx; /* a response doesn't exist */
int timeout; /* no answer was delivered */
int refused; /* dns server refused to answer */
int other; /* other dns response errors */
int obsolete; /* an answer hasn't been seen */
} hold;
struct task *t; /* timeout management */
struct {
struct list wait; /* resolutions managed to this resolvers section */
struct list curr; /* current running resolutions */
} resolutions;
struct eb_root query_ids; /* tree to quickly lookup/retrieve query ids currently in use
* used by each nameserver, but stored in resolvers since there must
* be a unique relation between an eb_root and an eb_node (resolution) */
struct list list; /* resolvers list */
struct list nameservers; /* dns server list */
char *id; /* resolvers unique identifier */
struct {
const char *file; /* file where the section appears */
int line; /* line where the section appears */
} conf; /* config information */
};
struct dns_dgram_server {
struct dgram_conn conn; /* transport layer */
struct ring *ring_req;
size_t ofs_req; // ring buffer reader offset
};
/* Structure describing a name server used during name resolution.
* A name server belongs to a resolvers section.
/* Structure describing a name server
*/
struct dns_nameserver {
char *id; /* nameserver unique identifier */
@ -225,6 +95,7 @@ struct dns_nameserver {
struct list list; /* nameserver chained list */
};
/* mixed dns and resolver counters, we will have to split them */
struct dns_counters {
char *id;
char *pid;
@ -245,127 +116,4 @@ struct dns_counters {
long long truncated; /* - truncated response */;
};
struct resolv_options {
int family_prio; /* which IP family should the resolver use when both are returned */
struct {
int family;
union {
struct in_addr in4;
struct in6_addr in6;
} addr;
union {
struct in_addr in4;
struct in6_addr in6;
} mask;
} pref_net[SRV_MAX_PREF_NET];
int pref_net_nb; /* The number of registered preferred networks. */
int accept_duplicate_ip; /* flag to indicate whether the associated object can use an IP address
already set to an other object of the same group */
int ignore_weight; /* flag to indicate whether to ignore the weight within the record */
};
/* Resolution structure associated to single server and used to manage name
* resolution for this server.
* The only link between the resolution and a nameserver is through the
* query_id.
*/
struct resolv_resolution {
struct resolvers *resolvers; /* pointer to the resolvers structure owning the resolution */
struct list requesters; /* list of requesters using this resolution */
int uuid; /* unique id (used for debugging purpose) */
char *hostname_dn; /* server hostname in domain name label format */
int hostname_dn_len; /* server domain name label len */
unsigned int last_resolution; /* time of the last resolution */
unsigned int last_query; /* time of the last query sent */
unsigned int last_valid; /* time of the last valid response */
int query_id; /* DNS query ID dedicated for this resolution */
struct eb32_node qid; /* ebtree query id */
int prefered_query_type; /* preferred query type */
int query_type; /* current query type */
int status; /* status of the resolution being processed RSLV_STATUS_* */
int step; /* RSLV_STEP_* */
int try; /* current resolution try */
int nb_queries; /* count number of queries sent */
int nb_responses; /* count number of responses received */
struct resolv_response response; /* structure hosting the DNS response */
struct resolv_query_item response_query_records[DNS_MAX_QUERY_RECORDS]; /* <response> query records */
struct list list; /* resolution list */
};
/* Structure used to describe the owner of a DNS resolution. */
struct resolv_requester {
enum obj_type *owner; /* pointer to the owner (server or dns_srvrq) */
struct resolv_resolution *resolution; /* pointer to the owned DNS resolution */
int (*requester_cb)(struct resolv_requester *, struct dns_counters *); /* requester callback for valid response */
int (*requester_error_cb)(struct resolv_requester *, int); /* requester callback, for error management */
struct list list; /* requester list */
};
/* Last resolution status code */
enum {
RSLV_STATUS_NONE = 0, /* no resolution occurred yet */
RSLV_STATUS_VALID, /* no error */
RSLV_STATUS_INVALID, /* invalid responses */
RSLV_STATUS_ERROR, /* error */
RSLV_STATUS_NX, /* NXDOMAIN */
RSLV_STATUS_REFUSED, /* server refused our query */
RSLV_STATUS_TIMEOUT, /* no response from DNS servers */
RSLV_STATUS_OTHER, /* other errors */
};
/* Current resolution step */
enum {
RSLV_STEP_NONE = 0, /* nothing happening currently */
RSLV_STEP_RUNNING, /* resolution is running */
};
/* Return codes after analyzing a DNS response */
enum {
RSLV_RESP_VALID = 0, /* valid response */
RSLV_RESP_INVALID, /* invalid response (various type of errors can trigger it) */
RSLV_RESP_ERROR, /* DNS error code */
RSLV_RESP_NX_DOMAIN, /* resolution unsuccessful */
RSLV_RESP_REFUSED, /* DNS server refused to answer */
RSLV_RESP_ANCOUNT_ZERO, /* no answers in the response */
RSLV_RESP_WRONG_NAME, /* response does not match query name */
RSLV_RESP_CNAME_ERROR, /* error when resolving a CNAME in an atomic response */
RSLV_RESP_TIMEOUT, /* DNS server has not answered in time */
RSLV_RESP_TRUNCATED, /* DNS response is truncated */
RSLV_RESP_NO_EXPECTED_RECORD, /* No expected records were found in the response */
RSLV_RESP_QUERY_COUNT_ERROR, /* we did not get the expected number of queries in the response */
RSLV_RESP_INTERNAL, /* internal resolver error */
};
/* Return codes after searching an IP in a DNS response buffer, using a family
* preference
*/
enum {
RSLV_UPD_NO = 1, /* provided IP was found and preference is matched
* OR provided IP found and preference is not matched, but no IP
* matching preference was found */
RSLV_UPD_SRVIP_NOT_FOUND, /* provided IP not found
* OR provided IP found and preference is not match and an IP
* matching preference was found */
RSLV_UPD_CNAME, /* CNAME without any IP provided in the response */
RSLV_UPD_NAME_ERROR, /* name in the response did not match the query */
RSLV_UPD_NO_IP_FOUND, /* no IP could be found in the response */
RSLV_UPD_OBSOLETE_IP, /* The server IP was obsolete, and no other IP was found */
};
struct proxy;
struct resolv_srvrq {
enum obj_type obj_type; /* object type == OBJ_TYPE_SRVRQ */
struct resolvers *resolvers; /* pointer to the resolvers structure used for this server template */
struct proxy *proxy; /* associated proxy */
char *name;
char *hostname_dn; /* server hostname in Domain Name format */
int hostname_dn_len; /* string length of the server hostname in Domain Name format */
struct resolv_requester *requester; /* used to link to its DNS resolution */
struct list list; /* Next SRV RQ for the same proxy */
};
#endif /* _HAPROXY_DNS_T_H */

View File

@ -2,7 +2,7 @@
* include/haproxy/dns.h
* This file provides functions related to DNS protocol
*
* Copyright (C) 2014 Baptiste Assmann <bedis9@gmail.com>
* Copyright (C) 2020 Haproxy Technologies
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -22,37 +22,10 @@
#ifndef _HAPROXY_DNS_H
#define _HAPROXY_DNS_H
#include <haproxy/action-t.h>
#include <haproxy/dns-t.h>
extern struct list sec_resolvers;
extern unsigned int resolv_failed_resolutions;
struct resolvers *find_resolvers_by_id(const char *id);
struct resolv_srvrq *find_srvrq_by_name(const char *name, struct proxy *px);
struct resolv_srvrq *new_resolv_srvrq(struct server *srv, char *fqdn);
int resolv_str_to_dn_label(const char *str, int str_len, char *dn, int dn_len);
int resolv_dn_label_to_str(const char *dn, int dn_len, char *str, int str_len);
int resolv_hostname_validation(const char *string, char **err);
int resolv_get_ip_from_response(struct resolv_response *r_res,
struct resolv_options *resolv_opts, void *currentip,
short currentip_sin_family,
void **newip, short *newip_sin_family,
void *owner);
int resolv_link_resolution(void *requester, int requester_type, int requester_locked);
void resolv_unlink_resolution(struct resolv_requester *requester);
void resolv_trigger_resolution(struct resolv_requester *requester);
enum act_parse_ret resolv_parse_do_resolve(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err);
int check_action_do_resolve(struct act_rule *rule, struct proxy *px, char **err);
int stats_dump_resolvers(struct stream_interface *si,
struct field *stats, size_t stats_count,
struct list *stat_modules);
void resolv_stats_clear_counters(int clrall, struct list *stat_modules);
int resolv_allocate_counters(struct list *stat_modules);
int dns_send_nameserver(struct dns_nameserver *ns, void *buf, size_t len);
ssize_t dns_recv_nameserver(struct dns_nameserver *ns, void *data, size_t size);
int dns_dgram_init(struct dns_nameserver *ns, struct sockaddr_storage *sk);
#endif // _HAPROXY_DNS_H

View File

@ -0,0 +1,292 @@
/*
* include/haproxy/dns-t.h
* This file provides structures and types for DNS.
*
* Copyright (C) 2014 Baptiste Assmann <bedis9@gmail.com>
*
* This library 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, version 2.1
* exclusively.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HAPROXY_RESOLVERS_T_H
#define _HAPROXY_RESOLVERS_T_H
#include <import/eb32tree.h>
#include <haproxy/connection-t.h>
#include <haproxy/dns-t.h>
#include <haproxy/obj_type-t.h>
#include <haproxy/stats-t.h>
#include <haproxy/task-t.h>
#include <haproxy/thread.h>
extern struct pool_head *resolv_requester_pool;
/*DNS maximum values */
/*
* Maximum issued from RFC:
* RFC 1035: https://www.ietf.org/rfc/rfc1035.txt chapter 2.3.4
* RFC 2671: http://tools.ietf.org/html/rfc2671
*/
#define DNS_MAX_LABEL_SIZE 63
#define DNS_MAX_NAME_SIZE 255
#define DNS_MAX_UDP_MESSAGE 8192
/* DNS minimum record size: 1 char + 1 NULL + type + class */
#define DNS_MIN_RECORD_SIZE (1 + 1 + 2 + 2)
/* DNS smallest fqdn 'a.gl' size */
# define DNS_SMALLEST_FQDN_SIZE 4
/* maximum number of query records in a DNS response
* For now, we allow only one */
#define DNS_MAX_QUERY_RECORDS 1
/* maximum number of answer record in a DNS response */
#define DNS_MAX_ANSWER_RECORDS ((DNS_MAX_UDP_MESSAGE - DNS_HEADER_SIZE) / DNS_MIN_RECORD_SIZE)
/* size of dns_buffer used to store responses from the buffer
* dns_buffer is used to store data collected from records found in a response.
* Before using it, caller will always check that there is at least DNS_MAX_NAME_SIZE bytes
* available */
#define DNS_ANALYZE_BUFFER_SIZE DNS_MAX_UDP_MESSAGE + DNS_MAX_NAME_SIZE
/* DNS error messages */
#define DNS_TOO_LONG_FQDN "hostname too long"
#define DNS_LABEL_TOO_LONG "one label too long"
#define DNS_INVALID_CHARACTER "found an invalid character"
/* dns query class */
#define DNS_RCLASS_IN 1 /* internet class */
/* dns record types (non exhaustive list) */
#define DNS_RTYPE_A 1 /* IPv4 address */
#define DNS_RTYPE_CNAME 5 /* canonical name */
#define DNS_RTYPE_AAAA 28 /* IPv6 address */
#define DNS_RTYPE_SRV 33 /* SRV record */
#define DNS_RTYPE_OPT 41 /* OPT */
#define DNS_RTYPE_ANY 255 /* all records */
/* dns rcode values */
#define DNS_RCODE_NO_ERROR 0 /* no error */
#define DNS_RCODE_NX_DOMAIN 3 /* non existent domain */
#define DNS_RCODE_REFUSED 5 /* query refused */
/* dns flags masks */
#define DNS_FLAG_TRUNCATED 0x0200 /* mask for truncated flag */
#define DNS_FLAG_REPLYCODE 0x000F /* mask for reply code */
/* max number of network preference entries are available from the
* configuration file.
*/
#define SRV_MAX_PREF_NET 5
/* NOTE: big endian structure */
struct resolv_query_item {
char name[DNS_MAX_NAME_SIZE+1]; /* query name */
unsigned short type; /* question type */
unsigned short class; /* query class */
struct list list;
};
/* NOTE: big endian structure */
struct resolv_answer_item {
/*For SRV type, name also includes service and protocol value */
char name[DNS_MAX_NAME_SIZE+1]; /* answer name */
int16_t type; /* question type */
int16_t class; /* query class */
int32_t ttl; /* response TTL */
int16_t priority; /* SRV type priority */
uint16_t weight; /* SRV type weight */
uint16_t port; /* SRV type port */
uint16_t data_len; /* number of bytes in target below */
struct sockaddr address; /* IPv4 or IPv6, network format */
char target[DNS_MAX_NAME_SIZE+1]; /* Response data: SRV or CNAME type target */
time_t last_seen; /* When was the answer was last seen */
struct resolv_answer_item *ar_item; /* pointer to a RRset from the additional section, if exists */
struct list list;
};
struct resolv_response {
struct dns_header header;
struct list query_list;
struct list answer_list;
/* authority ignored for now */
};
/* Resolvers section and parameters. It is linked to the name servers
* servers points to it.
* current resolution are stored in a FIFO list.
*/
struct resolvers {
__decl_thread(HA_SPINLOCK_T lock);
unsigned int accepted_payload_size; /* maximum payload size we accept for responses */
int nb_nameservers; /* total number of active nameservers in a resolvers section */
int resolve_retries; /* number of retries before giving up */
struct { /* time to: */
int resolve; /* wait between 2 queries for the same resolution */
int retry; /* wait for a response before retrying */
} timeout;
struct { /* time to hold current data when */
int valid; /* a response is valid */
int nx; /* a response doesn't exist */
int timeout; /* no answer was delivered */
int refused; /* dns server refused to answer */
int other; /* other dns response errors */
int obsolete; /* an answer hasn't been seen */
} hold;
struct task *t; /* timeout management */
struct {
struct list wait; /* resolutions managed to this resolvers section */
struct list curr; /* current running resolutions */
} resolutions;
struct eb_root query_ids; /* tree to quickly lookup/retrieve query ids currently in use
* used by each nameserver, but stored in resolvers since there must
* be a unique relation between an eb_root and an eb_node (resolution) */
struct list list; /* resolvers list */
struct list nameservers; /* dns server list */
struct proxy *px; /* px to handle connections to DNS servers */
char *id; /* resolvers unique identifier */
struct {
const char *file; /* file where the section appears */
int line; /* line where the section appears */
} conf; /* config information */
};
struct resolv_options {
int family_prio; /* which IP family should the resolver use when both are returned */
struct {
int family;
union {
struct in_addr in4;
struct in6_addr in6;
} addr;
union {
struct in_addr in4;
struct in6_addr in6;
} mask;
} pref_net[SRV_MAX_PREF_NET];
int pref_net_nb; /* The number of registered preferred networks. */
int accept_duplicate_ip; /* flag to indicate whether the associated object can use an IP address
already set to an other object of the same group */
int ignore_weight; /* flag to indicate whether to ignore the weight within the record */
};
/* Resolution structure associated to single server and used to manage name
* resolution for this server.
* The only link between the resolution and a nameserver is through the
* query_id.
*/
struct resolv_resolution {
struct resolvers *resolvers; /* pointer to the resolvers structure owning the resolution */
struct list requesters; /* list of requesters using this resolution */
int uuid; /* unique id (used for debugging purpose) */
char *hostname_dn; /* server hostname in domain name label format */
int hostname_dn_len; /* server domain name label len */
unsigned int last_resolution; /* time of the last resolution */
unsigned int last_query; /* time of the last query sent */
unsigned int last_valid; /* time of the last valid response */
int query_id; /* DNS query ID dedicated for this resolution */
struct eb32_node qid; /* ebtree query id */
int prefered_query_type; /* preferred query type */
int query_type; /* current query type */
int status; /* status of the resolution being processed RSLV_STATUS_* */
int step; /* RSLV_STEP_* */
int try; /* current resolution try */
int nb_queries; /* count number of queries sent */
int nb_responses; /* count number of responses received */
struct resolv_response response; /* structure hosting the DNS response */
struct resolv_query_item response_query_records[DNS_MAX_QUERY_RECORDS]; /* <response> query records */
struct list list; /* resolution list */
};
/* Structure used to describe the owner of a DNS resolution. */
struct resolv_requester {
enum obj_type *owner; /* pointer to the owner (server or dns_srvrq) */
struct resolv_resolution *resolution; /* pointer to the owned DNS resolution */
int (*requester_cb)(struct resolv_requester *, struct dns_counters *); /* requester callback for valid response */
int (*requester_error_cb)(struct resolv_requester *, int); /* requester callback, for error management */
struct list list; /* requester list */
};
/* Last resolution status code */
enum {
RSLV_STATUS_NONE = 0, /* no resolution occurred yet */
RSLV_STATUS_VALID, /* no error */
RSLV_STATUS_INVALID, /* invalid responses */
RSLV_STATUS_ERROR, /* error */
RSLV_STATUS_NX, /* NXDOMAIN */
RSLV_STATUS_REFUSED, /* server refused our query */
RSLV_STATUS_TIMEOUT, /* no response from DNS servers */
RSLV_STATUS_OTHER, /* other errors */
};
/* Current resolution step */
enum {
RSLV_STEP_NONE = 0, /* nothing happening currently */
RSLV_STEP_RUNNING, /* resolution is running */
};
/* Return codes after analyzing a DNS response */
enum {
RSLV_RESP_VALID = 0, /* valid response */
RSLV_RESP_INVALID, /* invalid response (various type of errors can trigger it) */
RSLV_RESP_ERROR, /* DNS error code */
RSLV_RESP_NX_DOMAIN, /* resolution unsuccessful */
RSLV_RESP_REFUSED, /* DNS server refused to answer */
RSLV_RESP_ANCOUNT_ZERO, /* no answers in the response */
RSLV_RESP_WRONG_NAME, /* response does not match query name */
RSLV_RESP_CNAME_ERROR, /* error when resolving a CNAME in an atomic response */
RSLV_RESP_TIMEOUT, /* DNS server has not answered in time */
RSLV_RESP_TRUNCATED, /* DNS response is truncated */
RSLV_RESP_NO_EXPECTED_RECORD, /* No expected records were found in the response */
RSLV_RESP_QUERY_COUNT_ERROR, /* we did not get the expected number of queries in the response */
RSLV_RESP_INTERNAL, /* internal resolver error */
};
/* Return codes after searching an IP in a DNS response buffer, using a family
* preference
*/
enum {
RSLV_UPD_NO = 1, /* provided IP was found and preference is matched
* OR provided IP found and preference is not matched, but no IP
* matching preference was found.
*/
RSLV_UPD_SRVIP_NOT_FOUND, /* provided IP not found
* OR provided IP found and preference is not match and an IP
* matching preference was found.
*/
RSLV_UPD_CNAME, /* CNAME without any IP provided in the response */
RSLV_UPD_NAME_ERROR, /* name in the response did not match the query */
RSLV_UPD_NO_IP_FOUND, /* no IP could be found in the response */
RSLV_UPD_OBSOLETE_IP, /* The server IP was obsolete, and no other IP was found */
};
struct proxy;
struct resolv_srvrq {
enum obj_type obj_type; /* object type == OBJ_TYPE_SRVRQ */
struct resolvers *resolvers; /* pointer to the resolvers structure used for this server template */
struct proxy *proxy; /* associated proxy */
char *name;
char *hostname_dn; /* server hostname in Domain Name format */
int hostname_dn_len; /* string length of the server hostname in Domain Name format */
struct resolv_requester *requester; /* used to link to its DNS resolution */
struct list list; /* Next SRV RQ for the same proxy */
};
#endif /* _HAPROXY_RESOLVERS_T_H */

View File

@ -0,0 +1,58 @@
/*
* include/haproxy/dns.h
* This file provides functions related to DNS protocol
*
* Copyright (C) 2014 Baptiste Assmann <bedis9@gmail.com>
*
* This library 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, version 2.1
* exclusively.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HAPROXY_RESOLVERS_H
#define _HAPROXY_RESOLVERS_H
#include <haproxy/action-t.h>
#include <haproxy/resolvers-t.h>
extern struct list sec_resolvers;
extern unsigned int resolv_failed_resolutions;
struct resolvers *find_resolvers_by_id(const char *id);
struct resolv_srvrq *find_srvrq_by_name(const char *name, struct proxy *px);
struct resolv_srvrq *new_resolv_srvrq(struct server *srv, char *fqdn);
int resolv_str_to_dn_label(const char *str, int str_len, char *dn, int dn_len);
int resolv_dn_label_to_str(const char *dn, int dn_len, char *str, int str_len);
int resolv_hostname_validation(const char *string, char **err);
int resolv_get_ip_from_response(struct resolv_response *r_res,
struct resolv_options *resolv_opts, void *currentip,
short currentip_sin_family,
void **newip, short *newip_sin_family,
void *owner);
int resolv_link_resolution(void *requester, int requester_type, int requester_locked);
void resolv_unlink_resolution(struct resolv_requester *requester);
void resolv_trigger_resolution(struct resolv_requester *requester);
enum act_parse_ret resolv_parse_do_resolve(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err);
int check_action_do_resolve(struct act_rule *rule, struct proxy *px, char **err);
int stats_dump_resolvers(struct stream_interface *si,
struct field *stats, size_t stats_count,
struct list *stat_modules);
void resolv_stats_clear_counters(int clrall, struct list *stat_modules);
int resolv_allocate_counters(struct list *stat_modules);
int dns_dgram_init(struct dns_nameserver *ns, struct sockaddr_storage *sk);
#endif // _HAPROXY_RESOLVER_H

View File

@ -32,11 +32,11 @@
#include <haproxy/check-t.h>
#include <haproxy/connection-t.h>
#include <haproxy/counters-t.h>
#include <haproxy/dns-t.h>
#include <haproxy/freq_ctr-t.h>
#include <haproxy/listener-t.h>
#include <haproxy/obj_type-t.h>
#include <haproxy/openssl-compat.h>
#include <haproxy/resolvers-t.h>
#include <haproxy/ssl_sock-t.h>
#include <haproxy/stats-t.h>
#include <haproxy/task-t.h>

View File

@ -26,9 +26,9 @@
#include <haproxy/api.h>
#include <haproxy/applet-t.h>
#include <haproxy/dns-t.h>
#include <haproxy/freq_ctr.h>
#include <haproxy/proxy-t.h>
#include <haproxy/resolvers-t.h>
#include <haproxy/server-t.h>
#include <haproxy/task.h>
#include <haproxy/thread-t.h>

View File

@ -44,7 +44,6 @@
#include <haproxy/check.h>
#include <haproxy/chunk.h>
#include <haproxy/connection.h>
#include <haproxy/dns.h>
#include <haproxy/errors.h>
#include <haproxy/filters.h>
#include <haproxy/frontend.h>
@ -66,6 +65,7 @@
#include <haproxy/pool.h>
#include <haproxy/protocol.h>
#include <haproxy/proxy.h>
#include <haproxy/resolvers.h>
#include <haproxy/sample.h>
#include <haproxy/server.h>
#include <haproxy/session.h>

View File

@ -36,7 +36,6 @@
#include <haproxy/check.h>
#include <haproxy/chunk.h>
#include <haproxy/dgram.h>
#include <haproxy/dns.h>
#include <haproxy/dynbuf-t.h>
#include <haproxy/extcheck.h>
#include <haproxy/fd.h>
@ -55,6 +54,7 @@
#include <haproxy/proxy.h>
#include <haproxy/queue.h>
#include <haproxy/regex.h>
#include <haproxy/resolvers.h>
#include <haproxy/sample.h>
#include <haproxy/server.h>
#include <haproxy/ssl_sock.h>

3165
src/dns.c

File diff suppressed because it is too large Load Diff

3220
src/resolvers.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,6 @@
#include <haproxy/cli.h>
#include <haproxy/connection.h>
#include <haproxy/dict-t.h>
#include <haproxy/dns.h>
#include <haproxy/errors.h>
#include <haproxy/global.h>
#include <haproxy/log.h>
@ -36,6 +35,7 @@
#include <haproxy/port_range.h>
#include <haproxy/protocol.h>
#include <haproxy/queue.h>
#include <haproxy/resolvers.h>
#include <haproxy/sample.h>
#include <haproxy/server.h>
#include <haproxy/ssl_sock.h>

View File

@ -34,7 +34,6 @@
#include <haproxy/cli.h>
#include <haproxy/compression.h>
#include <haproxy/debug.h>
#include <haproxy/dns.h>
#include <haproxy/errors.h>
#include <haproxy/fd.h>
#include <haproxy/freq_ctr.h>
@ -51,6 +50,7 @@
#include <haproxy/pipe.h>
#include <haproxy/pool.h>
#include <haproxy/proxy.h>
#include <haproxy/resolvers.h>
#include <haproxy/server.h>
#include <haproxy/session.h>
#include <haproxy/ssl_sock.h>

View File

@ -30,7 +30,6 @@
#include <haproxy/cli.h>
#include <haproxy/connection.h>
#include <haproxy/dict.h>
#include <haproxy/dns.h>
#include <haproxy/dynbuf.h>
#include <haproxy/fd.h>
#include <haproxy/filters.h>
@ -48,6 +47,7 @@
#include <haproxy/proxy.h>
#include <haproxy/queue.h>
#include <haproxy/server.h>
#include <haproxy/resolvers.h>
#include <haproxy/sample.h>
#include <haproxy/session.h>
#include <haproxy/stats-t.h>

View File

@ -42,12 +42,12 @@
#include <haproxy/api.h>
#include <haproxy/chunk.h>
#include <haproxy/dgram.h>
#include <haproxy/dns.h>
#include <haproxy/global.h>
#include <haproxy/hlua.h>
#include <haproxy/listener.h>
#include <haproxy/namespace.h>
#include <haproxy/protocol.h>
#include <haproxy/resolvers.h>
#include <haproxy/sock.h>
#include <haproxy/ssl_sock.h>
#include <haproxy/stream_interface.h>