1 /* 2 * ipc.c - Interprocess communication routines. Handlers read and write. 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #include "config.h" 11 #include <errno.h> 12 #include <unistd.h> 13 #include <stdlib.h> 14 #include <fcntl.h> 15 #include "ipc.h" 16 #include "buffer.h" 17 #include "xfrd-tcp.h" 18 #include "nsd.h" 19 #include "namedb.h" 20 #include "xfrd.h" 21 #include "xfrd-notify.h" 22 #include "difffile.h" 23 #include "rrl.h" 24 25 /* attempt to send NSD_STATS command to child fd */ 26 static void send_stat_to_child(struct main_ipc_handler_data* data, int fd); 27 /* send reload request over the IPC channel */ 28 static void xfrd_send_reload_req(xfrd_state_type* xfrd); 29 /* send quit request over the IPC channel */ 30 static void xfrd_send_quit_req(xfrd_state_type* xfrd); 31 /* perform read part of handle ipc for xfrd */ 32 static void xfrd_handle_ipc_read(struct event* handler, xfrd_state_type* xfrd); 33 static void ipc_child_quit(struct nsd* nsd) ATTR_NORETURN; 34 35 static void 36 ipc_child_quit(struct nsd* nsd) 37 { 38 /* call shutdown and quit routines */ 39 nsd->mode = NSD_QUIT; 40 service_remaining_tcp(nsd); 41 #ifdef BIND8_STATS 42 bind8_stats(nsd); 43 #endif /* BIND8_STATS */ 44 45 #ifdef MEMCLEAN /* OS collects memory pages */ 46 #ifdef RATELIMIT 47 rrl_deinit(nsd->this_child->child_num); 48 #endif 49 event_base_free(nsd->event_base); 50 region_destroy(nsd->server_region); 51 #endif 52 server_shutdown(nsd); 53 /* ENOTREACH */ 54 exit(0); 55 } 56 57 void 58 child_handle_parent_command(int fd, short event, void* arg) 59 { 60 sig_atomic_t mode; 61 int len; 62 struct ipc_handler_conn_data *data = 63 (struct ipc_handler_conn_data *) arg; 64 if (!(event & EV_READ)) { 65 return; 66 } 67 68 if ((len = read(fd, &mode, sizeof(mode))) == -1) { 69 log_msg(LOG_ERR, "handle_parent_command: read: %s", 70 strerror(errno)); 71 return; 72 } 73 if (len == 0) 74 { 75 /* parent closed the connection. Quit */ 76 ipc_child_quit(data->nsd); 77 return; 78 } 79 80 switch (mode) { 81 case NSD_STATS: 82 data->nsd->mode = mode; 83 break; 84 case NSD_QUIT: 85 ipc_child_quit(data->nsd); 86 break; 87 case NSD_QUIT_CHILD: 88 /* close our listening sockets and ack */ 89 server_close_all_sockets(data->nsd->udp, data->nsd->ifs); 90 server_close_all_sockets(data->nsd->tcp, data->nsd->ifs); 91 /* mode == NSD_QUIT_CHILD */ 92 if(write(fd, &mode, sizeof(mode)) == -1) { 93 VERBOSITY(3, (LOG_INFO, "quit child write: %s", 94 strerror(errno))); 95 } 96 ipc_child_quit(data->nsd); 97 break; 98 default: 99 log_msg(LOG_ERR, "handle_parent_command: bad mode %d", 100 (int) mode); 101 break; 102 } 103 } 104 105 void 106 parent_handle_xfrd_command(netio_type *ATTR_UNUSED(netio), 107 netio_handler_type *handler, 108 netio_event_types_type event_types) 109 { 110 sig_atomic_t mode; 111 int len; 112 struct ipc_handler_conn_data *data = 113 (struct ipc_handler_conn_data *) handler->user_data; 114 if (!(event_types & NETIO_EVENT_READ)) { 115 return; 116 } 117 118 if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) { 119 log_msg(LOG_ERR, "handle_xfrd_command: read: %s", 120 strerror(errno)); 121 return; 122 } 123 if (len == 0) 124 { 125 /* xfrd closed, we must quit */ 126 DEBUG(DEBUG_IPC,1, (LOG_INFO, "handle_xfrd_command: xfrd closed channel.")); 127 close(handler->fd); 128 handler->fd = -1; 129 data->nsd->mode = NSD_SHUTDOWN; 130 return; 131 } 132 133 switch (mode) { 134 case NSD_RELOAD: 135 DEBUG(DEBUG_IPC,1, (LOG_INFO, "parent handle xfrd command RELOAD")); 136 data->nsd->signal_hint_reload = 1; 137 break; 138 case NSD_QUIT: 139 case NSD_SHUTDOWN: 140 data->nsd->mode = mode; 141 break; 142 case NSD_STATS: 143 data->nsd->signal_hint_stats = 1; 144 break; 145 case NSD_REAP_CHILDREN: 146 data->nsd->signal_hint_child = 1; 147 break; 148 default: 149 log_msg(LOG_ERR, "handle_xfrd_command: bad mode %d", 150 (int) mode); 151 break; 152 } 153 } 154 155 static void 156 send_stat_to_child(struct main_ipc_handler_data* data, int fd) 157 { 158 sig_atomic_t cmd = NSD_STATS; 159 if(write(fd, &cmd, sizeof(cmd)) == -1) { 160 if(errno == EAGAIN || errno == EINTR) 161 return; /* try again later */ 162 log_msg(LOG_ERR, "svrmain: problems sending stats to child %d command: %s", 163 (int)data->child->pid, strerror(errno)); 164 return; 165 } 166 data->child->need_to_send_STATS = 0; 167 } 168 169 static void 170 send_quit_to_child(struct main_ipc_handler_data* data, int fd) 171 { 172 sig_atomic_t cmd = NSD_QUIT; 173 if(write(fd, &cmd, sizeof(cmd)) == -1) { 174 if(errno == EAGAIN || errno == EINTR) 175 return; /* try again later */ 176 log_msg(LOG_ERR, "svrmain: problems sending quit to child %d command: %s", 177 (int)data->child->pid, strerror(errno)); 178 return; 179 } 180 data->child->need_to_send_QUIT = 0; 181 DEBUG(DEBUG_IPC,2, (LOG_INFO, "main: sent quit to child %d", 182 (int)data->child->pid)); 183 } 184 185 /** the child is done, mark it as exited */ 186 static void 187 child_is_done(struct nsd* nsd, int fd) 188 { 189 size_t i; 190 if(fd != -1) close(fd); 191 for(i=0; i<nsd->child_count; ++i) 192 if(nsd->children[i].child_fd == fd) { 193 nsd->children[i].child_fd = -1; 194 nsd->children[i].handler->fd = -1; 195 if(nsd->children[i].need_to_exit) { 196 DEBUG(DEBUG_IPC,1, (LOG_INFO, "server %d is done", 197 (int)nsd->children[i].pid)); 198 nsd->children[i].has_exited = 1; 199 } else { 200 log_msg(LOG_WARNING, 201 "server %d died unexpectedly, restarting", 202 (int)nsd->children[i].pid); 203 /* this child is now going to be re-forked as 204 * a subprocess of this server-main, and if a 205 * reload is in progress the other children 206 * are subprocesses of reload. Until the 207 * reload is done and they are all reforked. */ 208 nsd->children[i].pid = -1; 209 nsd->restart_children = 1; 210 } 211 } 212 parent_check_all_children_exited(nsd); 213 } 214 215 #ifdef BIND8_STATS 216 /** add stats to total */ 217 void 218 stats_add(struct nsdst* total, struct nsdst* s) 219 { 220 unsigned i; 221 for(i=0; i<sizeof(total->qtype)/sizeof(stc_type); i++) 222 total->qtype[i] += s->qtype[i]; 223 for(i=0; i<sizeof(total->qclass)/sizeof(stc_type); i++) 224 total->qclass[i] += s->qclass[i]; 225 total->qudp += s->qudp; 226 total->qudp6 += s->qudp6; 227 total->ctcp += s->ctcp; 228 total->ctcp6 += s->ctcp6; 229 total->ctls += s->ctls; 230 total->ctls6 += s->ctls6; 231 for(i=0; i<sizeof(total->rcode)/sizeof(stc_type); i++) 232 total->rcode[i] += s->rcode[i]; 233 for(i=0; i<sizeof(total->opcode)/sizeof(stc_type); i++) 234 total->opcode[i] += s->opcode[i]; 235 total->dropped += s->dropped; 236 total->truncated += s->truncated; 237 total->wrongzone += s->wrongzone; 238 total->txerr += s->txerr; 239 total->rxerr += s->rxerr; 240 total->edns += s->edns; 241 total->ednserr += s->ednserr; 242 total->raxfr += s->raxfr; 243 total->nona += s->nona; 244 total->rixfr += s->rixfr; 245 246 total->db_disk = s->db_disk; 247 total->db_mem = s->db_mem; 248 } 249 250 /** subtract stats from total */ 251 void 252 stats_subtract(struct nsdst* total, struct nsdst* s) 253 { 254 unsigned i; 255 for(i=0; i<sizeof(total->qtype)/sizeof(stc_type); i++) 256 total->qtype[i] -= s->qtype[i]; 257 for(i=0; i<sizeof(total->qclass)/sizeof(stc_type); i++) 258 total->qclass[i] -= s->qclass[i]; 259 total->qudp -= s->qudp; 260 total->qudp6 -= s->qudp6; 261 total->ctcp -= s->ctcp; 262 total->ctcp6 -= s->ctcp6; 263 total->ctls -= s->ctls; 264 total->ctls6 -= s->ctls6; 265 for(i=0; i<sizeof(total->rcode)/sizeof(stc_type); i++) 266 total->rcode[i] -= s->rcode[i]; 267 for(i=0; i<sizeof(total->opcode)/sizeof(stc_type); i++) 268 total->opcode[i] -= s->opcode[i]; 269 total->dropped -= s->dropped; 270 total->truncated -= s->truncated; 271 total->wrongzone -= s->wrongzone; 272 total->txerr -= s->txerr; 273 total->rxerr -= s->rxerr; 274 total->edns -= s->edns; 275 total->ednserr -= s->ednserr; 276 total->raxfr -= s->raxfr; 277 total->nona -= s->nona; 278 total->rixfr -= s->rixfr; 279 } 280 #endif /* BIND8_STATS */ 281 282 void 283 parent_handle_child_command(netio_type *ATTR_UNUSED(netio), 284 netio_handler_type *handler, 285 netio_event_types_type event_types) 286 { 287 sig_atomic_t mode; 288 int len; 289 struct main_ipc_handler_data *data = 290 (struct main_ipc_handler_data*)handler->user_data; 291 292 /* do a nonblocking write to the child if it is ready. */ 293 if ((event_types & NETIO_EVENT_WRITE)) { 294 if(data->child->need_to_send_STATS && 295 !data->child->need_to_exit) { 296 send_stat_to_child(data, handler->fd); 297 } else if(data->child->need_to_send_QUIT) { 298 send_quit_to_child(data, handler->fd); 299 if(!data->child->need_to_send_QUIT) 300 handler->event_types = NETIO_EVENT_READ; 301 } else { 302 handler->event_types = NETIO_EVENT_READ; 303 } 304 } 305 306 if (!(event_types & NETIO_EVENT_READ)) { 307 return; 308 } 309 310 /* read command from ipc */ 311 if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) { 312 log_msg(LOG_ERR, "handle_child_command: read: %s", 313 strerror(errno)); 314 return; 315 } 316 if (len == 0) 317 { 318 child_is_done(data->nsd, handler->fd); 319 return; 320 } 321 322 switch (mode) { 323 case NSD_QUIT: 324 data->nsd->mode = mode; 325 break; 326 case NSD_STATS: 327 data->nsd->signal_hint_stats = 1; 328 break; 329 case NSD_REAP_CHILDREN: 330 data->nsd->signal_hint_child = 1; 331 break; 332 default: 333 log_msg(LOG_ERR, "handle_child_command: bad mode %d", 334 (int) mode); 335 break; 336 } 337 } 338 339 void 340 parent_check_all_children_exited(struct nsd* nsd) 341 { 342 size_t i; 343 for(i=0; i < nsd->child_count; i++) { 344 if(!nsd->children[i].need_to_exit) 345 return; 346 if(!nsd->children[i].has_exited) 347 return; 348 } 349 nsd->mode = NSD_QUIT_SYNC; 350 DEBUG(DEBUG_IPC,2, (LOG_INFO, "main: all children exited. quit sync.")); 351 } 352 353 void 354 parent_handle_reload_command(netio_type *ATTR_UNUSED(netio), 355 netio_handler_type *handler, 356 netio_event_types_type event_types) 357 { 358 sig_atomic_t mode; 359 int len; 360 size_t i; 361 struct nsd *nsd = (struct nsd*) handler->user_data; 362 if (!(event_types & NETIO_EVENT_READ)) { 363 return; 364 } 365 /* read command from ipc */ 366 if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) { 367 log_msg(LOG_ERR, "handle_reload_command: read: %s", 368 strerror(errno)); 369 return; 370 } 371 if (len == 0) 372 { 373 assert(handler->fd != -1); /* or read() would have failed */ 374 close(handler->fd); 375 handler->fd = -1; 376 377 log_msg(LOG_ERR, "handle_reload_cmd: reload closed cmd channel"); 378 nsd->reload_failed = 1; 379 return; 380 } 381 switch (mode) { 382 case NSD_QUIT_SYNC: 383 /* set all children to exit, only then notify xfrd. */ 384 /* so that buffered packets to pass to xfrd can arrive. */ 385 for(i=0; i < nsd->child_count; i++) { 386 nsd->children[i].need_to_exit = 1; 387 if(nsd->children[i].pid > 0 && 388 nsd->children[i].child_fd != -1) { 389 nsd->children[i].need_to_send_QUIT = 1; 390 nsd->children[i].handler->event_types 391 |= NETIO_EVENT_WRITE; 392 } else { 393 if(nsd->children[i].child_fd == -1) 394 nsd->children[i].has_exited = 1; 395 } 396 } 397 parent_check_all_children_exited(nsd); 398 break; 399 default: 400 log_msg(LOG_ERR, "handle_reload_command: bad mode %d", 401 (int) mode); 402 break; 403 } 404 } 405 406 static void 407 xfrd_send_reload_req(xfrd_state_type* xfrd) 408 { 409 sig_atomic_t req = NSD_RELOAD; 410 uint64_t p = xfrd->last_task->data; 411 udb_ptr_unlink(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask]); 412 task_process_sync(xfrd->nsd->task[xfrd->nsd->mytask]); 413 /* ask server_main for a reload */ 414 if(write(xfrd->ipc_handler.ev_fd, &req, sizeof(req)) == -1) { 415 udb_ptr_init(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask]); 416 udb_ptr_set(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask], p); 417 if(errno == EAGAIN || errno == EINTR) 418 return; /* try again later */ 419 log_msg(LOG_ERR, "xfrd: problems sending reload command: %s", 420 strerror(errno)); 421 return; 422 } 423 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: asked nsd to reload new updates")); 424 /* swapped task to other side, start to use other task udb. */ 425 xfrd->nsd->mytask = 1 - xfrd->nsd->mytask; 426 task_remap(xfrd->nsd->task[xfrd->nsd->mytask]); 427 udb_ptr_init(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask]); 428 assert(udb_base_get_userdata(xfrd->nsd->task[xfrd->nsd->mytask])->data == 0); 429 if(!xfrd->reload_cmd_first_sent) 430 xfrd->reload_cmd_first_sent = xfrd_time(); 431 xfrd->reload_cmd_last_sent = xfrd_time(); 432 xfrd->need_to_send_reload = 0; 433 xfrd->can_send_reload = 0; 434 } 435 436 void 437 ipc_xfrd_set_listening(struct xfrd_state* xfrd, short mode) 438 { 439 int fd = xfrd->ipc_handler.ev_fd; 440 struct event_base* base = xfrd->event_base; 441 event_del(&xfrd->ipc_handler); 442 memset(&xfrd->ipc_handler, 0, sizeof(xfrd->ipc_handler)); 443 event_set(&xfrd->ipc_handler, fd, mode, xfrd_handle_ipc, xfrd); 444 if(event_base_set(base, &xfrd->ipc_handler) != 0) 445 log_msg(LOG_ERR, "ipc: cannot set event_base"); 446 /* no timeout for IPC events */ 447 if(event_add(&xfrd->ipc_handler, NULL) != 0) 448 log_msg(LOG_ERR, "ipc: cannot add event"); 449 xfrd->ipc_handler_flags = mode; 450 } 451 452 static void 453 xfrd_send_shutdown_req(xfrd_state_type* xfrd) 454 { 455 sig_atomic_t cmd = NSD_SHUTDOWN; 456 xfrd->ipc_send_blocked = 1; 457 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 458 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc send shutdown")); 459 if(!write_socket(xfrd->ipc_handler.ev_fd, &cmd, sizeof(cmd))) { 460 log_msg(LOG_ERR, "xfrd: error writing shutdown to main: %s", 461 strerror(errno)); 462 } 463 xfrd->need_to_send_shutdown = 0; 464 } 465 466 static void 467 xfrd_send_quit_req(xfrd_state_type* xfrd) 468 { 469 sig_atomic_t cmd = NSD_QUIT; 470 xfrd->ipc_send_blocked = 1; 471 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 472 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc send ackreload(quit)")); 473 if(!write_socket(xfrd->ipc_handler.ev_fd, &cmd, sizeof(cmd))) { 474 log_msg(LOG_ERR, "xfrd: error writing ack to main: %s", 475 strerror(errno)); 476 } 477 xfrd->need_to_send_quit = 0; 478 } 479 480 static void 481 xfrd_send_stats(xfrd_state_type* xfrd) 482 { 483 sig_atomic_t cmd = NSD_STATS; 484 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc send stats")); 485 if(!write_socket(xfrd->ipc_handler.ev_fd, &cmd, sizeof(cmd))) { 486 log_msg(LOG_ERR, "xfrd: error writing stats to main: %s", 487 strerror(errno)); 488 } 489 xfrd->need_to_send_stats = 0; 490 } 491 492 void 493 xfrd_handle_ipc(int ATTR_UNUSED(fd), short event, void* arg) 494 { 495 xfrd_state_type* xfrd = (xfrd_state_type*)arg; 496 if ((event & EV_READ)) 497 { 498 /* first attempt to read as a signal from main 499 * could block further send operations */ 500 xfrd_handle_ipc_read(&xfrd->ipc_handler, xfrd); 501 } 502 if ((event & EV_WRITE)) 503 { 504 if(xfrd->ipc_send_blocked) { /* wait for RELOAD_DONE */ 505 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 506 return; 507 } 508 if(xfrd->need_to_send_shutdown) { 509 xfrd_send_shutdown_req(xfrd); 510 } else if(xfrd->need_to_send_quit) { 511 xfrd_send_quit_req(xfrd); 512 } else if(xfrd->can_send_reload && xfrd->need_to_send_reload) { 513 xfrd_send_reload_req(xfrd); 514 } else if(xfrd->need_to_send_stats) { 515 xfrd_send_stats(xfrd); 516 } 517 if(!(xfrd->can_send_reload && xfrd->need_to_send_reload) && 518 !xfrd->need_to_send_shutdown && 519 !xfrd->need_to_send_quit && 520 !xfrd->need_to_send_stats) { 521 /* disable writing for now */ 522 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 523 } 524 } 525 526 } 527 528 static void 529 xfrd_handle_ipc_read(struct event* handler, xfrd_state_type* xfrd) 530 { 531 sig_atomic_t cmd; 532 int len; 533 534 if((len = read(handler->ev_fd, &cmd, sizeof(cmd))) == -1) { 535 if(errno != EINTR && errno != EAGAIN) 536 log_msg(LOG_ERR, "xfrd_handle_ipc: read: %s", 537 strerror(errno)); 538 return; 539 } 540 if(len == 0) 541 { 542 /* parent closed the connection. Quit */ 543 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: main closed connection.")); 544 xfrd->shutdown = 1; 545 return; 546 } 547 548 switch(cmd) { 549 case NSD_QUIT: 550 case NSD_SHUTDOWN: 551 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: main sent shutdown cmd.")); 552 xfrd->shutdown = 1; 553 break; 554 case NSD_RELOAD_FAILED: 555 xfrd->reload_failed = 1; 556 /* fall through */ 557 case NSD_RELOAD_DONE: 558 /* reload has finished */ 559 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv %s", 560 xfrd->reload_failed ? "RELOAD FAILED" : "RELOAD DONE")); 561 if(block_read(NULL, handler->ev_fd, &xfrd->reload_pid, 562 sizeof(pid_t), -1) != sizeof(pid_t)) { 563 log_msg(LOG_ERR, "xfrd cannot get reload_pid"); 564 } 565 /* read the not-mytask for the results and soainfo */ 566 xfrd_process_task_result(xfrd, 567 xfrd->nsd->task[1-xfrd->nsd->mytask]); 568 /* reset the IPC, (and the nonblocking ipc write; 569 the new parent does not want half a packet) */ 570 xfrd->can_send_reload = 1; 571 xfrd->ipc_send_blocked = 0; 572 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ|EV_WRITE); 573 xfrd_reopen_logfile(); 574 if(!xfrd->reload_failed) { 575 xfrd_check_failed_updates(); 576 xfrd->reload_cmd_first_sent = 0; 577 } else { 578 /* make reload happen again, right away */ 579 xfrd_set_reload_now(xfrd); 580 } 581 xfrd_prepare_zones_for_reload(); 582 xfrd->reload_failed = 0; 583 break; 584 case NSD_RELOAD_REQ: 585 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv RELOAD_REQ")); 586 /* make reload happen, right away, and schedule file check */ 587 task_new_check_zonefiles(xfrd->nsd->task[xfrd->nsd->mytask], 588 xfrd->last_task, NULL); 589 xfrd_set_reload_now(xfrd); 590 break; 591 case NSD_RELOAD: 592 /* main tells us that reload is done, stop ipc send to main */ 593 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv RELOAD")); 594 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ|EV_WRITE); 595 xfrd->need_to_send_quit = 1; 596 break; 597 default: 598 log_msg(LOG_ERR, "xfrd_handle_ipc: bad mode %d (%d)", (int)cmd, 599 (int)ntohl(cmd)); 600 break; 601 } 602 } 603 604 void 605 xfrd_handle_notify(int ATTR_UNUSED(fd), short event, void* arg) 606 { 607 struct xfrd_tcp* notify_pipe = (struct xfrd_tcp*)arg; 608 uint32_t acl_num; 609 int32_t acl_xfr; 610 611 if(!(event & EV_READ)) 612 return; 613 614 switch(conn_read(notify_pipe)){ 615 case -1: /* TODO: What to do here? */ 616 return; 617 case 0: return; /* call back later */ 618 default: break; 619 } 620 if(buffer_limit(notify_pipe->packet) < sizeof(acl_xfr)+sizeof(acl_num)) 621 log_msg(LOG_ERR, "xfrd_handle_notify invalid message size"); 622 else { 623 size_t eop = buffer_position(notify_pipe->packet) 624 - sizeof(acl_xfr) - sizeof(acl_num); 625 626 buffer_set_position(notify_pipe->packet, eop); 627 acl_num = buffer_read_u32(notify_pipe->packet); 628 acl_xfr = (int32_t)buffer_read_u32(notify_pipe->packet); 629 buffer_set_position(notify_pipe->packet, eop); 630 buffer_flip(notify_pipe->packet); 631 xfrd_handle_passed_packet(notify_pipe->packet,acl_num,acl_xfr); 632 } 633 notify_pipe->total_bytes = 0; 634 notify_pipe->msglen = 0; 635 buffer_clear(notify_pipe->packet); 636 } 637