mirror of https://github.com/rspamd/rspamd.git
Rapid spam filtering system
https://rspamd.com/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
294 lines
6.8 KiB
294 lines
6.8 KiB
/*
|
|
* Copyright (c) 2013, Vsevolod Stakhov
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * 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.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY AUTHOR ''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 AUTHOR 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 RSPAMD_DNS_H
|
|
#define RSPAMD_DNS_H
|
|
|
|
#include "config.h"
|
|
#include "mem_pool.h"
|
|
#include "events.h"
|
|
#include "upstream.h"
|
|
|
|
#define MAX_SERVERS 16
|
|
|
|
#define DNS_D_MAXLABEL 63 /* + 1 '\0' */
|
|
#define DNS_D_MAXNAME 255 /* + 1 '\0' */
|
|
|
|
#define MAX_ADDRS 10
|
|
|
|
struct rspamd_dns_reply;
|
|
struct config_file;
|
|
|
|
typedef void (*dns_callback_type) (struct rspamd_dns_reply *reply, gpointer arg);
|
|
|
|
/**
|
|
* Represents DNS server
|
|
*/
|
|
struct rspamd_dns_server {
|
|
struct upstream up; /**< upstream structure */
|
|
gchar *name; /**< name of DNS server */
|
|
struct rspamd_dns_io_channel *io_channels;
|
|
struct rspamd_dns_io_channel *cur_io_channel;
|
|
};
|
|
|
|
/**
|
|
* IO channel for a specific DNS server
|
|
*/
|
|
struct rspamd_dns_io_channel {
|
|
struct rspamd_dns_server *srv;
|
|
struct rspamd_dns_resolver *resolver;
|
|
gint sock; /**< persistent socket */
|
|
struct event ev;
|
|
GHashTable *requests; /**< requests in flight */
|
|
struct rspamd_dns_io_channel *prev, *next;
|
|
};
|
|
|
|
struct dns_permutor;
|
|
|
|
struct rspamd_dns_resolver {
|
|
struct rspamd_dns_server servers[MAX_SERVERS];
|
|
gint servers_num; /**< number of DNS servers registered */
|
|
struct dns_permutor *permutor; /**< permutor for randomizing request id */
|
|
guint request_timeout;
|
|
guint max_retransmits;
|
|
guint max_errors;
|
|
GHashTable *io_channels; /**< hash of io chains indexed by socket */
|
|
memory_pool_t *static_pool; /**< permament pool (cfg_pool) */
|
|
gboolean throttling; /**< dns servers are busy */
|
|
gboolean is_master_slave; /**< if this is true, then select upstreams as master/slave */
|
|
guint errors; /**< resolver errors */
|
|
struct timeval throttling_time; /**< throttling time */
|
|
struct event throttling_event; /**< throttling event */
|
|
struct event_base *ev_base; /**< base for event ops */
|
|
};
|
|
|
|
struct dns_header;
|
|
struct dns_query;
|
|
|
|
enum rspamd_request_type {
|
|
DNS_REQUEST_A = 0,
|
|
DNS_REQUEST_PTR,
|
|
DNS_REQUEST_MX,
|
|
DNS_REQUEST_TXT,
|
|
DNS_REQUEST_SRV,
|
|
DNS_REQUEST_SPF,
|
|
DNS_REQUEST_AAA
|
|
};
|
|
|
|
struct rspamd_dns_request {
|
|
memory_pool_t *pool; /**< pool associated with request */
|
|
struct rspamd_dns_resolver *resolver;
|
|
struct rspamd_dns_io_channel *io;
|
|
dns_callback_type func;
|
|
gpointer arg;
|
|
struct event timer_event;
|
|
struct event io_event;
|
|
struct timeval tv;
|
|
guint retransmits;
|
|
guint16 id;
|
|
struct rspamd_async_session *session;
|
|
struct rspamd_dns_reply *reply;
|
|
guint8 *packet;
|
|
const gchar *requested_name;
|
|
off_t pos;
|
|
guint packet_len;
|
|
gint sock;
|
|
enum rspamd_request_type type;
|
|
time_t time;
|
|
};
|
|
|
|
|
|
|
|
union rspamd_reply_element {
|
|
struct {
|
|
struct in_addr addr[MAX_ADDRS];
|
|
guint16 addrcount;
|
|
} a;
|
|
#ifdef HAVE_INET_PTON
|
|
struct {
|
|
struct in6_addr addr;
|
|
} aaa;
|
|
#endif
|
|
struct {
|
|
gchar *name;
|
|
} ptr;
|
|
struct {
|
|
gchar *name;
|
|
guint16 priority;
|
|
} mx;
|
|
struct {
|
|
gchar *data;
|
|
} txt;
|
|
struct {
|
|
gchar *data;
|
|
} spf;
|
|
struct {
|
|
guint16 priority;
|
|
guint16 weight;
|
|
guint16 port;
|
|
gchar *target;
|
|
} srv;
|
|
};
|
|
|
|
enum dns_rcode {
|
|
DNS_RC_NOERROR = 0,
|
|
DNS_RC_FORMERR = 1,
|
|
DNS_RC_SERVFAIL = 2,
|
|
DNS_RC_NXDOMAIN = 3,
|
|
DNS_RC_NOTIMP = 4,
|
|
DNS_RC_REFUSED = 5,
|
|
DNS_RC_YXDOMAIN = 6,
|
|
DNS_RC_YXRRSET = 7,
|
|
DNS_RC_NXRRSET = 8,
|
|
DNS_RC_NOTAUTH = 9,
|
|
DNS_RC_NOTZONE = 10,
|
|
};
|
|
|
|
struct rspamd_dns_reply {
|
|
enum rspamd_request_type type;
|
|
struct rspamd_dns_request *request;
|
|
enum dns_rcode code;
|
|
GList *elements;
|
|
};
|
|
|
|
/* Internal DNS structs */
|
|
|
|
struct dns_header {
|
|
guint qid:16;
|
|
|
|
#if BYTE_ORDER == BIG_ENDIAN
|
|
guint qr:1;
|
|
guint opcode:4;
|
|
guint aa:1;
|
|
guint tc:1;
|
|
guint rd:1;
|
|
|
|
guint ra:1;
|
|
guint unused:3;
|
|
guint rcode:4;
|
|
#else
|
|
guint rd:1;
|
|
guint tc:1;
|
|
guint aa:1;
|
|
guint opcode:4;
|
|
guint qr:1;
|
|
|
|
guint rcode:4;
|
|
guint unused:3;
|
|
guint ra:1;
|
|
#endif
|
|
|
|
guint qdcount:16;
|
|
guint ancount:16;
|
|
guint nscount:16;
|
|
guint arcount:16;
|
|
};
|
|
|
|
enum dns_section {
|
|
DNS_S_QD = 0x01,
|
|
#define DNS_S_QUESTION DNS_S_QD
|
|
|
|
DNS_S_AN = 0x02,
|
|
#define DNS_S_ANSWER DNS_S_AN
|
|
|
|
DNS_S_NS = 0x04,
|
|
#define DNS_S_AUTHORITY DNS_S_NS
|
|
|
|
DNS_S_AR = 0x08,
|
|
#define DNS_S_ADDITIONAL DNS_S_AR
|
|
|
|
DNS_S_ALL = 0x0f
|
|
}; /* enum dns_section */
|
|
|
|
enum dns_opcode {
|
|
DNS_OP_QUERY = 0,
|
|
DNS_OP_IQUERY = 1,
|
|
DNS_OP_STATUS = 2,
|
|
DNS_OP_NOTIFY = 4,
|
|
DNS_OP_UPDATE = 5,
|
|
}; /* dns_opcode */
|
|
|
|
enum dns_type {
|
|
DNS_T_A = 1,
|
|
DNS_T_NS = 2,
|
|
DNS_T_CNAME = 5,
|
|
DNS_T_SOA = 6,
|
|
DNS_T_PTR = 12,
|
|
DNS_T_MX = 15,
|
|
DNS_T_TXT = 16,
|
|
DNS_T_AAAA = 28,
|
|
DNS_T_SRV = 33,
|
|
DNS_T_OPT = 41,
|
|
DNS_T_SSHFP = 44,
|
|
DNS_T_SPF = 99,
|
|
|
|
DNS_T_ALL = 255
|
|
}; /* enum dns_type */
|
|
|
|
enum dns_class {
|
|
DNS_C_IN = 1,
|
|
|
|
DNS_C_ANY = 255
|
|
}; /* enum dns_class */
|
|
|
|
struct dns_query {
|
|
gchar *qname;
|
|
guint qtype:16;
|
|
guint qclass:16;
|
|
};
|
|
|
|
/* Rspamd DNS API */
|
|
|
|
/**
|
|
* Init DNS resolver, params are obtained from a config file or system file /etc/resolv.conf
|
|
*/
|
|
struct rspamd_dns_resolver *dns_resolver_init (struct event_base *ev_base, struct config_file *cfg);
|
|
|
|
/**
|
|
* Make a DNS request
|
|
* @param resolver resolver object
|
|
* @param session async session to register event
|
|
* @param pool memory pool for storage
|
|
* @param cb callback to call on resolve completing
|
|
* @param ud user data for callback
|
|
* @param type request type
|
|
* @param ... string or ip address based on a request type
|
|
* @return TRUE if request was sent.
|
|
*/
|
|
gboolean make_dns_request (struct rspamd_dns_resolver *resolver,
|
|
struct rspamd_async_session *session, memory_pool_t *pool, dns_callback_type cb,
|
|
gpointer ud, enum rspamd_request_type type, ...);
|
|
|
|
/**
|
|
* Get textual presentation of DNS error code
|
|
*/
|
|
const gchar *dns_strerror (enum dns_rcode rcode);
|
|
|
|
/**
|
|
* Get textual presentation of DNS request type
|
|
*/
|
|
const gchar *dns_strtype (enum rspamd_request_type type);
|
|
|
|
#endif
|