1 /* 2 * dnstap/dnstap_collector.c -- nsd collector process for dnstap information 3 * 4 * Copyright (c) 2018, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #include "config.h" 11 #include <sys/types.h> 12 #include <sys/socket.h> 13 #include <errno.h> 14 #include <fcntl.h> 15 #include <unistd.h> 16 #ifndef USE_MINI_EVENT 17 # ifdef HAVE_EVENT_H 18 # include <event.h> 19 # else 20 # include <event2/event.h> 21 # include "event2/event_struct.h" 22 # include "event2/event_compat.h" 23 # endif 24 #else 25 # include "mini_event.h" 26 #endif 27 #include "dnstap/dnstap_collector.h" 28 #include "dnstap/dnstap.h" 29 #include "util.h" 30 #include "nsd.h" 31 #include "region-allocator.h" 32 #include "buffer.h" 33 #include "namedb.h" 34 #include "options.h" 35 #include "remote.h" 36 37 #include "udb.h" 38 #include "rrl.h" 39 40 struct dt_collector* dt_collector_create(struct nsd* nsd) 41 { 42 int i, sv[2]; 43 struct dt_collector* dt_col = (struct dt_collector*)xalloc_zero( 44 sizeof(*dt_col)); 45 dt_col->count = nsd->child_count * 2; 46 dt_col->dt_env = NULL; 47 dt_col->region = region_create(xalloc, free); 48 dt_col->send_buffer = buffer_create(dt_col->region, 49 /* msglen + is_response + addrlen + is_tcp + packetlen + packet + zonelen + zone + spare + local_addr + addr */ 50 4+1+4+1+4+TCP_MAX_MESSAGE_LEN+4+MAXHOSTNAMELEN + 32 + 51 #ifdef INET6 52 sizeof(struct sockaddr_storage) + sizeof(struct sockaddr_storage) 53 #else 54 sizeof(struct sockaddr_in) + sizeof(struct sockaddr_in) 55 #endif 56 ); 57 58 /* open communication channels in struct nsd */ 59 nsd->dt_collector_fd_send = (int*)xalloc_array_zero(dt_col->count, 60 sizeof(int)); 61 nsd->dt_collector_fd_recv = (int*)xalloc_array_zero(dt_col->count, 62 sizeof(int)); 63 for(i=0; i<dt_col->count; i++) { 64 int sv[2]; 65 int bufsz = buffer_capacity(dt_col->send_buffer); 66 sv[0] = -1; /* For receiving by parent (dnstap-collector) */ 67 sv[1] = -1; /* For sending by child (server childs) */ 68 if(socketpair(AF_UNIX, SOCK_DGRAM 69 #ifdef SOCK_NONBLOCK 70 | SOCK_NONBLOCK 71 #endif 72 , 0, sv) < 0) { 73 error("dnstap_collector: cannot create communication channel: %s", 74 strerror(errno)); 75 } 76 #ifndef SOCK_NONBLOCK 77 if (fcntl(sv[0], F_SETFL, O_NONBLOCK) == -1) { 78 log_msg(LOG_ERR, "dnstap_collector receive fd fcntl " 79 "failed: %s", strerror(errno)); 80 } 81 if (fcntl(sv[1], F_SETFL, O_NONBLOCK) == -1) { 82 log_msg(LOG_ERR, "dnstap_collector send fd fcntl " 83 "failed: %s", strerror(errno)); 84 } 85 #endif 86 if(setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &bufsz, sizeof(bufsz))) { 87 log_msg(LOG_ERR, "setting dnstap_collector " 88 "receive buffer size failed: %s", strerror(errno)); 89 } 90 if(setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &bufsz, sizeof(bufsz))) { 91 log_msg(LOG_ERR, "setting dnstap_collector " 92 "send buffer size failed: %s", strerror(errno)); 93 } 94 nsd->dt_collector_fd_recv[i] = sv[0]; 95 nsd->dt_collector_fd_send[i] = sv[1]; 96 } 97 nsd->dt_collector_fd_swap = nsd->dt_collector_fd_send + nsd->child_count; 98 99 /* open socketpair */ 100 if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) { 101 error("dnstap_collector: cannot create socketpair: %s", 102 strerror(errno)); 103 } 104 if(fcntl(sv[0], F_SETFL, O_NONBLOCK) == -1) { 105 log_msg(LOG_ERR, "fcntl failed: %s", strerror(errno)); 106 } 107 if(fcntl(sv[1], F_SETFL, O_NONBLOCK) == -1) { 108 log_msg(LOG_ERR, "fcntl failed: %s", strerror(errno)); 109 } 110 dt_col->cmd_socket_dt = sv[0]; 111 dt_col->cmd_socket_nsd = sv[1]; 112 113 return dt_col; 114 } 115 116 void dt_collector_destroy(struct dt_collector* dt_col, struct nsd* nsd) 117 { 118 if(!dt_col) return; 119 free(nsd->dt_collector_fd_recv); 120 nsd->dt_collector_fd_recv = NULL; 121 if (nsd->dt_collector_fd_send < nsd->dt_collector_fd_swap) 122 free(nsd->dt_collector_fd_send); 123 else 124 free(nsd->dt_collector_fd_swap); 125 nsd->dt_collector_fd_send = NULL; 126 nsd->dt_collector_fd_swap = NULL; 127 region_destroy(dt_col->region); 128 free(dt_col); 129 } 130 131 void dt_collector_close(struct dt_collector* dt_col, struct nsd* nsd) 132 { 133 int i, *fd_send; 134 if(!dt_col) return; 135 if(dt_col->cmd_socket_dt != -1) { 136 close(dt_col->cmd_socket_dt); 137 dt_col->cmd_socket_dt = -1; 138 } 139 if(dt_col->cmd_socket_nsd != -1) { 140 close(dt_col->cmd_socket_nsd); 141 dt_col->cmd_socket_nsd = -1; 142 } 143 fd_send = nsd->dt_collector_fd_send < nsd->dt_collector_fd_swap 144 ? nsd->dt_collector_fd_send : nsd->dt_collector_fd_swap; 145 for(i=0; i<dt_col->count; i++) { 146 if(nsd->dt_collector_fd_recv[i] != -1) { 147 close(nsd->dt_collector_fd_recv[i]); 148 nsd->dt_collector_fd_recv[i] = -1; 149 } 150 if(fd_send[i] != -1) { 151 close(fd_send[i]); 152 fd_send[i] = -1; 153 } 154 } 155 } 156 157 /* handle command from nsd to dt collector. 158 * mostly, check for fd closed, this means we have to exit */ 159 void 160 dt_handle_cmd_from_nsd(int ATTR_UNUSED(fd), short event, void* arg) 161 { 162 struct dt_collector* dt_col = (struct dt_collector*)arg; 163 if((event&EV_READ) != 0) { 164 event_base_loopexit(dt_col->event_base, NULL); 165 } 166 } 167 168 /* receive data from fd into buffer, 1 when message received, -1 on error */ 169 static int recv_into_buffer(int fd, struct buffer* buf) 170 { 171 size_t msglen; 172 ssize_t r; 173 174 assert(buffer_position(buf) == 0); 175 r = recv(fd, buffer_current(buf), buffer_capacity(buf), MSG_DONTWAIT); 176 if(r == -1) { 177 if(errno == EAGAIN || errno == EINTR || errno == EMSGSIZE) { 178 /* continue to receive a message later */ 179 return 0; 180 } 181 log_msg(LOG_ERR, "dnstap collector: receive failed: %s", 182 strerror(errno)); 183 return -1; 184 } 185 if(r == 0) { 186 /* Remote end closed the connection? */ 187 log_msg(LOG_ERR, "dnstap collector: remote closed connection"); 188 return -1; 189 } 190 assert(r > 4); 191 msglen = buffer_read_u32_at(buf, 0); 192 if(msglen != (size_t)(r - 4)) { 193 /* Is this still possible now the communication channel is of 194 * type SOCK_DGRAM? I think not, but better safe than sorry. */ 195 log_msg(LOG_ERR, "dnstap collector: out of sync (msglen: %u)", 196 (unsigned int) msglen); 197 return 0; 198 } 199 buffer_skip(buf, r); 200 buffer_flip(buf); 201 return 1; 202 } 203 204 /* submit the content of the buffer received to dnstap */ 205 static void 206 dt_submit_content(struct dt_env* dt_env, struct buffer* buf) 207 { 208 uint8_t is_response, is_tcp; 209 #ifdef INET6 210 struct sockaddr_storage local_addr, addr; 211 #else 212 struct sockaddr_in local_addr, addr; 213 #endif 214 socklen_t addrlen; 215 size_t pktlen; 216 uint8_t* data; 217 size_t zonelen; 218 uint8_t* zone; 219 220 /* parse content from buffer */ 221 if(!buffer_available(buf, 4+1+4)) return; 222 buffer_skip(buf, 4); /* skip msglen */ 223 is_response = buffer_read_u8(buf); 224 addrlen = buffer_read_u32(buf); 225 if(addrlen > sizeof(local_addr) || addrlen > sizeof(addr)) return; 226 if(!buffer_available(buf, 2*addrlen)) return; 227 buffer_read(buf, &local_addr, addrlen); 228 buffer_read(buf, &addr, addrlen); 229 if(!buffer_available(buf, 1+4)) return; 230 is_tcp = buffer_read_u8(buf); 231 pktlen = buffer_read_u32(buf); 232 if(!buffer_available(buf, pktlen)) return; 233 data = buffer_current(buf); 234 buffer_skip(buf, pktlen); 235 if(!buffer_available(buf, 4)) return; 236 zonelen = buffer_read_u32(buf); 237 if(zonelen == 0) { 238 zone = NULL; 239 } else { 240 if(zonelen > MAXDOMAINLEN) return; 241 if(!buffer_available(buf, zonelen)) return; 242 zone = buffer_current(buf); 243 buffer_skip(buf, zonelen); 244 } 245 246 /* submit it */ 247 if(is_response) { 248 dt_msg_send_auth_response(dt_env, &local_addr, &addr, is_tcp, zone, 249 zonelen, data, pktlen); 250 } else { 251 dt_msg_send_auth_query(dt_env, &local_addr, &addr, is_tcp, zone, 252 zonelen, data, pktlen); 253 } 254 } 255 256 /* handle input from worker for dnstap */ 257 void 258 dt_handle_input(int fd, short event, void* arg) 259 { 260 struct dt_collector_input* dt_input = (struct dt_collector_input*)arg; 261 if((event&EV_READ) != 0) { 262 /* receive */ 263 int r = recv_into_buffer(fd, dt_input->buffer); 264 if(r == 0) 265 return; 266 else if(r < 0) { 267 event_base_loopexit(dt_input->dt_collector->event_base, NULL); 268 return; 269 } 270 /* once data is complete, send it to dnstap */ 271 VERBOSITY(4, (LOG_INFO, "dnstap collector: received msg len %d", 272 (int)buffer_remaining(dt_input->buffer))); 273 if(dt_input->dt_collector->dt_env) { 274 dt_submit_content(dt_input->dt_collector->dt_env, 275 dt_input->buffer); 276 } 277 278 /* clear buffer for next message */ 279 buffer_clear(dt_input->buffer); 280 } 281 } 282 283 /* init dnstap */ 284 static void dt_init_dnstap(struct dt_collector* dt_col, struct nsd* nsd) 285 { 286 int num_workers = 1; 287 #ifdef HAVE_CHROOT 288 if(nsd->chrootdir && nsd->chrootdir[0]) { 289 int l = strlen(nsd->chrootdir)-1; /* ends in trailing slash */ 290 if (nsd->options->dnstap_socket_path && 291 nsd->options->dnstap_socket_path[0] == '/' && 292 strncmp(nsd->options->dnstap_socket_path, 293 nsd->chrootdir, l) == 0) 294 nsd->options->dnstap_socket_path += l; 295 } 296 #endif 297 dt_col->dt_env = dt_create(nsd->options->dnstap_socket_path, 298 nsd->options->dnstap_ip, num_workers, nsd->options->dnstap_tls, 299 nsd->options->dnstap_tls_server_name, 300 nsd->options->dnstap_tls_cert_bundle, 301 nsd->options->dnstap_tls_client_key_file, 302 nsd->options->dnstap_tls_client_cert_file); 303 if(!dt_col->dt_env) { 304 log_msg(LOG_ERR, "could not create dnstap env"); 305 return; 306 } 307 dt_apply_cfg(dt_col->dt_env, nsd->options); 308 dt_init(dt_col->dt_env); 309 } 310 311 /* cleanup dt collector process for exit */ 312 static void dt_collector_cleanup(struct dt_collector* dt_col, struct nsd* nsd) 313 { 314 int i; 315 dt_delete(dt_col->dt_env); 316 event_del(dt_col->cmd_event); 317 for(i=0; i<dt_col->count; i++) { 318 event_del(dt_col->inputs[i].event); 319 } 320 dt_collector_close(dt_col, nsd); 321 event_base_free(dt_col->event_base); 322 #ifdef MEMCLEAN 323 free(dt_col->cmd_event); 324 if(dt_col->inputs) { 325 for(i=0; i<dt_col->count; i++) { 326 free(dt_col->inputs[i].event); 327 } 328 free(dt_col->inputs); 329 } 330 dt_collector_destroy(dt_col, nsd); 331 daemon_remote_delete(nsd->rc); /* ssl-delete secret keys */ 332 nsd_options_destroy(nsd->options); 333 region_destroy(nsd->region); 334 #endif 335 } 336 337 /* attach events to the event base to listen to the workers and cmd channel */ 338 static void dt_attach_events(struct dt_collector* dt_col, struct nsd* nsd) 339 { 340 int i; 341 /* create event base */ 342 dt_col->event_base = nsd_child_event_base(); 343 if(!dt_col->event_base) { 344 error("dnstap collector: event_base create failed"); 345 } 346 347 /* add command handler */ 348 dt_col->cmd_event = (struct event*)xalloc_zero( 349 sizeof(*dt_col->cmd_event)); 350 event_set(dt_col->cmd_event, dt_col->cmd_socket_dt, 351 EV_PERSIST|EV_READ, dt_handle_cmd_from_nsd, dt_col); 352 if(event_base_set(dt_col->event_base, dt_col->cmd_event) != 0) 353 log_msg(LOG_ERR, "dnstap collector: event_base_set failed"); 354 if(event_add(dt_col->cmd_event, NULL) != 0) 355 log_msg(LOG_ERR, "dnstap collector: event_add failed"); 356 357 /* add worker input handlers */ 358 dt_col->inputs = xalloc_array_zero(dt_col->count, 359 sizeof(*dt_col->inputs)); 360 for(i=0; i<dt_col->count; i++) { 361 dt_col->inputs[i].dt_collector = dt_col; 362 dt_col->inputs[i].event = (struct event*)xalloc_zero( 363 sizeof(struct event)); 364 event_set(dt_col->inputs[i].event, 365 nsd->dt_collector_fd_recv[i], EV_PERSIST|EV_READ, 366 dt_handle_input, &dt_col->inputs[i]); 367 if(event_base_set(dt_col->event_base, 368 dt_col->inputs[i].event) != 0) 369 log_msg(LOG_ERR, "dnstap collector: event_base_set failed"); 370 if(event_add(dt_col->inputs[i].event, NULL) != 0) 371 log_msg(LOG_ERR, "dnstap collector: event_add failed"); 372 373 dt_col->inputs[i].buffer = buffer_create(dt_col->region, 374 /* msglen + is_response + addrlen + is_tcp + packetlen + packet + zonelen + zone + spare + local_addr + addr */ 375 4+1+4+1+4+TCP_MAX_MESSAGE_LEN+4+MAXHOSTNAMELEN + 32 + 376 #ifdef INET6 377 sizeof(struct sockaddr_storage) + sizeof(struct sockaddr_storage) 378 #else 379 sizeof(struct sockaddr_in) + sizeof(struct sockaddr_in) 380 #endif 381 ); 382 assert(buffer_capacity(dt_col->inputs[i].buffer) == 383 buffer_capacity(dt_col->send_buffer)); 384 } 385 } 386 387 /* the dnstap collector process main routine */ 388 static void dt_collector_run(struct dt_collector* dt_col, struct nsd* nsd) 389 { 390 /* init dnstap */ 391 VERBOSITY(1, (LOG_INFO, "dnstap collector started")); 392 dt_init_dnstap(dt_col, nsd); 393 dt_attach_events(dt_col, nsd); 394 395 /* run */ 396 if(event_base_loop(dt_col->event_base, 0) == -1) { 397 error("dnstap collector: event_base_loop failed"); 398 } 399 400 /* cleanup and done */ 401 VERBOSITY(1, (LOG_INFO, "dnstap collector stopped")); 402 dt_collector_cleanup(dt_col, nsd); 403 exit(0); 404 } 405 406 void dt_collector_start(struct dt_collector* dt_col, struct nsd* nsd) 407 { 408 int i, *fd_send; 409 /* fork */ 410 dt_col->dt_pid = fork(); 411 if(dt_col->dt_pid == -1) { 412 error("dnstap_collector: fork failed: %s", strerror(errno)); 413 } 414 if(dt_col->dt_pid == 0) { 415 /* the dt collector process is this */ 416 /* close the nsd side of the command channel */ 417 close(dt_col->cmd_socket_nsd); 418 dt_col->cmd_socket_nsd = -1; 419 420 /* close the send side of the communication channels */ 421 assert(nsd->dt_collector_fd_send < nsd->dt_collector_fd_swap); 422 fd_send = nsd->dt_collector_fd_send < nsd->dt_collector_fd_swap 423 ? nsd->dt_collector_fd_send : nsd->dt_collector_fd_swap; 424 for(i=0; i<dt_col->count; i++) { 425 if(fd_send[i] != -1) { 426 close(fd_send[i]); 427 fd_send[i] = -1; 428 } 429 } 430 #ifdef HAVE_SETPROCTITLE 431 setproctitle("dnstap_collector"); 432 #endif 433 #ifdef USE_LOG_PROCESS_ROLE 434 log_set_process_role("dnstap_collector"); 435 #endif 436 /* Free serve process specific memory pages */ 437 #ifdef RATELIMIT 438 rrl_mmap_deinit_keep_mmap(); 439 #endif 440 udb_base_free_keep_mmap(nsd->task[0]); 441 udb_base_free_keep_mmap(nsd->task[1]); 442 namedb_close(nsd->db); 443 444 dt_collector_run(dt_col, nsd); 445 /* NOTREACH */ 446 exit(0); 447 } else { 448 /* the parent continues on, with starting NSD */ 449 /* close the dt side of the command channel */ 450 close(dt_col->cmd_socket_dt); 451 dt_col->cmd_socket_dt = -1; 452 453 /* close the receive side of the communication channels */ 454 for(i=0; i<dt_col->count; i++) { 455 if(nsd->dt_collector_fd_recv[i] != -1) { 456 close(nsd->dt_collector_fd_recv[i]); 457 nsd->dt_collector_fd_recv[i] = -1; 458 } 459 } 460 } 461 } 462 463 /* put data for sending to the collector process into the buffer */ 464 static int 465 prep_send_data(struct buffer* buf, uint8_t is_response, 466 #ifdef INET6 467 struct sockaddr_storage* local_addr, 468 struct sockaddr_storage* addr, 469 #else 470 struct sockaddr_in* local_addr, 471 struct sockaddr_in* addr, 472 #endif 473 socklen_t addrlen, int is_tcp, struct buffer* packet, 474 struct zone* zone) 475 { 476 buffer_clear(buf); 477 #ifdef INET6 478 if(local_addr->ss_family != addr->ss_family) 479 return 0; /* must be same length to send */ 480 #else 481 if(local_addr->sin_family != addr->sin_family) 482 return 0; /* must be same length to send */ 483 #endif 484 if(!buffer_available(buf, 4+1+4+2*addrlen+1+4+buffer_remaining(packet))) 485 return 0; /* does not fit in send_buffer, log is dropped */ 486 buffer_skip(buf, 4); /* the length of the message goes here */ 487 buffer_write_u8(buf, is_response); 488 buffer_write_u32(buf, addrlen); 489 buffer_write(buf, local_addr, (size_t)addrlen); 490 buffer_write(buf, addr, (size_t)addrlen); 491 buffer_write_u8(buf, (is_tcp?1:0)); 492 buffer_write_u32(buf, buffer_remaining(packet)); 493 buffer_write(buf, buffer_begin(packet), buffer_remaining(packet)); 494 if(zone && zone->apex && domain_dname(zone->apex)) { 495 if(!buffer_available(buf, 4 + domain_dname(zone->apex)->name_size)) 496 return 0; 497 buffer_write_u32(buf, domain_dname(zone->apex)->name_size); 498 buffer_write(buf, dname_name(domain_dname(zone->apex)), 499 domain_dname(zone->apex)->name_size); 500 } else { 501 if(!buffer_available(buf, 4)) 502 return 0; 503 buffer_write_u32(buf, 0); 504 } 505 506 buffer_flip(buf); 507 /* write length of message */ 508 buffer_write_u32_at(buf, 0, buffer_remaining(buf)-4); 509 return 1; 510 } 511 512 /* attempt to send buffer to socket, if it blocks do not send it. 513 * return 0 on success, -1 on error */ 514 static int attempt_to_send(int s, uint8_t* data, size_t len) 515 { 516 ssize_t r; 517 if(len == 0) 518 return 0; 519 r = send(s, data, len, MSG_DONTWAIT | MSG_NOSIGNAL); 520 if(r == -1) { 521 if(errno == EAGAIN || errno == EINTR || 522 errno == ENOBUFS || errno == EMSGSIZE) { 523 /* check if pipe is full, if the nonblocking fd blocks, 524 * then drop the message */ 525 return 0; 526 } 527 /* some sort of error, print it */ 528 log_msg(LOG_ERR, "dnstap collector: send failed: %s", 529 strerror(errno)); 530 return -1; 531 } 532 assert(r > 0); 533 if(r > 0) { 534 assert((size_t)r == len); 535 return 0; 536 } 537 /* Other end closed the channel? */ 538 log_msg(LOG_ERR, "dnstap collector: server child closed the channel"); 539 return -1; 540 } 541 542 void dt_collector_submit_auth_query(struct nsd* nsd, 543 #ifdef INET6 544 struct sockaddr_storage* local_addr, 545 struct sockaddr_storage* addr, 546 #else 547 struct sockaddr_in* local_addr, 548 struct sockaddr_in* addr, 549 #endif 550 socklen_t addrlen, int is_tcp, struct buffer* packet) 551 { 552 if(!nsd->dt_collector) return; 553 if(!nsd->options->dnstap_log_auth_query_messages) return; 554 if(nsd->dt_collector_fd_send[nsd->this_child->child_num] == -1) return; 555 VERBOSITY(4, (LOG_INFO, "dnstap submit auth query")); 556 557 /* marshal data into send buffer */ 558 if(!prep_send_data(nsd->dt_collector->send_buffer, 0, local_addr, addr, addrlen, 559 is_tcp, packet, NULL)) 560 return; /* probably did not fit in buffer */ 561 562 /* attempt to send data; do not block */ 563 if(attempt_to_send(nsd->dt_collector_fd_send[nsd->this_child->child_num], 564 buffer_begin(nsd->dt_collector->send_buffer), 565 buffer_remaining(nsd->dt_collector->send_buffer))) { 566 /* Something went wrong sending to the socket. Don't send to 567 * this socket again. */ 568 close(nsd->dt_collector_fd_send[nsd->this_child->child_num]); 569 nsd->dt_collector_fd_send[nsd->this_child->child_num] = -1; 570 } 571 } 572 573 void dt_collector_submit_auth_response(struct nsd* nsd, 574 #ifdef INET6 575 struct sockaddr_storage* local_addr, 576 struct sockaddr_storage* addr, 577 #else 578 struct sockaddr_in* local_addr, 579 struct sockaddr_in* addr, 580 #endif 581 socklen_t addrlen, int is_tcp, struct buffer* packet, 582 struct zone* zone) 583 { 584 if(!nsd->dt_collector) return; 585 if(!nsd->options->dnstap_log_auth_response_messages) return; 586 if(nsd->dt_collector_fd_send[nsd->this_child->child_num] == -1) return; 587 VERBOSITY(4, (LOG_INFO, "dnstap submit auth response")); 588 589 /* marshal data into send buffer */ 590 if(!prep_send_data(nsd->dt_collector->send_buffer, 1, local_addr, addr, addrlen, 591 is_tcp, packet, zone)) 592 return; /* probably did not fit in buffer */ 593 594 /* attempt to send data; do not block */ 595 if(attempt_to_send(nsd->dt_collector_fd_send[nsd->this_child->child_num], 596 buffer_begin(nsd->dt_collector->send_buffer), 597 buffer_remaining(nsd->dt_collector->send_buffer))) { 598 /* Something went wrong sending to the socket. Don't send to 599 * this socket again. */ 600 close(nsd->dt_collector_fd_send[nsd->this_child->child_num]); 601 nsd->dt_collector_fd_send[nsd->this_child->child_num] = -1; 602 } 603 } 604