void listen_stop_accept(struct listen_dnsport* listen) { /* do not stop the ones that have no tcp_free list * (they have already stopped listening) */ struct listen_list* p; for(p=listen->cps; p; p=p->next) { if(p->com->type == comm_tcp_accept && p->com->tcp_free != NULL) { comm_point_stop_listening(p->com); } } }
int remote_accept_callback(struct comm_point* c, void* arg, int err, struct comm_reply* ATTR_UNUSED(rep)) { struct daemon_remote* rc = (struct daemon_remote*)arg; struct sockaddr_storage addr; socklen_t addrlen; int newfd; struct rc_state* n; if(err != NETEVENT_NOERROR) { log_err("error %d on remote_accept_callback", err); return 0; } /* perform the accept */ newfd = comm_point_perform_accept(c, &addr, &addrlen); if(newfd == -1) return 0; /* create new commpoint unless we are servicing already */ if(rc->active >= rc->max_active) { log_warn("drop incoming remote control: too many connections"); comm_point_stop_listening(c); close_exit: #ifndef USE_WINSOCK close(newfd); #else closesocket(newfd); #endif return 0; } /* setup commpoint to service the remote control command */ n = (struct rc_state*)calloc(1, sizeof(*n)); if(!n) { log_err("out of memory"); goto close_exit; } /* start in reading state */ n->c = comm_point_create_raw(rc->worker->base, newfd, 0, &remote_control_callback, n); if(!n->c) { log_err("out of memory"); free(n); goto close_exit; } log_addr(VERB_QUERY, "new control connection from", &addr, addrlen); n->c->do_not_close = 0; comm_point_stop_listening(n->c); comm_point_start_listening(n->c, -1, REMOTE_CONTROL_TCP_TIMEOUT); memcpy(&n->c->repinfo.addr, &addr, addrlen); n->c->repinfo.addrlen = addrlen; n->shake_state = rc_hs_read; n->ssl = SSL_new(rc->ctx); if(!n->ssl) { log_crypto_err("could not SSL_new"); free(n); goto close_exit; } SSL_set_accept_state(n->ssl); (void)SSL_set_mode(n->ssl, SSL_MODE_AUTO_RETRY); if(!SSL_set_fd(n->ssl, newfd)) { log_crypto_err("could not SSL_set_fd"); SSL_free(n->ssl); free(n); goto close_exit; } n->rc = rc; n->next = rc->busy_list; rc->busy_list = n; rc->active ++; /* perform the first nonblocking read already, for windows, * so it can return wouldblock. could be faster too. */ (void)remote_control_callback(n->c, n, NETEVENT_NOERROR, NULL); return 0; }
int tube_handle_write(struct comm_point* c, void* arg, int error, struct comm_reply* ATTR_UNUSED(reply_info)) { struct tube* tube = (struct tube*)arg; struct tube_res_list* item = tube->res_list; ssize_t r; if(error != NETEVENT_NOERROR) { log_err("tube_handle_write net error %d", error); return 0; } if(!item) { comm_point_stop_listening(c); return 0; } if(tube->res_write < sizeof(item->len)) { r = write(c->fd, ((uint8_t*)&item->len) + tube->res_write, sizeof(item->len) - tube->res_write); if(r == -1) { if(errno != EAGAIN && errno != EINTR) { log_err("wpipe error: %s", strerror(errno)); } return 0; /* try again later */ } if(r == 0) { /* error on pipe, must have exited somehow */ /* cannot signal this to pipe user */ return 0; } tube->res_write += r; if(tube->res_write < sizeof(item->len)) return 0; } r = write(c->fd, item->buf + tube->res_write - sizeof(item->len), item->len - (tube->res_write - sizeof(item->len))); if(r == -1) { if(errno != EAGAIN && errno != EINTR) { log_err("wpipe error: %s", strerror(errno)); } return 0; /* try again later */ } if(r == 0) { /* error on pipe, must have exited somehow */ /* cannot signal this to pipe user */ return 0; } tube->res_write += r; if(tube->res_write < sizeof(item->len) + item->len) return 0; /* done this result, remove it */ free(item->buf); item->buf = NULL; tube->res_list = tube->res_list->next; free(item); if(!tube->res_list) { tube->res_last = NULL; comm_point_stop_listening(c); } tube->res_write = 0; return 0; }