summaryrefslogtreecommitdiff
path: root/ct_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'ct_server.c')
-rw-r--r--ct_server.c812
1 files changed, 0 insertions, 812 deletions
diff --git a/ct_server.c b/ct_server.c
deleted file mode 100644
index 9737ffd..0000000
--- a/ct_server.c
+++ /dev/null
@@ -1,812 +0,0 @@
-/*
- * curvetun - the cipherspace wormhole creator
- * Part of the netsniff-ng project
- * Copyright 2011 Daniel Borkmann <daniel@netsniff-ng.org>,
- * Subject to the GPL, version 2.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <syslog.h>
-#include <signal.h>
-#include <netdb.h>
-#include <stdint.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
-#include <sys/poll.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <sys/epoll.h>
-#include <arpa/inet.h>
-#include <linux/if_tun.h>
-
-#include "die.h"
-#include "epoll2.h"
-#include "ioops.h"
-#include "xmalloc.h"
-#include "curvetun.h"
-#include "curve.h"
-#include "ioexact.h"
-#include "corking.h"
-#include "cpus.h"
-#include "sock.h"
-#include "built_in.h"
-#include "ct_usermgmt.h"
-#include "cpusched.h"
-#include "trie.h"
-
-struct parent_info {
- int efd;
- int refd;
- int tunfd;
- int ipv4;
- int udp;
-};
-
-struct worker_struct {
- pthread_t trid;
- int efd[2];
- unsigned int cpu;
- struct parent_info parent;
- int (*handler)(int fd, const struct worker_struct *ws,
- char *buff, size_t len);
- struct curve25519_struct *c;
-};
-
-static struct worker_struct *threadpool = NULL;
-
-static int auth_log = 1;
-
-extern volatile sig_atomic_t sigint;
-
-static int handler_udp_tun_to_net(int fd, const struct worker_struct *ws,
- char *buff, size_t len) __pure;
-static int handler_udp_net_to_tun(int fd, const struct worker_struct *ws,
- char *buff, size_t len) __pure;
-static int handler_udp(int fd, const struct worker_struct *ws,
- char *buff, size_t len) __pure;
-static int handler_tcp_tun_to_net(int fd, const struct worker_struct *ws,
- char *buff, size_t len) __pure;
-static int handler_tcp_net_to_tun(int fd, const struct worker_struct *ws,
- char *buff, size_t len) __pure;
-static int handler_tcp(int fd, const struct worker_struct *ws,
- char *buff, size_t len) __pure;
-ssize_t handler_tcp_read(int fd, char *buff, size_t len);
-static void *worker(void *self) __pure;
-
-static int handler_udp_tun_to_net(int fd, const struct worker_struct *ws,
- char *buff, size_t len)
-{
- int dfd, keep = 1;
- char *cbuff;
- ssize_t rlen, err, clen;
- struct ct_proto *hdr;
- struct curve25519_proto *p;
- struct sockaddr_storage naddr;
- socklen_t nlen;
- size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;
-
- if (!buff || len <= off)
- return 0;
-
- memset(buff, 0, len);
- while ((rlen = read(fd, buff + off, len - off)) > 0) {
- dfd = -1; nlen = 0; p = NULL;
-
- memset(&naddr, 0, sizeof(naddr));
-
- hdr = (struct ct_proto *) buff;
- memset(hdr, 0, sizeof(*hdr));
- hdr->flags = 0;
-
- trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, &naddr,
- (size_t *) &nlen);
- if (unlikely(dfd < 0 || nlen == 0)) {
- memset(buff, 0, len);
- continue;
- }
-
- err = get_user_by_sockaddr(&naddr, nlen, &p);
- if (unlikely(err || !p)) {
- memset(buff, 0, len);
- continue;
- }
-
- clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off -
- crypto_box_zerobytes), (rlen +
- crypto_box_zerobytes), (unsigned char **)
- &cbuff);
- if (unlikely(clen <= 0)) {
- memset(buff, 0, len);
- continue;
- }
-
- hdr->payload = htons((uint16_t) clen);
-
- set_udp_cork(dfd);
-
- sendto(dfd, hdr, sizeof(struct ct_proto), 0, (struct sockaddr *)
- &naddr, nlen);
- sendto(dfd, cbuff, clen, 0, (struct sockaddr *) &naddr, nlen);
-
- set_udp_uncork(dfd);
-
- memset(buff, 0, len);
- }
-
- return keep;
-}
-
-static void handler_udp_notify_close(int fd, struct sockaddr_storage *addr)
-{
- struct ct_proto hdr;
-
- memset(&hdr, 0, sizeof(hdr));
- hdr.flags |= PROTO_FLAG_EXIT;
- hdr.payload = 0;
-
- sendto(fd, &hdr, sizeof(hdr), 0, (struct sockaddr *) addr,
- sizeof(*addr));
-}
-
-static int handler_udp_net_to_tun(int fd, const struct worker_struct *ws,
- char *buff, size_t len)
-{
- int keep = 1;
- char *cbuff;
- ssize_t rlen, err, clen;
- struct ct_proto *hdr;
- struct curve25519_proto *p;
- struct sockaddr_storage naddr;
- socklen_t nlen = sizeof(naddr);
-
- if (!buff || !len)
- return 0;
-
- memset(&naddr, 0, sizeof(naddr));
- while ((rlen = recvfrom(fd, buff, len, 0, (struct sockaddr *) &naddr,
- &nlen)) > 0) {
- p = NULL;
-
- hdr = (struct ct_proto *) buff;
-
- if (unlikely(rlen < sizeof(struct ct_proto)))
- goto close;
- if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
- goto close;
- if (unlikely(ntohs(hdr->payload) == 0))
- goto close;
- if (hdr->flags & PROTO_FLAG_EXIT) {
-close:
- remove_user_by_sockaddr(&naddr, nlen);
- trie_addr_remove_addr(&naddr, nlen);
- handler_udp_notify_close(fd, &naddr);
-
- return keep;
- }
- if (hdr->flags & PROTO_FLAG_INIT) {
- syslog_maybe(auth_log, LOG_INFO, "Got initial userhash "
- "from remote end!\n");
-
- if (unlikely(rlen - sizeof(*hdr) <
- sizeof(struct username_struct)))
- goto close;
-
- err = try_register_user_by_sockaddr(ws->c,
- buff + sizeof(struct ct_proto),
- rlen - sizeof(struct ct_proto),
- &naddr, nlen, auth_log);
- if (unlikely(err))
- goto close;
-
- goto next;
- }
-
- err = get_user_by_sockaddr(&naddr, nlen, &p);
- if (unlikely(err || !p))
- goto close;
-
- clen = curve25519_decode(ws->c, p, (unsigned char *) buff +
- sizeof(struct ct_proto),
- rlen - sizeof(struct ct_proto),
- (unsigned char **) &cbuff, NULL);
- if (unlikely(clen <= 0))
- goto close;
-
- cbuff += crypto_box_zerobytes;
- clen -= crypto_box_zerobytes;
-
- err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
- fd, &naddr, nlen);
- if (unlikely(err))
- goto next;
-
- err = write(ws->parent.tunfd, cbuff, clen);
-next:
- nlen = sizeof(naddr);
- memset(&naddr, 0, sizeof(naddr));
- }
-
- return keep;
-}
-
-static int handler_udp(int fd, const struct worker_struct *ws,
- char *buff, size_t len)
-{
- int ret = 0;
-
- if (fd == ws->parent.tunfd)
- ret = handler_udp_tun_to_net(fd, ws, buff, len);
- else
- ret = handler_udp_net_to_tun(fd, ws, buff, len);
-
- return ret;
-}
-
-static int handler_tcp_tun_to_net(int fd, const struct worker_struct *ws,
- char *buff, size_t len)
-{
- int dfd, keep = 1;
- char *cbuff;
- ssize_t rlen, err, clen;
- struct ct_proto *hdr;
- struct curve25519_proto *p;
- socklen_t nlen;
- size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;
-
- if (!buff || len <= off)
- return 0;
-
- memset(buff, 0, len);
- while ((rlen = read(fd, buff + off, len - off)) > 0) {
- dfd = -1; p = NULL;
-
- hdr = (struct ct_proto *) buff;
- memset(hdr, 0, sizeof(*hdr));
- hdr->flags = 0;
-
- trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, NULL,
- (size_t *) &nlen);
- if (unlikely(dfd < 0)) {
- memset(buff, 0, len);
- continue;
- }
-
- err = get_user_by_socket(dfd, &p);
- if (unlikely(err || !p)) {
- memset(buff, 0, len);
- continue;
- }
-
- clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off -
- crypto_box_zerobytes), (rlen +
- crypto_box_zerobytes), (unsigned char **)
- &cbuff);
- if (unlikely(clen <= 0)) {
- memset(buff, 0, len);
- continue;
- }
-
- hdr->payload = htons((uint16_t) clen);
-
- set_tcp_cork(dfd);
-
- write_exact(dfd, hdr, sizeof(struct ct_proto), 0);
- write_exact(dfd, cbuff, clen, 0);
-
- set_tcp_uncork(dfd);
-
- memset(buff, 0, len);
- }
-
- return keep;
-}
-
-ssize_t handler_tcp_read(int fd, char *buff, size_t len)
-{
- ssize_t rlen;
- struct ct_proto *hdr = (struct ct_proto *) buff;
-
- if (!buff || !len)
- return 0;
-
- /* May exit on EAGAIN if 0 Byte read */
- rlen = read_exact(fd, buff, sizeof(struct ct_proto), 1);
- if (rlen < 0)
- return rlen;
- if (unlikely(ntohs(hdr->payload) > len - sizeof(struct ct_proto))) {
- errno = ENOMEM;
- return 1; /* Force server to close connection */
- }
-
- /* May not exit on EAGAIN if 0 Byte read */
- rlen = read_exact(fd, buff + sizeof(struct ct_proto),
- ntohs(hdr->payload), 0);
- if (rlen < 0)
- return rlen;
-
- return sizeof(struct ct_proto) + rlen;
-}
-
-static void handler_tcp_notify_close(int fd)
-{
- struct ct_proto hdr;
-
- memset(&hdr, 0, sizeof(hdr));
- hdr.flags |= PROTO_FLAG_EXIT;
- hdr.payload = 0;
-
- if (write(fd, &hdr, sizeof(hdr))) { ; }
-}
-
-static int handler_tcp_net_to_tun(int fd, const struct worker_struct *ws,
- char *buff, size_t len)
-{
- int keep = 1, count = 0;
- char *cbuff;
- ssize_t rlen, err, clen;
- struct ct_proto *hdr;
- struct curve25519_proto *p;
-
- if (!buff || !len)
- return 0;
-
- while ((rlen = handler_tcp_read(fd, buff, len)) > 0) {
- p = NULL;
-
- hdr = (struct ct_proto *) buff;
-
- if (unlikely(rlen < sizeof(struct ct_proto)))
- goto close;
- if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
- goto close;
- if (unlikely(ntohs(hdr->payload) == 0))
- goto close;
- if (hdr->flags & PROTO_FLAG_EXIT) {
-close:
- remove_user_by_socket(fd);
- trie_addr_remove(fd);
- handler_tcp_notify_close(fd);
- rlen = write(ws->parent.efd, &fd, sizeof(fd));
-
- keep = 0;
- return keep;
- }
- if (hdr->flags & PROTO_FLAG_INIT) {
- syslog_maybe(auth_log, LOG_INFO, "Got initial userhash "
- "from remote end!\n");
-
- if (unlikely(rlen - sizeof(*hdr) <
- sizeof(struct username_struct)))
- goto close;
-
- err = try_register_user_by_socket(ws->c,
- buff + sizeof(struct ct_proto),
- rlen - sizeof(struct ct_proto),
- fd, auth_log);
- if (unlikely(err))
- goto close;
-
- continue;
- }
-
- err = get_user_by_socket(fd, &p);
- if (unlikely(err || !p))
- continue;
-
- clen = curve25519_decode(ws->c, p, (unsigned char *) buff +
- sizeof(struct ct_proto),
- rlen - sizeof(struct ct_proto),
- (unsigned char **) &cbuff, NULL);
- if (unlikely(clen <= 0))
- continue;
-
- cbuff += crypto_box_zerobytes;
- clen -= crypto_box_zerobytes;
-
- err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
- fd, NULL, 0);
- if (unlikely(err))
- continue;
-
- err = write(ws->parent.tunfd, cbuff, clen);
-
- count++;
- if (count == 10) {
- write_exact(ws->efd[1], &fd, sizeof(fd), 1);
- /* Read later next data and let others process */
- return keep;
- }
- }
-
- return keep;
-}
-
-static int handler_tcp(int fd, const struct worker_struct *ws,
- char *buff, size_t len)
-{
- int ret = 0;
-
- if (fd == ws->parent.tunfd)
- ret = handler_tcp_tun_to_net(fd, ws, buff, len);
- else
- ret = handler_tcp_net_to_tun(fd, ws, buff, len);
-
- return ret;
-}
-
-static void *worker(void *self)
-{
- int fd, old_state;
- ssize_t ret;
- size_t blen = TUNBUFF_SIZ; //FIXME
- struct worker_struct *ws = self;
- struct pollfd fds;
- char *buff;
-
- fds.fd = ws->efd[0];
- fds.events = POLLIN;
-
- ws->c = curve25519_tfm_alloc();
- buff = xmalloc_aligned(blen, 64);
-
- syslog(LOG_INFO, "curvetun thread on CPU%u up!\n", ws->cpu);
-
- pthread_cleanup_push(curve25519_tfm_free_void, ws->c);
- pthread_cleanup_push(xfree_func, buff);
-
- while (likely(!sigint)) {
- poll(&fds, 1, -1);
- if ((fds.revents & POLLIN) != POLLIN)
- continue;
-
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
-
- while ((ret = read_exact(ws->efd[0], &fd, sizeof(fd), 1)) > 0) {
- if (ret != sizeof(fd)) {
- sched_yield();
- continue;
- }
-
- ret = ws->handler(fd, ws, buff, blen);
- if (ret)
- write_exact(ws->parent.refd, &fd, sizeof(fd), 1);
- }
-
- pthread_setcancelstate(old_state, NULL);
- }
-
- syslog(LOG_INFO, "curvetun thread on CPU%u down!\n", ws->cpu);
-
- pthread_cleanup_pop(1);
- pthread_cleanup_pop(1);
-
- pthread_exit((void *) ((long) ws->cpu));
-}
-
-static void thread_spawn_or_panic(unsigned int cpus, int efd, int refd,
- int tunfd, int ipv4, int udp)
-{
- int i, ret;
- cpu_set_t cpuset;
- unsigned int threads;
-
- threads = cpus * THREADS_PER_CPU;
-
- for (i = 0; i < threads; ++i) {
- CPU_ZERO(&cpuset);
- threadpool[i].cpu = i % cpus;
- CPU_SET(threadpool[i].cpu, &cpuset);
-
- ret = pipe2(threadpool[i].efd, O_NONBLOCK);
- if (ret < 0)
- syslog_panic("Cannot create event socket!\n");
-
- threadpool[i].c = xmalloc_aligned(sizeof(*threadpool[i].c), 64);
- threadpool[i].parent.efd = efd;
- threadpool[i].parent.refd = refd;
- threadpool[i].parent.tunfd = tunfd;
- threadpool[i].parent.ipv4 = ipv4;
- threadpool[i].parent.udp = udp;
- threadpool[i].handler = udp ? handler_udp : handler_tcp;
-
- ret = pthread_create(&threadpool[i].trid, NULL,
- worker, &threadpool[i]);
- if (ret < 0)
- syslog_panic("Thread creation failed!\n");
-
- ret = pthread_setaffinity_np(threadpool[i].trid,
- sizeof(cpuset), &cpuset);
- if (ret < 0)
- syslog_panic("Thread CPU migration failed!\n");
-
- pthread_detach(threadpool[i].trid);
- }
-
- sleep(1);
-}
-
-static void thread_finish(unsigned int cpus)
-{
- int i;
- unsigned int threads;
-
- threads = cpus * THREADS_PER_CPU;
-
- for (i = 0; i < threads; ++i) {
- while (pthread_join(threadpool[i].trid, NULL) < 0)
- ;
-
- close(threadpool[i].efd[0]);
- close(threadpool[i].efd[1]);
- }
-}
-
-int server_main(char *home, char *dev, char *port, int udp, int ipv4, int log)
-{
- int lfd = -1, kdpfd, nfds, nfd, curfds, efd[2], refd[2], tunfd, i;
- unsigned int cpus = 0, threads, udp_cpu = 0;
- ssize_t ret;
- struct epoll_event *events;
- struct addrinfo hints, *ahead, *ai;
-
- auth_log = !!log;
- openlog("curvetun", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_DAEMON);
-
- syslog(LOG_INFO, "curvetun server booting!\n");
- syslog_maybe(!auth_log, LOG_INFO, "curvetun user logging disabled!\n");
-
- parse_userfile_and_generate_user_store_or_die(home);
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
- hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
- hints.ai_flags = AI_PASSIVE;
-
- ret = getaddrinfo(NULL, port, &hints, &ahead);
- if (ret < 0)
- syslog_panic("Cannot get address info!\n");
-
- for (ai = ahead; ai != NULL && lfd < 0; ai = ai->ai_next) {
- lfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (lfd < 0)
- continue;
- if (ai->ai_family == AF_INET6) {
-#ifdef IPV6_V6ONLY
- ret = set_ipv6_only(lfd);
- if (ret < 0) {
- close(lfd);
- lfd = -1;
- continue;
- }
-#else
- close(lfd);
- lfd = -1;
- continue;
-#endif /* IPV6_V6ONLY */
- }
-
- set_reuseaddr(lfd);
- set_mtu_disc_dont(lfd);
-
- ret = bind(lfd, ai->ai_addr, ai->ai_addrlen);
- if (ret < 0) {
- close(lfd);
- lfd = -1;
- continue;
- }
-
- if (!udp) {
- ret = listen(lfd, 5);
- if (ret < 0) {
- close(lfd);
- lfd = -1;
- continue;
- }
- }
-
- if (ipv4 == -1) {
- ipv4 = (ai->ai_family == AF_INET6 ? 0 :
- (ai->ai_family == AF_INET ? 1 : -1));
- }
-
- syslog_maybe(auth_log, LOG_INFO, "curvetun on IPv%d via %s "
- "on port %s!\n", ai->ai_family == AF_INET ? 4 : 6,
- udp ? "UDP" : "TCP", port);
- syslog_maybe(auth_log, LOG_INFO, "Allowed overlay proto is "
- "IPv%d!\n", ipv4 ? 4 : 6);
- }
-
- freeaddrinfo(ahead);
-
- if (lfd < 0 || ipv4 < 0)
- syslog_panic("Cannot create socket!\n");
-
- tunfd = tun_open_or_die(dev ? dev : DEVNAME_SERVER, IFF_TUN | IFF_NO_PI);
-
- pipe_or_die(efd, O_NONBLOCK);
- pipe_or_die(refd, O_NONBLOCK);
-
- set_nonblocking(lfd);
-
- events = xzmalloc(MAX_EPOLL_SIZE * sizeof(*events));
- for (i = 0; i < MAX_EPOLL_SIZE; ++i)
- events[i].data.fd = -1;
-
- kdpfd = epoll_create(MAX_EPOLL_SIZE);
- if (kdpfd < 0)
- syslog_panic("Cannot create socket!\n");
-
- set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, lfd,
- udp ? EPOLLIN | EPOLLET | EPOLLONESHOT : EPOLLIN);
- set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, efd[0], EPOLLIN);
- set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, refd[0], EPOLLIN);
- set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, tunfd,
- EPOLLIN | EPOLLET | EPOLLONESHOT);
- curfds = 4;
-
- trie_init();
-
- cpus = get_number_cpus_online();
- threads = cpus * THREADS_PER_CPU;
- if (!ispow2(threads))
- syslog_panic("Thread number not power of two!\n");
-
- threadpool = xzmalloc(sizeof(*threadpool) * threads);
- thread_spawn_or_panic(cpus, efd[1], refd[1], tunfd, ipv4, udp);
-
- init_cpusched(threads);
-
- register_socket(tunfd);
- register_socket(lfd);
-
- syslog(LOG_INFO, "curvetun up and running!\n");
-
- while (likely(!sigint)) {
- nfds = epoll_wait(kdpfd, events, curfds, -1);
- if (nfds < 0) {
- syslog(LOG_ERR, "epoll_wait error: %s\n",
- strerror(errno));
- break;
- }
-
- for (i = 0; i < nfds; ++i) {
- if (unlikely(events[i].data.fd < 0))
- continue;
-
- if (events[i].data.fd == lfd && !udp) {
- int ncpu;
- char hbuff[256], sbuff[256];
- struct sockaddr_storage taddr;
- socklen_t tlen;
-
- tlen = sizeof(taddr);
- nfd = accept(lfd, (struct sockaddr *) &taddr,
- &tlen);
- if (nfd < 0) {
- syslog(LOG_ERR, "accept error: %s\n",
- strerror(errno));
- continue;
- }
-
- if (curfds + 1 > MAX_EPOLL_SIZE) {
- close(nfd);
- continue;
- }
-
- curfds++;
-
- ncpu = register_socket(nfd);
-
- memset(hbuff, 0, sizeof(hbuff));
- memset(sbuff, 0, sizeof(sbuff));
- getnameinfo((struct sockaddr *) &taddr, tlen,
- hbuff, sizeof(hbuff),
- sbuff, sizeof(sbuff),
- NI_NUMERICHOST | NI_NUMERICSERV);
-
- syslog_maybe(auth_log, LOG_INFO, "New connection "
- "from %s:%s (%d active client connections) - id %d on CPU%d",
- hbuff, sbuff, curfds-4, nfd, ncpu);
-
- set_nonblocking(nfd);
- set_socket_keepalive(nfd);
- set_tcp_nodelay(nfd);
- ret = set_epoll_descriptor2(kdpfd, EPOLL_CTL_ADD,
- nfd, EPOLLIN | EPOLLET | EPOLLONESHOT);
- if (ret < 0) {
- close(nfd);
- curfds--;
- continue;
- }
- } else if (events[i].data.fd == refd[0]) {
- int fd_one;
-
- ret = read_exact(refd[0], &fd_one,
- sizeof(fd_one), 1);
- if (ret != sizeof(fd_one) || fd_one <= 0)
- continue;
-
- ret = set_epoll_descriptor2(kdpfd, EPOLL_CTL_MOD,
- fd_one, EPOLLIN | EPOLLET | EPOLLONESHOT);
- if (ret < 0) {
- close(fd_one);
- continue;
- }
- } else if (events[i].data.fd == efd[0]) {
- int fd_del, test;
-
- ret = read_exact(efd[0], &fd_del,
- sizeof(fd_del), 1);
- if (ret != sizeof(fd_del) || fd_del <= 0)
- continue;
-
- ret = read(fd_del, &test, sizeof(test));
- if (ret < 0 && errno == EBADF)
- continue;
-
- ret = set_epoll_descriptor2(kdpfd, EPOLL_CTL_DEL,
- fd_del, 0);
- if (ret < 0) {
- close(fd_del);
- continue;
- }
-
- close(fd_del);
- curfds--;
- unregister_socket(fd_del);
-
- syslog_maybe(auth_log, LOG_INFO, "Closed connection "
- "with id %d (%d active client connections remain)\n", fd_del,
- curfds-4);
- } else {
- int cpu, fd_work = events[i].data.fd;
-
- if (!udp)
- cpu = socket_to_cpu(fd_work);
- else
- udp_cpu = (udp_cpu + 1) & (threads - 1);
-
- write_exact(threadpool[udp ? udp_cpu : cpu].efd[1],
- &fd_work, sizeof(fd_work), 1);
- }
- }
- }
-
- syslog(LOG_INFO, "curvetun prepare shut down!\n");
-
- close(lfd);
- close(efd[0]);
- close(efd[1]);
- close(refd[0]);
- close(refd[1]);
- close(tunfd);
-
- thread_finish(cpus);
-
- xfree(threadpool);
- xfree(events);
-
- unregister_socket(lfd);
- unregister_socket(tunfd);
-
- destroy_cpusched();
-
- trie_cleanup();
-
- destroy_user_store();
-
- syslog(LOG_INFO, "curvetun shut down!\n");
- closelog();
-
- return 0;
-}