#ifndef XFRD_H
#define XFRD_H
#ifndef USE_MINI_EVENT
# ifdef HAVE_EVENT_H
# include <event.h>
# else
# include <event2/event.h>
# include "event2/event_struct.h"
# include "event2/event_compat.h"
# endif
#else
# include "mini_event.h"
#endif
#include "rbtree.h"
#include "namedb.h"
#include "options.h"
#include "dns.h"
#include "tsig.h"
struct nsd;
struct region;
struct buffer;
struct xfrd_tcp;
struct xfrd_tcp_set;
struct notify_zone;
struct udb_ptr;
typedef struct xfrd_state xfrd_state_type;
typedef struct xfrd_xfr xfrd_xfr_type;
typedef struct xfrd_zone xfrd_zone_type;
typedef struct xfrd_soa xfrd_soa_type;
struct xfrd_state {
time_t xfrd_start_time;
struct region* region;
struct event_base* event_base;
struct nsd* nsd;
struct xfrd_tcp_set* tcp_set;
struct buffer* packet;
struct xfrd_zone *udp_waiting_first, *udp_waiting_last;
size_t udp_use_num;
struct xfrd_zone *activated_first;
uint8_t got_time;
time_t current_time;
uint64_t xfrfilenumber;
unsigned zonestat_safe;
size_t zonestat_clear_num;
struct nsdst** zonestat_clear;
struct nsdst* stat_clear;
struct timeval reload_timeout;
struct event reload_handler;
int reload_added;
time_t reload_cmd_last_sent;
time_t reload_cmd_first_sent;
uint8_t reload_failed;
uint8_t can_send_reload;
pid_t reload_pid;
struct event child_timer;
int child_timer_added;
struct event write_timer;
int write_zonefile_needed;
struct event ipc_handler;
int ipc_handler_flags;
struct event *notify_events;
struct xfrd_tcp *notify_pipes;
uint8_t need_to_send_shutdown;
uint8_t need_to_send_reload;
uint8_t need_to_send_stats;
uint8_t need_to_send_quit;
uint8_t ipc_send_blocked;
struct udb_ptr* last_task;
uint8_t shutdown;
rbtree_type *zones;
rbtree_type *notify_zones;
int notify_udp_num;
struct notify_zone *notify_waiting_first, *notify_waiting_last;
rbtree_type *catalog_consumer_zones;
rbtree_type *catalog_producer_zones;
};
struct xfrd_soa {
uint16_t type;
uint16_t klass;
uint32_t ttl;
uint8_t prim_ns[MAXDOMAINLEN + 2];
uint8_t email[MAXDOMAINLEN + 2];
uint32_t serial;
uint32_t refresh;
uint32_t retry;
uint32_t expire;
uint32_t minimum;
} ATTR_PACKED;
struct xfrd_zone {
rbnode_type node;
const dname_type* apex;
const char* apex_str;
xfrd_soa_type soa_nsd;
time_t soa_nsd_acquired;
xfrd_soa_type soa_disk;
time_t soa_disk_acquired;
xfrd_soa_type soa_notified;
time_t soa_notified_acquired;
enum xfrd_zone_state {
xfrd_zone_ok,
xfrd_zone_refreshing,
xfrd_zone_expired
} state;
struct acl_options* master;
int master_num;
int next_master;
int round_num;
struct zone_options* zone_options;
int fresh_xfr_timeout;
struct timeval timeout;
struct event zone_handler;
int zone_handler_flags;
int event_added;
int tcp_conn;
uint8_t tcp_waiting;
xfrd_zone_type* tcp_waiting_next;
xfrd_zone_type* tcp_waiting_prev;
uint8_t in_tcp_send;
xfrd_zone_type* tcp_send_next;
xfrd_zone_type* tcp_send_prev;
uint8_t udp_waiting;
xfrd_zone_type* udp_waiting_next;
xfrd_zone_type* udp_waiting_prev;
uint8_t is_activated;
xfrd_zone_type* activated_next;
xfrd_zone_type* activated_prev;
uint16_t query_id;
xfrd_xfr_type *latest_xfr;
int multi_master_first_master;
int multi_master_update_check;
} ATTR_PACKED;
struct xfrd_xfr {
xfrd_xfr_type *next;
xfrd_xfr_type *prev;
uint16_t query_type;
uint8_t sent;
time_t acquired;
uint32_t msg_seq_nr;
uint32_t msg_old_serial, msg_new_serial;
size_t msg_rr_count;
uint8_t msg_is_ixfr;
tsig_record_type tsig;
uint64_t xfrfilenumber;
};
enum xfrd_packet_result {
xfrd_packet_bad,
xfrd_packet_drop,
xfrd_packet_more,
xfrd_packet_notimpl,
xfrd_packet_tcp,
xfrd_packet_transfer,
xfrd_packet_newlease
};
#define XFRD_MAX_UDP 128
#define XFRD_MAX_UDP_NOTIFY 128
#define XFRD_TRANSFER_TIMEOUT_START 10
#define XFRD_TRANSFER_TIMEOUT_MAX 86400
#define XFRD_LOWERBOUND_REFRESH 1
#define XFRD_LOWERBOUND_RETRY 1
static inline time_t
within_refresh_bounds(xfrd_zone_type* zone, time_t refresh)
{
return (time_t)zone->zone_options->pattern->max_refresh_time < refresh
? (time_t)zone->zone_options->pattern->max_refresh_time
: (time_t)zone->zone_options->pattern->min_refresh_time > refresh
? (time_t)zone->zone_options->pattern->min_refresh_time
: XFRD_LOWERBOUND_REFRESH > refresh
? XFRD_LOWERBOUND_REFRESH : refresh;
}
static inline time_t
bound_soa_disk_refresh(xfrd_zone_type* zone)
{
return within_refresh_bounds(zone, ntohl(zone->soa_disk.refresh));
}
static inline time_t
within_retry_bounds(xfrd_zone_type* zone, time_t retry)
{
return (time_t)zone->zone_options->pattern->max_retry_time < retry
? (time_t)zone->zone_options->pattern->max_retry_time
: (time_t)zone->zone_options->pattern->min_retry_time > retry
? (time_t)zone->zone_options->pattern->min_retry_time
: XFRD_LOWERBOUND_RETRY > retry
? XFRD_LOWERBOUND_RETRY : retry;
}
static inline time_t
bound_soa_disk_retry(xfrd_zone_type* zone)
{
return within_retry_bounds(zone, ntohl(zone->soa_disk.retry));
}
static inline time_t
within_expire_bounds(xfrd_zone_type* zone, time_t expire)
{
switch (zone->zone_options->pattern->min_expire_time_expr) {
case EXPIRE_TIME_HAS_VALUE:
return (time_t)zone->zone_options->pattern->min_expire_time > expire
? (time_t)zone->zone_options->pattern->min_expire_time : expire;
case REFRESHPLUSRETRYPLUS1:
return bound_soa_disk_refresh(zone) + bound_soa_disk_retry(zone) + 1 > expire
? bound_soa_disk_refresh(zone) + bound_soa_disk_retry(zone) + 1 : expire;
default:
return expire;
}
}
static inline time_t
bound_soa_disk_expire(xfrd_zone_type* zone)
{
return within_expire_bounds(zone, ntohl(zone->soa_disk.expire));
}
static inline time_t
bound_soa_nsd_expire(xfrd_zone_type* zone)
{
return within_expire_bounds(zone, ntohl(zone->soa_nsd.expire));
}
extern xfrd_state_type* xfrd;
void xfrd_init(int socket, struct nsd* nsd, int shortsoa, int reload_active,
pid_t nsd_pid);
void xfrd_init_slave_zone(xfrd_state_type* xfrd, struct zone_options* zone_opt);
void xfrd_del_slave_zone(xfrd_state_type* xfrd, const dname_type* dname);
void xfrd_disable_ixfr(xfrd_zone_type* zone);
time_t xfrd_time(void);
enum xfrd_packet_result xfrd_handle_received_xfr_packet(
xfrd_zone_type* zone, buffer_type* packet);
void xfrd_set_timer(xfrd_zone_type* zone, time_t t);
void xfrd_set_refresh_now(xfrd_zone_type* zone);
void xfrd_unset_timer(xfrd_zone_type* zone);
void xfrd_deactivate_zone(xfrd_zone_type* z);
void xfrd_make_request(xfrd_zone_type* zone);
int xfrd_send_udp(struct acl_options* acl, buffer_type* packet,
struct acl_options* ifc);
int xfrd_udp_read_packet(buffer_type* packet, int fd, struct sockaddr* src,
socklen_t* srclen);
void xfrd_udp_release(xfrd_zone_type* zone);
struct buffer* xfrd_get_temp_buffer(void);
void xfrd_tsig_sign_request(buffer_type* packet, struct tsig_record* tsig,
struct acl_options* acl);
void xfrd_handle_incoming_soa(xfrd_zone_type* zone, xfrd_soa_type* soa,
time_t acquired);
void xfrd_handle_passed_packet(buffer_type* packet,
int acl_num, int acl_xfr);
void xfrd_reopen_logfile(void);
void xfrd_free_namedb(struct nsd* nsd);
void xfrd_copy_soa(xfrd_soa_type* soa, rr_type* rr);
void xfrd_check_failed_updates(void);
void
xfrd_prepare_updates_for_reload(void);
void xfrd_prepare_zones_for_reload(void);
int xfrd_bind_local_interface(int sockd, struct acl_options* ifc,
struct acl_options* acl, int tcp);
void xfrd_process_task_result(xfrd_state_type* xfrd, struct udb_base* taskudb);
void xfrd_set_reload_now(xfrd_state_type* xfrd);
void xfrd_send_expire_notification(xfrd_zone_type* zone);
void xfrd_handle_notify_and_start_xfr(xfrd_zone_type* zone, xfrd_soa_type* soa);
void xfrd_handle_zone(int fd, short event, void* arg);
const char* xfrd_pretty_time(time_t v);
xfrd_xfr_type *xfrd_prepare_zone_xfr(xfrd_zone_type *zone, uint16_t query_type);
void xfrd_delete_zone_xfr(xfrd_zone_type *zone, xfrd_xfr_type *xfr);
#endif