Skip to content

Commit

Permalink
Merge branch 'bugfix/bad-xfr-with-other-tasks2'
Browse files Browse the repository at this point in the history
  • Loading branch information
wtoorop committed Oct 23, 2024
2 parents c75cab0 + 62c40f0 commit 1f2a015
Show file tree
Hide file tree
Showing 25 changed files with 558 additions and 287 deletions.
17 changes: 7 additions & 10 deletions difffile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1276,8 +1276,7 @@ check_for_bad_serial(namedb_type* db, const char* zone_str, uint32_t old_serial)

int
apply_ixfr_for_zone(nsd_type* nsd, zone_type* zone, FILE* in,
struct nsd_options* ATTR_UNUSED(opt), udb_base* taskudb, udb_ptr* last_task,
uint32_t xfrfilenr)
struct nsd_options* ATTR_UNUSED(opt), udb_base* taskudb, uint32_t xfrfilenr)
{
char zone_buf[3072];
char log_buf[5120];
Expand All @@ -1289,7 +1288,6 @@ apply_ixfr_for_zone(nsd_type* nsd, zone_type* zone, FILE* in,
uint8_t committed;
uint32_t i;
int num_bytes = 0;
(void)last_task;
assert(zone);

/* read zone name and serial */
Expand Down Expand Up @@ -2027,9 +2025,8 @@ task_process_zonestat_inc(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
}
#endif

static void
task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
udb_ptr* task)
void
task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr* task)
{
/* we have to use an udb_ptr task here, because the apply_xfr procedure
* appends soa_info which may remap and change the pointer. */
Expand All @@ -2041,6 +2038,7 @@ task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
if(!zone) {
/* assume the zone has been deleted and a zone transfer was
* still waiting to be processed */
udb_ptr_free_space(task, udb, TASKLIST(task)->size);
return;
}

Expand All @@ -2052,10 +2050,11 @@ task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
/* soainfo_gone will be communicated from server_reload, unless
preceding updates have been applied */
zone->is_skipped = 1;
udb_ptr_free_space(task, udb, TASKLIST(task)->size);
return;
}
/* read and apply zone transfer */
switch(apply_ixfr_for_zone(nsd, zone, df, nsd->options, udb, last_task,
switch(apply_ixfr_for_zone(nsd, zone, df, nsd->options, udb,
TASKLIST(task)->yesno)) {
case 1: /* Success */
break;
Expand All @@ -2073,6 +2072,7 @@ task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
default:break;
}
fclose(df);
udb_ptr_free_space(task, udb, TASKLIST(task)->size);
}


Expand Down Expand Up @@ -2118,9 +2118,6 @@ void task_process_in_reload(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
task_process_zonestat_inc(nsd, udb, last_task, TASKLIST(task));
break;
#endif
case task_apply_xfr:
task_process_apply_xfr(nsd, udb, last_task, task);
break;
case task_cookies:
task_process_cookies(nsd, TASKLIST(task));
break;
Expand Down
4 changes: 2 additions & 2 deletions difffile.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ int add_RR(namedb_type* db, const dname_type* dname,

/* apply the xfr file identified by xfrfilenr to zone */
int apply_ixfr_for_zone(struct nsd* nsd, zone_type* zone, FILE* in,
struct nsd_options* opt, udb_base* taskudb, udb_ptr* last_task,
uint32_t xfrfilenr);
struct nsd_options* opt, udb_base* taskudb, uint32_t xfrfilenr);

enum soainfo_hint {
soainfo_ok,
Expand Down Expand Up @@ -152,6 +151,7 @@ void task_new_cookies(udb_base* udb, udb_ptr* last, int answer_cookie,
size_t cookie_count, void* cookie_secrets);
int task_new_apply_xfr(udb_base* udb, udb_ptr* last, const dname_type* zone,
uint32_t old_serial, uint32_t new_serial, uint64_t filenumber);
void task_process_apply_xfr(struct nsd* nsd, udb_base* udb, udb_ptr *task);
void task_process_in_reload(struct nsd* nsd, udb_base* udb, udb_ptr *last_task,
udb_ptr* task);
void task_process_expire(namedb_type* db, struct task_list_d* task);
Expand Down
3 changes: 3 additions & 0 deletions dnstap/dnstap_collector.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,9 @@ void dt_collector_start(struct dt_collector* dt_col, struct nsd* nsd)
}
#ifdef HAVE_SETPROCTITLE
setproctitle("dnstap_collector");
#endif
#ifdef USE_LOG_PROCESS_ROLE
log_set_process_role("dnstap_collector");
#endif
/* Free serve process specific memory pages */
#ifdef RATELIMIT
Expand Down
209 changes: 33 additions & 176 deletions ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,31 +166,6 @@ send_stat_to_child(struct main_ipc_handler_data* data, int fd)
data->child->need_to_send_STATS = 0;
}

#ifndef NDEBUG
int packet_read_query_section(buffer_type *packet, uint8_t* dest, uint16_t* qtype, uint16_t* qclass);
static void
debug_print_fwd_name(int ATTR_UNUSED(len), buffer_type* packet, int acl_num)
{
uint8_t qnamebuf[MAXDOMAINLEN];
uint16_t qtype, qclass;
const dname_type* dname;
region_type* tempregion = region_create(xalloc, free);

size_t bufpos = buffer_position(packet);
buffer_rewind(packet);
buffer_skip(packet, 12);
if(packet_read_query_section(packet, qnamebuf, &qtype, &qclass)) {
dname = dname_make(tempregion, qnamebuf, 1);
log_msg(LOG_INFO, "main: fwd packet for %s, acl %d",
dname_to_string(dname,0), acl_num);
} else {
log_msg(LOG_INFO, "main: fwd packet badqname, acl %d", acl_num);
}
buffer_set_position(packet, bufpos);
region_destroy(tempregion);
}
#endif

static void
send_quit_to_child(struct main_ipc_handler_data* data, int fd)
{
Expand Down Expand Up @@ -332,95 +307,6 @@ parent_handle_child_command(netio_type *ATTR_UNUSED(netio),
return;
}

if (data->forward_mode) {
int got_acl;
/* forward the data to xfrd */
DEBUG(DEBUG_IPC,2, (LOG_INFO,
"main passed packet readup %d", (int)data->got_bytes));
if(data->got_bytes < sizeof(data->total_bytes))
{
if ((len = read(handler->fd,
(char*)&data->total_bytes+data->got_bytes,
sizeof(data->total_bytes)-data->got_bytes)) == -1) {
log_msg(LOG_ERR, "handle_child_command: read: %s",
strerror(errno));
return;
}
if(len == 0) {
/* EOF */
data->forward_mode = 0;
return;
}
data->got_bytes += len;
if(data->got_bytes < sizeof(data->total_bytes))
return;
data->total_bytes = ntohs(data->total_bytes);
buffer_clear(data->packet);
if(data->total_bytes > buffer_capacity(data->packet)) {
log_msg(LOG_ERR, "internal error: ipc too large");
exit(1);
}
return;
}
/* read the packet */
if(data->got_bytes-sizeof(data->total_bytes) < data->total_bytes) {
if((len = read(handler->fd, buffer_current(data->packet),
data->total_bytes - (data->got_bytes-sizeof(data->total_bytes))
)) == -1 ) {
log_msg(LOG_ERR, "handle_child_command: read: %s",
strerror(errno));
return;
}
if(len == 0) {
/* EOF */
data->forward_mode = 0;
return;
}
data->got_bytes += len;
buffer_skip(data->packet, len);
/* read rest later */
return;
}
/* read the acl numbers */
got_acl = data->got_bytes - sizeof(data->total_bytes) - data->total_bytes;
if((len = read(handler->fd, (char*)&data->acl_num+got_acl,
sizeof(data->acl_num)+sizeof(data->acl_xfr)-got_acl)) == -1 ) {
log_msg(LOG_ERR, "handle_child_command: read: %s",
strerror(errno));
return;
}
if(len == 0) {
/* EOF */
data->forward_mode = 0;
return;
}
got_acl += len;
data->got_bytes += len;
if(got_acl >= (int)(sizeof(data->acl_num)+sizeof(data->acl_xfr))) {
uint16_t len = htons(data->total_bytes);
DEBUG(DEBUG_IPC,2, (LOG_INFO,
"main fwd passed packet write %d", (int)data->got_bytes));
#ifndef NDEBUG
if(nsd_debug_level >= 2)
debug_print_fwd_name(len, data->packet, data->acl_num);
#endif
data->forward_mode = 0;
mode = NSD_PASS_TO_XFRD;
if(!write_socket(*data->xfrd_sock, &mode, sizeof(mode)) ||
!write_socket(*data->xfrd_sock, &len, sizeof(len)) ||
!write_socket(*data->xfrd_sock, buffer_begin(data->packet),
data->total_bytes) ||
!write_socket(*data->xfrd_sock, &data->acl_num,
sizeof(data->acl_num)) ||
!write_socket(*data->xfrd_sock, &data->acl_xfr,
sizeof(data->acl_xfr))) {
log_msg(LOG_ERR, "error in ipc fwd main2xfrd: %s",
strerror(errno));
}
}
return;
}

/* read command from ipc */
if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) {
log_msg(LOG_ERR, "handle_child_command: read: %s",
Expand All @@ -443,12 +329,6 @@ parent_handle_child_command(netio_type *ATTR_UNUSED(netio),
case NSD_REAP_CHILDREN:
data->nsd->signal_hint_child = 1;
break;
case NSD_PASS_TO_XFRD:
/* set mode for handle_child_command; echo to xfrd. */
data->forward_mode = 1;
data->got_bytes = 0;
data->total_bytes = 0;
break;
default:
log_msg(LOG_ERR, "handle_child_command: bad mode %d",
(int) mode);
Expand Down Expand Up @@ -651,52 +531,6 @@ xfrd_handle_ipc_read(struct event* handler, xfrd_state_type* xfrd)
sig_atomic_t cmd;
int len;

if(xfrd->ipc_conn->is_reading==2) {
buffer_type* tmp = xfrd->ipc_pass;
uint32_t acl_num;
int32_t acl_xfr;
/* read acl_num */
int ret = conn_read(xfrd->ipc_conn);
if(ret == -1) {
log_msg(LOG_ERR, "xfrd: error in read ipc: %s", strerror(errno));
xfrd->ipc_conn->is_reading = 0;
return;
}
if(ret == 0)
return;
buffer_flip(xfrd->ipc_conn->packet);
xfrd->ipc_pass = xfrd->ipc_conn->packet;
xfrd->ipc_conn->packet = tmp;
xfrd->ipc_conn->is_reading = 0;
acl_num = buffer_read_u32(xfrd->ipc_pass);
acl_xfr = (int32_t)buffer_read_u32(xfrd->ipc_pass);
xfrd_handle_passed_packet(xfrd->ipc_conn->packet, acl_num, acl_xfr);
return;
}
if(xfrd->ipc_conn->is_reading) {
/* reading an IPC message */
buffer_type* tmp;
int ret = conn_read(xfrd->ipc_conn);
if(ret == -1) {
log_msg(LOG_ERR, "xfrd: error in read ipc: %s", strerror(errno));
xfrd->ipc_conn->is_reading = 0;
return;
}
if(ret == 0)
return;
buffer_flip(xfrd->ipc_conn->packet);
/* use ipc_conn to read remaining data as well */
tmp = xfrd->ipc_pass;
xfrd->ipc_conn->is_reading=2;
xfrd->ipc_pass = xfrd->ipc_conn->packet;
xfrd->ipc_conn->packet = tmp;
xfrd->ipc_conn->total_bytes = sizeof(xfrd->ipc_conn->msglen);
xfrd->ipc_conn->msglen = 2*sizeof(uint32_t);
buffer_clear(xfrd->ipc_conn->packet);
buffer_set_limit(xfrd->ipc_conn->packet, xfrd->ipc_conn->msglen);
return;
}

if((len = read(handler->ev_fd, &cmd, sizeof(cmd))) == -1) {
if(errno != EINTR && errno != EAGAIN)
log_msg(LOG_ERR, "xfrd_handle_ipc: read: %s",
Expand Down Expand Up @@ -747,10 +581,6 @@ xfrd_handle_ipc_read(struct event* handler, xfrd_state_type* xfrd)
xfrd_prepare_zones_for_reload();
xfrd->reload_failed = 0;
break;
case NSD_PASS_TO_XFRD:
DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv PASS_TO_XFRD"));
xfrd->ipc_conn->is_reading = 1;
break;
case NSD_RELOAD_REQ:
DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv RELOAD_REQ"));
/* make reload happen, right away, and schedule file check */
Expand All @@ -769,11 +599,38 @@ xfrd_handle_ipc_read(struct event* handler, xfrd_state_type* xfrd)
(int)ntohl(cmd));
break;
}
}

if(xfrd->ipc_conn->is_reading) {
/* setup read of info */
xfrd->ipc_conn->total_bytes = 0;
xfrd->ipc_conn->msglen = 0;
buffer_clear(xfrd->ipc_conn->packet);
}
void
xfrd_handle_notify(int ATTR_UNUSED(fd), short event, void* arg)
{
struct xfrd_tcp* notify_pipe = (struct xfrd_tcp*)arg;
uint32_t acl_num;
int32_t acl_xfr;

if(!(event & EV_READ))
return;

switch(conn_read(notify_pipe)){
case -1: /* TODO: What to do here? */
return;
case 0: return; /* call back later */
default: break;
}
if(buffer_limit(notify_pipe->packet) < sizeof(acl_xfr)+sizeof(acl_num))
log_msg(LOG_ERR, "xfrd_handle_notify invalid message size");
else {
size_t eop = buffer_position(notify_pipe->packet)
- sizeof(acl_xfr) - sizeof(acl_num);

buffer_set_position(notify_pipe->packet, eop);
acl_num = buffer_read_u32(notify_pipe->packet);
acl_xfr = (int32_t)buffer_read_u32(notify_pipe->packet);
buffer_set_position(notify_pipe->packet, eop);
buffer_flip(notify_pipe->packet);
xfrd_handle_passed_packet(notify_pipe->packet,acl_num,acl_xfr);
}
notify_pipe->total_bytes = 0;
notify_pipe->msglen = 0;
buffer_clear(notify_pipe->packet);
}
13 changes: 3 additions & 10 deletions ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,6 @@ struct main_ipc_handler_data
{
struct nsd *nsd;
struct nsd_child *child;
int child_num;

/* pointer to the socket, as it may change if it is restarted */
int *xfrd_sock;
struct buffer *packet;
int forward_mode;
size_t got_bytes;
uint16_t total_bytes;
uint32_t acl_num;
int32_t acl_xfr;
};

/*
Expand Down Expand Up @@ -84,6 +74,9 @@ void child_handle_parent_command(int fd, short event, void* arg);
*/
void xfrd_handle_ipc(int fd, short event, void* arg);

/* receive incoming notifies received by and from the serve processes */
void xfrd_handle_notify(int fd, short event, void* arg);

/* check if all children have exited in an orderly fashion and set mode */
void parent_check_all_children_exited(struct nsd* nsd);

Expand Down
Loading

0 comments on commit 1f2a015

Please sign in to comment.