2 * curvetun - the cipherspace wormhole creator
3 * Part of the netsniff-ng project
4 * By Daniel Borkmann <daniel@netsniff-ng.org>
5 * Copyright 2011 Daniel Borkmann <daniel@netsniff-ng.org>,
6 * Subject to the GPL, version 2.
21 #include <netinet/in.h>
22 #include <netinet/tcp.h>
23 #include <netinet/udp.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <sys/epoll.h>
29 #include <arpa/inet.h>
30 #include <linux/if_tun.h>
34 #include "write_or_die.h"
52 struct worker_struct
{
56 struct parent_info parent
;
57 int (*handler
)(int fd
, const struct worker_struct
*ws
,
58 char *buff
, size_t len
);
59 struct curve25519_struct
*c
;
62 static struct worker_struct
*threadpool
= NULL
;
64 static int auth_log
= 1;
66 extern sig_atomic_t sigint
;
68 static int handler_udp_tun_to_net(int fd
, const struct worker_struct
*ws
,
69 char *buff
, size_t len
) __pure
;
70 static int handler_udp_net_to_tun(int fd
, const struct worker_struct
*ws
,
71 char *buff
, size_t len
) __pure
;
72 static int handler_udp(int fd
, const struct worker_struct
*ws
,
73 char *buff
, size_t len
) __pure
;
74 static int handler_tcp_tun_to_net(int fd
, const struct worker_struct
*ws
,
75 char *buff
, size_t len
) __pure
;
76 static int handler_tcp_net_to_tun(int fd
, const struct worker_struct
*ws
,
77 char *buff
, size_t len
) __pure
;
78 static int handler_tcp(int fd
, const struct worker_struct
*ws
,
79 char *buff
, size_t len
) __pure
;
80 ssize_t
handler_tcp_read(int fd
, char *buff
, size_t len
);
81 static void *worker(void *self
) __pure
;
83 static int handler_udp_tun_to_net(int fd
, const struct worker_struct
*ws
,
84 char *buff
, size_t len
)
86 int dfd
, state
, keep
= 1;
88 ssize_t rlen
, err
, clen
;
90 struct curve25519_proto
*p
;
91 struct sockaddr_storage naddr
;
93 size_t off
= sizeof(struct ct_proto
) + crypto_box_zerobytes
;
95 if (!buff
|| len
<= off
) {
101 memset(buff
, 0, len
);
102 while ((rlen
= read(fd
, buff
+ off
, len
- off
)) > 0) {
106 memset(&naddr
, 0, sizeof(naddr
));
108 hdr
= (struct ct_proto
*) buff
;
109 memset(hdr
, 0, sizeof(*hdr
));
112 trie_addr_lookup(buff
+ off
, rlen
, ws
->parent
.ipv4
, &dfd
, &naddr
,
114 if (unlikely(dfd
< 0 || nlen
== 0)) {
115 syslog(LOG_INFO
, "CPU%u: UDP tunnel lookup failed: "
116 "unknown destination\n", ws
->cpu
);
117 memset(buff
, 0, len
);
120 err
= get_user_by_sockaddr(&naddr
, nlen
, &p
);
121 if (unlikely(err
|| !p
)) {
122 syslog(LOG_ERR
, "CPU%u: User protocol not in cache! "
123 "Dropping connection!\n", ws
->cpu
);
124 memset(buff
, 0, len
);
127 clen
= curve25519_encode(ws
->c
, p
, (unsigned char *) (buff
+ off
-
128 crypto_box_zerobytes
), (rlen
+
129 crypto_box_zerobytes
), (unsigned char **)
131 if (unlikely(clen
<= 0)) {
132 syslog(LOG_ERR
, "CPU%u: UDP tunnel encrypt error: %zd\n",
134 memset(buff
, 0, len
);
138 hdr
->payload
= htons((uint16_t) clen
);
141 setsockopt(dfd
, IPPROTO_UDP
, UDP_CORK
, &state
, sizeof(state
));
143 err
= sendto(dfd
, hdr
, sizeof(struct ct_proto
), 0,
144 (struct sockaddr
*) &naddr
, nlen
);
145 if (unlikely(err
< 0))
146 syslog(LOG_ERR
, "CPU%u: UDP tunnel write error: %s\n",
147 ws
->cpu
, strerror(errno
));
149 err
= sendto(dfd
, cbuff
, clen
, 0, (struct sockaddr
*) &naddr
,
151 if (unlikely(err
< 0))
152 syslog(LOG_ERR
, "CPU%u: UDP tunnel write error: %s\n",
153 ws
->cpu
, strerror(errno
));
156 setsockopt(dfd
, IPPROTO_UDP
, UDP_CORK
, &state
, sizeof(state
));
159 memset(buff
, 0, len
);
162 if (unlikely(rlen
< 0 && errno
!= EAGAIN
))
163 syslog(LOG_ERR
, "CPU%u: UDP tunnel read error: %s\n",
164 ws
->cpu
, strerror(errno
));
169 static void handler_udp_notify_close(int fd
, struct sockaddr_storage
*addr
)
174 memset(&hdr
, 0, sizeof(hdr
));
175 hdr
.flags
|= PROTO_FLAG_EXIT
;
178 err
= sendto(fd
, &hdr
, sizeof(hdr
), 0, (struct sockaddr
*) addr
, sizeof(*addr
));
181 syslog(LOG_ERR
, "Error while sending close notification: "
182 "%s!\n", strerror(errno
));
185 static int handler_udp_net_to_tun(int fd
, const struct worker_struct
*ws
,
186 char *buff
, size_t len
)
190 ssize_t rlen
, err
, clen
;
191 struct ct_proto
*hdr
;
192 struct curve25519_proto
*p
;
193 struct sockaddr_storage naddr
;
194 socklen_t nlen
= sizeof(naddr
);
201 memset(&naddr
, 0, sizeof(naddr
));
204 while ((rlen
= recvfrom(fd
, buff
, len
, 0, (struct sockaddr
*) &naddr
,
207 hdr
= (struct ct_proto
*) buff
;
209 if (unlikely(rlen
< sizeof(struct ct_proto
)))
211 if (unlikely(rlen
- sizeof(*hdr
) != ntohs(hdr
->payload
)))
213 if (unlikely(ntohs(hdr
->payload
) == 0))
215 if (hdr
->flags
& PROTO_FLAG_EXIT
) {
217 remove_user_by_sockaddr(&naddr
, nlen
);
218 trie_addr_remove_addr(&naddr
, nlen
);
219 handler_udp_notify_close(fd
, &naddr
);
222 if (hdr
->flags
& PROTO_FLAG_INIT
) {
224 syslog(LOG_INFO
, "Got initial userhash from remote end!\n");
225 if (unlikely(rlen
- sizeof(*hdr
) <
226 sizeof(struct username_struct
)))
228 err
= try_register_user_by_sockaddr(ws
->c
, buff
+ sizeof(struct ct_proto
),
229 rlen
- sizeof(struct ct_proto
),
230 &naddr
, nlen
, auth_log
);
236 err
= get_user_by_sockaddr(&naddr
, nlen
, &p
);
237 if (unlikely(err
|| !p
)) {
238 syslog(LOG_ERR
, "CPU%u: User protocol not in cache! "
239 "Dropping connection!\n", ws
->cpu
);
242 clen
= curve25519_decode(ws
->c
, p
, (unsigned char *) buff
+
243 sizeof(struct ct_proto
),
244 rlen
- sizeof(struct ct_proto
),
245 (unsigned char **) &cbuff
, NULL
);
246 if (unlikely(clen
<= 0)) {
247 syslog(LOG_ERR
, "CPU%u: UDP net decryption error: %zd\n",
251 cbuff
+= crypto_box_zerobytes
;
252 clen
-= crypto_box_zerobytes
;
253 err
= trie_addr_maybe_update(cbuff
, clen
, ws
->parent
.ipv4
,
256 syslog(LOG_INFO
, "CPU%u: Malicious packet dropped "
257 "from id %d\n", ws
->cpu
, fd
);
261 err
= write(ws
->parent
.tunfd
, cbuff
, clen
);
262 if (unlikely(err
< 0))
263 syslog(LOG_ERR
, "CPU%u: UDP net write error: %s\n",
264 ws
->cpu
, strerror(errno
));
267 nlen
= sizeof(naddr
);
268 memset(&naddr
, 0, sizeof(naddr
));
272 if (unlikely(rlen
< 0 && errno
!= EAGAIN
))
273 syslog(LOG_ERR
, "CPU%u: UDP net read error: %s\n",
274 ws
->cpu
, strerror(errno
));
279 static int handler_udp(int fd
, const struct worker_struct
*ws
,
280 char *buff
, size_t len
)
283 if (fd
== ws
->parent
.tunfd
)
284 ret
= handler_udp_tun_to_net(fd
, ws
, buff
, len
);
286 ret
= handler_udp_net_to_tun(fd
, ws
, buff
, len
);
290 static int handler_tcp_tun_to_net(int fd
, const struct worker_struct
*ws
,
291 char *buff
, size_t len
)
293 int dfd
, state
, keep
= 1;
295 ssize_t rlen
, err
, clen
;
296 struct ct_proto
*hdr
;
297 struct curve25519_proto
*p
;
299 size_t off
= sizeof(struct ct_proto
) + crypto_box_zerobytes
;
301 if (!buff
|| len
<= off
) {
307 memset(buff
, 0, len
);
308 while ((rlen
= read(fd
, buff
+ off
, len
- off
)) > 0) {
312 hdr
= (struct ct_proto
*) buff
;
313 memset(hdr
, 0, sizeof(*hdr
));
316 trie_addr_lookup(buff
+ off
, rlen
, ws
->parent
.ipv4
, &dfd
, NULL
,
318 if (unlikely(dfd
< 0)) {
319 syslog(LOG_INFO
, "CPU%u: TCP tunnel lookup failed: "
320 "unknown destination\n", ws
->cpu
);
321 memset(buff
, 0, len
);
324 err
= get_user_by_socket(dfd
, &p
);
325 if (unlikely(err
|| !p
)) {
326 syslog(LOG_ERR
, "CPU%u: User protocol not in cache! "
327 "Dropping connection!\n", ws
->cpu
);
328 memset(buff
, 0, len
);
331 clen
= curve25519_encode(ws
->c
, p
, (unsigned char *) (buff
+ off
-
332 crypto_box_zerobytes
), (rlen
+
333 crypto_box_zerobytes
), (unsigned char **)
335 if (unlikely(clen
<= 0)) {
336 syslog(LOG_ERR
, "CPU%u: TCP tunnel encrypt error: %zd\n",
338 memset(buff
, 0, len
);
342 hdr
->payload
= htons((uint16_t) clen
);
345 setsockopt(dfd
, IPPROTO_TCP
, TCP_CORK
, &state
, sizeof(state
));
347 err
= write_exact(dfd
, hdr
, sizeof(struct ct_proto
), 0);
348 if (unlikely(err
< 0))
349 syslog(LOG_ERR
, "CPU%u: TCP tunnel write error: %s\n",
350 ws
->cpu
, strerror(errno
));
352 err
= write_exact(dfd
, cbuff
, clen
, 0);
353 if (unlikely(err
< 0))
354 syslog(LOG_ERR
, "CPU%u: TCP tunnel write error: %s\n",
355 ws
->cpu
, strerror(errno
));
358 setsockopt(dfd
, IPPROTO_TCP
, TCP_CORK
, &state
, sizeof(state
));
361 memset(buff
, 0, len
);
364 if (unlikely(rlen
< 0 && errno
!= EAGAIN
))
365 syslog(LOG_ERR
, "CPU%u: TCP tunnel read error: %s\n",
366 ws
->cpu
, strerror(errno
));
371 ssize_t
handler_tcp_read(int fd
, char *buff
, size_t len
)
374 struct ct_proto
*hdr
= (struct ct_proto
*) buff
;
381 /* May exit on EAGAIN if 0 Byte read */
382 rlen
= read_exact(fd
, buff
, sizeof(struct ct_proto
), 1);
385 if (unlikely(ntohs(hdr
->payload
) > len
- sizeof(struct ct_proto
))) {
387 return 1; /* Force server to close connection */
389 /* May not exit on EAGAIN if 0 Byte read */
390 rlen
= read_exact(fd
, buff
+ sizeof(struct ct_proto
),
391 ntohs(hdr
->payload
), 0);
395 return sizeof(struct ct_proto
) + rlen
;
398 static void handler_tcp_notify_close(int fd
)
403 memset(&hdr
, 0, sizeof(hdr
));
404 hdr
.flags
|= PROTO_FLAG_EXIT
;
407 err
= write(fd
, &hdr
, sizeof(hdr
));
410 syslog(LOG_ERR
, "Error while sending close notification: "
411 "%s!\n", strerror(errno
));
414 static int handler_tcp_net_to_tun(int fd
, const struct worker_struct
*ws
,
415 char *buff
, size_t len
)
417 int keep
= 1, count
= 0;
419 ssize_t rlen
, err
, clen
;
420 struct ct_proto
*hdr
;
421 struct curve25519_proto
*p
;
429 while ((rlen
= handler_tcp_read(fd
, buff
, len
)) > 0) {
431 hdr
= (struct ct_proto
*) buff
;
433 if (unlikely(rlen
< sizeof(struct ct_proto
)))
435 if (unlikely(rlen
- sizeof(*hdr
) != ntohs(hdr
->payload
)))
437 if (unlikely(ntohs(hdr
->payload
) == 0))
439 if (hdr
->flags
& PROTO_FLAG_EXIT
) {
441 remove_user_by_socket(fd
);
442 trie_addr_remove(fd
);
443 handler_tcp_notify_close(fd
);
444 rlen
= write(ws
->parent
.efd
, &fd
, sizeof(fd
));
445 if (rlen
!= sizeof(fd
))
446 syslog(LOG_ERR
, "CPU%u: TCP event write error: %s\n",
447 ws
->cpu
, strerror(errno
));
451 if (hdr
->flags
& PROTO_FLAG_INIT
) {
453 syslog(LOG_INFO
, "Got initial userhash from remote end!\n");
454 if (unlikely(rlen
- sizeof(*hdr
) <
455 sizeof(struct username_struct
)))
457 err
= try_register_user_by_socket(ws
->c
, buff
+ sizeof(struct ct_proto
),
458 rlen
- sizeof(struct ct_proto
),
465 err
= get_user_by_socket(fd
, &p
);
466 if (unlikely(err
|| !p
)) {
467 syslog(LOG_ERR
, "CPU%u: User protocol not in cache! "
468 "Dropping connection!\n", ws
->cpu
);
471 clen
= curve25519_decode(ws
->c
, p
, (unsigned char *) buff
+
472 sizeof(struct ct_proto
),
473 rlen
- sizeof(struct ct_proto
),
474 (unsigned char **) &cbuff
, NULL
);
475 if (unlikely(clen
<= 0)) {
476 syslog(LOG_ERR
, "CPU%u: TCP net decryption error: %zd\n",
480 cbuff
+= crypto_box_zerobytes
;
481 clen
-= crypto_box_zerobytes
;
482 err
= trie_addr_maybe_update(cbuff
, clen
, ws
->parent
.ipv4
,
485 syslog(LOG_INFO
, "CPU%u: Malicious packet dropped "
486 "from id %d\n", ws
->cpu
, fd
);
490 err
= write(ws
->parent
.tunfd
, cbuff
, clen
);
491 if (unlikely(err
< 0))
492 syslog(LOG_ERR
, "CPU%u: TCP net write error: %s\n",
493 ws
->cpu
, strerror(errno
));
497 err
= write_exact(ws
->efd
[1], &fd
, sizeof(fd
), 1);
498 if (unlikely(err
!= sizeof(fd
)))
499 syslog(LOG_ERR
, "CPU%u: TCP net put fd back in "
500 "pipe error: %s\n", ws
->cpu
, strerror(errno
));
507 if (unlikely(rlen
< 0 && errno
!= EAGAIN
&& errno
!= EBADF
))
508 syslog(LOG_ERR
, "CPU%u: TCP net read error: %s\n",
509 ws
->cpu
, strerror(errno
));
514 static int handler_tcp(int fd
, const struct worker_struct
*ws
,
515 char *buff
, size_t len
)
518 if (fd
== ws
->parent
.tunfd
)
519 ret
= handler_tcp_tun_to_net(fd
, ws
, buff
, len
);
521 ret
= handler_tcp_net_to_tun(fd
, ws
, buff
, len
);
525 static void *worker(void *self
)
529 size_t blen
= TUNBUFF_SIZ
; //FIXME
530 const struct worker_struct
*ws
= self
;
537 ret
= curve25519_alloc_or_maybe_die(ws
->c
);
539 syslog_panic("Cannot init curve25519!\n");
541 buff
= xmalloc_aligned(blen
, 64);
542 syslog(LOG_INFO
, "curvetun thread on CPU%u up!\n", ws
->cpu
);
543 pthread_cleanup_push(xfree_func
, ws
->c
);
544 pthread_cleanup_push(curve25519_free
, ws
->c
);
545 pthread_cleanup_push(xfree_func
, buff
);
547 while (likely(!sigint
)) {
549 if ((fds
.revents
& POLLIN
) != POLLIN
)
551 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &old_state
);
552 while ((ret
= read_exact(ws
->efd
[0], &fd
, sizeof(fd
), 1)) > 0) {
553 if (ret
!= sizeof(fd
)) {
554 syslog(LOG_ERR
, "CPU%u: Thread could not read "
555 "event descriptor!\n", ws
->cpu
);
560 ret
= ws
->handler(fd
, ws
, buff
, blen
);
562 ret
= write_exact(ws
->parent
.refd
, &fd
, sizeof(fd
), 1);
563 if (ret
!= sizeof(fd
))
564 syslog(LOG_ERR
, "CPU%u: Retriggering failed: "
565 "%s\n", ws
->cpu
, strerror(errno
));
568 pthread_setcancelstate(old_state
, NULL
);
571 syslog(LOG_INFO
, "curvetun thread on CPU%u down!\n", ws
->cpu
);
572 pthread_cleanup_pop(1);
573 pthread_cleanup_pop(1);
574 pthread_cleanup_pop(1);
575 pthread_exit((void *) ((long) ws
->cpu
));
578 static void thread_spawn_or_panic(unsigned int cpus
, int efd
, int refd
,
579 int tunfd
, int ipv4
, int udp
)
583 unsigned int threads
;
585 threads
= cpus
* THREADS_PER_CPU
;
586 for (i
= 0; i
< threads
; ++i
) {
588 threadpool
[i
].cpu
= i
% cpus
;
589 CPU_SET(threadpool
[i
].cpu
, &cpuset
);
591 ret
= pipe2(threadpool
[i
].efd
, O_NONBLOCK
);
593 syslog_panic("Cannot create event socket!\n");
595 threadpool
[i
].c
= xmalloc_aligned(sizeof(*threadpool
[i
].c
), 64);
596 threadpool
[i
].parent
.efd
= efd
;
597 threadpool
[i
].parent
.refd
= refd
;
598 threadpool
[i
].parent
.tunfd
= tunfd
;
599 threadpool
[i
].parent
.ipv4
= ipv4
;
600 threadpool
[i
].parent
.udp
= udp
;
601 threadpool
[i
].handler
= udp
? handler_udp
: handler_tcp
;
603 ret
= pthread_create(&threadpool
[i
].trid
, NULL
,
604 worker
, &threadpool
[i
]);
606 syslog_panic("Thread creation failed!\n");
608 ret
= pthread_setaffinity_np(threadpool
[i
].trid
,
609 sizeof(cpuset
), &cpuset
);
611 syslog_panic("Thread CPU migration failed!\n");
613 pthread_detach(threadpool
[i
].trid
);
619 static void thread_finish(unsigned int cpus
)
622 unsigned int threads
;
623 threads
= cpus
* THREADS_PER_CPU
;
624 for (i
= 0; i
< threads
; ++i
) {
625 while (pthread_join(threadpool
[i
].trid
, NULL
) < 0)
627 close(threadpool
[i
].efd
[0]);
628 close(threadpool
[i
].efd
[1]);
632 int server_main(char *home
, char *dev
, char *port
, int udp
, int ipv4
, int log
)
634 int lfd
= -1, kdpfd
, nfds
, nfd
, curfds
, efd
[2], refd
[2], tunfd
, i
, mtu
;
635 unsigned int cpus
= 0, threads
, udp_cpu
= 0;
637 struct epoll_event ev
, *events
;
638 struct addrinfo hints
, *ahead
, *ai
;
641 openlog("curvetun", LOG_PID
| LOG_CONS
| LOG_NDELAY
, LOG_DAEMON
);
642 syslog(LOG_INFO
, "curvetun server booting!\n");
644 syslog(LOG_INFO
, "curvetun user logging disabled!\n");
646 parse_userfile_and_generate_user_store_or_die(home
);
648 memset(&hints
, 0, sizeof(hints
));
649 hints
.ai_family
= PF_UNSPEC
;
650 hints
.ai_socktype
= udp
? SOCK_DGRAM
: SOCK_STREAM
;
651 hints
.ai_protocol
= udp
? IPPROTO_UDP
: IPPROTO_TCP
;
652 hints
.ai_flags
= AI_PASSIVE
;
654 ret
= getaddrinfo(NULL
, port
, &hints
, &ahead
);
656 syslog_panic("Cannot get address info!\n");
658 for (ai
= ahead
; ai
!= NULL
&& lfd
< 0; ai
= ai
->ai_next
) {
659 lfd
= socket(ai
->ai_family
, ai
->ai_socktype
, ai
->ai_protocol
);
662 if (ai
->ai_family
== AF_INET6
) {
665 ret
= setsockopt(lfd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
676 #endif /* IPV6_V6ONLY */
679 mtu
= IP_PMTUDISC_DONT
;
680 setsockopt(lfd
, SOL_IP
, IP_MTU_DISCOVER
, &mtu
, sizeof(mtu
));
681 ret
= bind(lfd
, ai
->ai_addr
, ai
->ai_addrlen
);
688 ret
= listen(lfd
, 5);
696 ipv4
= (ai
->ai_family
== AF_INET6
? 0 :
697 (ai
->ai_family
== AF_INET
? 1 : -1));
700 syslog(LOG_INFO
, "curvetun on IPv%d via %s on port %s!\n",
701 ai
->ai_family
== AF_INET
? 4 : 6,
702 udp
? "UDP" : "TCP", port
);
703 syslog(LOG_INFO
, "Allowed overlay proto is IPv%d!\n",
709 if (lfd
< 0 || ipv4
< 0)
710 syslog_panic("Cannot create socket!\n");
712 tunfd
= tun_open_or_die(dev
? dev
: DEVNAME_SERVER
, IFF_TUN
| IFF_NO_PI
);
714 ret
= pipe2(efd
, O_NONBLOCK
);
716 syslog_panic("Cannot create parent event fd!\n");
718 ret
= pipe2(refd
, O_NONBLOCK
);
720 syslog_panic("Cannot create parent (r)event fd!\n");
722 set_nonblocking(lfd
);
724 events
= xzmalloc(MAX_EPOLL_SIZE
* sizeof(*events
));
725 for (i
= 0; i
< MAX_EPOLL_SIZE
; ++i
)
726 events
[i
].data
.fd
= -1;
728 kdpfd
= epoll_create(MAX_EPOLL_SIZE
);
730 syslog_panic("Cannot create socket!\n");
732 memset(&ev
, 0, sizeof(ev
));
733 ev
.events
= udp
? EPOLLIN
| EPOLLET
| EPOLLONESHOT
: EPOLLIN
;
735 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_ADD
, lfd
, &ev
);
737 syslog_panic("Cannot add socket for epoll!\n");
739 memset(&ev
, 0, sizeof(ev
));
742 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_ADD
, efd
[0], &ev
);
744 syslog_panic("Cannot add socket for events!\n");
746 memset(&ev
, 0, sizeof(ev
));
748 ev
.data
.fd
= refd
[0];
749 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_ADD
, refd
[0], &ev
);
751 syslog_panic("Cannot add socket for (r)events!\n");
753 memset(&ev
, 0, sizeof(ev
));
754 ev
.events
= EPOLLIN
| EPOLLET
| EPOLLONESHOT
;
756 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_ADD
, tunfd
, &ev
);
758 syslog_panic("Cannot add socket for tundev!\n");
764 cpus
= get_number_cpus_online();
765 threads
= cpus
* THREADS_PER_CPU
;
766 if (!((threads
!= 0) && ((threads
& (threads
- 1)) == 0)))
767 syslog_panic("Thread number not power of two!\n");
768 threadpool
= xzmalloc(sizeof(*threadpool
) * threads
);
769 thread_spawn_or_panic(cpus
, efd
[1], refd
[1], tunfd
, ipv4
, udp
);
771 init_cpusched(threads
);
772 register_socket(tunfd
);
773 register_socket(lfd
);
775 syslog(LOG_INFO
, "curvetun up and running!\n");
777 while (likely(!sigint
)) {
778 nfds
= epoll_wait(kdpfd
, events
, curfds
, -1);
780 syslog(LOG_ERR
, "epoll_wait error: %s\n",
785 for (i
= 0; i
< nfds
; ++i
) {
786 if (unlikely(events
[i
].data
.fd
< 0))
788 if (events
[i
].data
.fd
== lfd
&& !udp
) {
790 char hbuff
[256], sbuff
[256];
791 struct sockaddr_storage taddr
;
794 tlen
= sizeof(taddr
);
795 nfd
= accept(lfd
, (struct sockaddr
*) &taddr
,
798 syslog(LOG_ERR
, "accept error: %s\n",
803 if (curfds
+ 1 > MAX_EPOLL_SIZE
) {
809 ncpu
= register_socket(nfd
);
811 memset(hbuff
, 0, sizeof(hbuff
));
812 memset(sbuff
, 0, sizeof(sbuff
));
814 getnameinfo((struct sockaddr
*) &taddr
, tlen
,
815 hbuff
, sizeof(hbuff
),
816 sbuff
, sizeof(sbuff
),
817 NI_NUMERICHOST
| NI_NUMERICSERV
);
820 syslog(LOG_INFO
, "New connection from %s:%s "
821 "with id %d on CPU%d, %d active!\n",
822 hbuff
, sbuff
, nfd
, ncpu
, curfds
);
825 set_nonblocking(nfd
);
828 setsockopt(nfd
, SOL_SOCKET
, SO_KEEPALIVE
,
831 setsockopt(nfd
, IPPROTO_TCP
, TCP_NODELAY
,
834 memset(&ev
, 0, sizeof(ev
));
835 ev
.events
= EPOLLIN
| EPOLLET
| EPOLLONESHOT
;
837 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_ADD
, nfd
, &ev
);
839 syslog(LOG_ERR
, "Epoll ctl add error"
840 "on id %d: %s\n", nfd
,
846 } else if (events
[i
].data
.fd
== refd
[0]) {
849 ret
= read_exact(refd
[0], &fd_one
, sizeof(fd_one
), 1);
850 if (ret
!= sizeof(fd_one
) || fd_one
<= 0)
853 memset(&ev
, 0, sizeof(ev
));
854 ev
.events
= EPOLLIN
| EPOLLET
| EPOLLONESHOT
;
856 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_MOD
, fd_one
, &ev
);
858 syslog(LOG_ERR
, "Epoll ctl mod "
859 "error on id %d: %s\n",
860 fd_one
, strerror(errno
));
864 } else if (events
[i
].data
.fd
== efd
[0]) {
867 ret
= read_exact(efd
[0], &fd_del
, sizeof(fd_del
), 1);
868 if (ret
!= sizeof(fd_del
) || fd_del
<= 0)
871 ret
= read(fd_del
, &test
, sizeof(test
));
872 if (ret
< 0 && errno
== EBADF
)
875 ret
= epoll_ctl(kdpfd
, EPOLL_CTL_DEL
, fd_del
, &ev
);
877 syslog(LOG_ERR
, "Epoll ctl del "
878 "error on id %d: %s\n",
879 fd_del
, strerror(errno
));
885 unregister_socket(fd_del
);
888 syslog(LOG_INFO
, "Closed connection with "
889 "id %d, %d active!\n",
893 int cpu
, fd_work
= events
[i
].data
.fd
;
895 cpu
= socket_to_cpu(fd_work
);
897 udp_cpu
= (udp_cpu
+ 1) & (threads
- 1);
898 ret
= write_exact(threadpool
[udp
? udp_cpu
: cpu
].efd
[1],
899 &fd_work
, sizeof(fd_work
), 1);
900 if (ret
!= sizeof(fd_work
))
901 syslog(LOG_ERR
, "Write error on event "
902 "dispatch: %s\n", strerror(errno
));
907 syslog(LOG_INFO
, "curvetun prepare shut down!\n");
920 unregister_socket(lfd
);
921 unregister_socket(tunfd
);
924 destroy_user_store();
926 syslog(LOG_INFO
, "curvetun shut down!\n");