src: made sigatomic_t as volatile
[netsniff-ng.git] / src / ct_server.c
blob7ca1c3aaa514544b35dc67324465438f89ba1026
1 /*
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.
7 */
9 #define _GNU_SOURCE
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <fcntl.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <pthread.h>
17 #include <syslog.h>
18 #include <signal.h>
19 #include <netdb.h>
20 #include <stdint.h>
21 #include <netinet/in.h>
22 #include <netinet/tcp.h>
23 #include <netinet/udp.h>
24 #include <sys/poll.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/wait.h>
28 #include <sys/epoll.h>
29 #include <arpa/inet.h>
30 #include <linux/if_tun.h>
32 #include "die.h"
33 #include "xsys.h"
34 #include "xio.h"
35 #include "xmalloc.h"
36 #include "curvetun.h"
37 #include "curve.h"
38 #include "compiler.h"
39 #include "usermgmt.h"
40 #include "cpusched.h"
41 #include "trie.h"
43 struct parent_info {
44 int efd;
45 int refd;
46 int tunfd;
47 int ipv4;
48 int udp;
51 struct worker_struct {
52 pthread_t trid;
53 int efd[2];
54 unsigned int cpu;
55 struct parent_info parent;
56 int (*handler)(int fd, const struct worker_struct *ws,
57 char *buff, size_t len);
58 struct curve25519_struct *c;
61 static struct worker_struct *threadpool = NULL;
63 static int auth_log = 1;
65 extern volatile sig_atomic_t sigint;
67 static int handler_udp_tun_to_net(int fd, const struct worker_struct *ws,
68 char *buff, size_t len) __pure;
69 static int handler_udp_net_to_tun(int fd, const struct worker_struct *ws,
70 char *buff, size_t len) __pure;
71 static int handler_udp(int fd, const struct worker_struct *ws,
72 char *buff, size_t len) __pure;
73 static int handler_tcp_tun_to_net(int fd, const struct worker_struct *ws,
74 char *buff, size_t len) __pure;
75 static int handler_tcp_net_to_tun(int fd, const struct worker_struct *ws,
76 char *buff, size_t len) __pure;
77 static int handler_tcp(int fd, const struct worker_struct *ws,
78 char *buff, size_t len) __pure;
79 ssize_t handler_tcp_read(int fd, char *buff, size_t len);
80 static void *worker(void *self) __pure;
82 static int handler_udp_tun_to_net(int fd, const struct worker_struct *ws,
83 char *buff, size_t len)
85 int dfd, state, keep = 1;
86 char *cbuff;
87 ssize_t rlen, err, clen;
88 struct ct_proto *hdr;
89 struct curve25519_proto *p;
90 struct sockaddr_storage naddr;
91 socklen_t nlen;
92 size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;
94 if (!buff || len <= off) {
95 errno = EINVAL;
96 return 0;
99 errno = 0;
100 memset(buff, 0, len);
101 while ((rlen = read(fd, buff + off, len - off)) > 0) {
102 dfd = -1;
103 nlen = 0;
104 p = NULL;
105 memset(&naddr, 0, sizeof(naddr));
107 hdr = (struct ct_proto *) buff;
108 memset(hdr, 0, sizeof(*hdr));
109 hdr->flags = 0;
111 trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, &naddr,
112 (size_t *) &nlen);
113 if (unlikely(dfd < 0 || nlen == 0)) {
114 syslog(LOG_INFO, "CPU%u: UDP tunnel lookup failed: "
115 "unknown destination\n", ws->cpu);
116 memset(buff, 0, len);
117 continue;
119 err = get_user_by_sockaddr(&naddr, nlen, &p);
120 if (unlikely(err || !p)) {
121 syslog(LOG_ERR, "CPU%u: User protocol not in cache! "
122 "Dropping connection!\n", ws->cpu);
123 memset(buff, 0, len);
124 continue;
126 clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off -
127 crypto_box_zerobytes), (rlen +
128 crypto_box_zerobytes), (unsigned char **)
129 &cbuff);
130 if (unlikely(clen <= 0)) {
131 syslog(LOG_ERR, "CPU%u: UDP tunnel encrypt error: %zd\n",
132 ws->cpu, clen);
133 memset(buff, 0, len);
134 continue;
137 hdr->payload = htons((uint16_t) clen);
139 state = 1;
140 setsockopt(dfd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
142 err = sendto(dfd, hdr, sizeof(struct ct_proto), 0,
143 (struct sockaddr *) &naddr, nlen);
144 if (unlikely(err < 0))
145 syslog(LOG_ERR, "CPU%u: UDP tunnel write error: %s\n",
146 ws->cpu, strerror(errno));
148 err = sendto(dfd, cbuff, clen, 0, (struct sockaddr *) &naddr,
149 nlen);
150 if (unlikely(err < 0))
151 syslog(LOG_ERR, "CPU%u: UDP tunnel write error: %s\n",
152 ws->cpu, strerror(errno));
154 state = 0;
155 setsockopt(dfd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
157 errno = 0;
158 memset(buff, 0, len);
161 if (unlikely(rlen < 0 && errno != EAGAIN))
162 syslog(LOG_ERR, "CPU%u: UDP tunnel read error: %s\n",
163 ws->cpu, strerror(errno));
165 return keep;
168 static void handler_udp_notify_close(int fd, struct sockaddr_storage *addr)
170 ssize_t err;
171 struct ct_proto hdr;
173 memset(&hdr, 0, sizeof(hdr));
174 hdr.flags |= PROTO_FLAG_EXIT;
175 hdr.payload = 0;
177 err = sendto(fd, &hdr, sizeof(hdr), 0, (struct sockaddr *) addr, sizeof(*addr));
179 if (err < 0)
180 syslog(LOG_ERR, "Error while sending close notification: "
181 "%s!\n", strerror(errno));
184 static int handler_udp_net_to_tun(int fd, const struct worker_struct *ws,
185 char *buff, size_t len)
187 int keep = 1;
188 char *cbuff;
189 ssize_t rlen, err, clen;
190 struct ct_proto *hdr;
191 struct curve25519_proto *p;
192 struct sockaddr_storage naddr;
193 socklen_t nlen = sizeof(naddr);
195 if (!buff || !len) {
196 errno = EINVAL;
197 return 0;
200 memset(&naddr, 0, sizeof(naddr));
202 errno = 0;
203 while ((rlen = recvfrom(fd, buff, len, 0, (struct sockaddr *) &naddr,
204 &nlen)) > 0) {
205 p = NULL;
206 hdr = (struct ct_proto *) buff;
208 if (unlikely(rlen < sizeof(struct ct_proto)))
209 goto close;
210 if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
211 goto close;
212 if (unlikely(ntohs(hdr->payload) == 0))
213 goto close;
214 if (hdr->flags & PROTO_FLAG_EXIT) {
215 close:
216 remove_user_by_sockaddr(&naddr, nlen);
217 trie_addr_remove_addr(&naddr, nlen);
218 handler_udp_notify_close(fd, &naddr);
219 return keep;
221 if (hdr->flags & PROTO_FLAG_INIT) {
222 if (auth_log)
223 syslog(LOG_INFO, "Got initial userhash from remote end!\n");
224 if (unlikely(rlen - sizeof(*hdr) <
225 sizeof(struct username_struct)))
226 goto close;
227 err = try_register_user_by_sockaddr(ws->c, buff + sizeof(struct ct_proto),
228 rlen - sizeof(struct ct_proto),
229 &naddr, nlen, auth_log);
230 if (unlikely(err))
231 goto close;
232 goto next;
235 err = get_user_by_sockaddr(&naddr, nlen, &p);
236 if (unlikely(err || !p)) {
237 syslog(LOG_ERR, "CPU%u: User protocol not in cache! "
238 "Dropping connection!\n", ws->cpu);
239 goto close;
241 clen = curve25519_decode(ws->c, p, (unsigned char *) buff +
242 sizeof(struct ct_proto),
243 rlen - sizeof(struct ct_proto),
244 (unsigned char **) &cbuff, NULL);
245 if (unlikely(clen <= 0)) {
246 syslog(LOG_ERR, "CPU%u: UDP net decryption error: %zd\n",
247 ws->cpu, clen);
248 goto close;
250 cbuff += crypto_box_zerobytes;
251 clen -= crypto_box_zerobytes;
252 err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
253 fd, &naddr, nlen);
254 if (unlikely(err)) {
255 syslog(LOG_INFO, "CPU%u: Malicious packet dropped "
256 "from id %d\n", ws->cpu, fd);
257 goto next;
260 err = write(ws->parent.tunfd, cbuff, clen);
261 if (unlikely(err < 0))
262 syslog(LOG_ERR, "CPU%u: UDP net write error: %s\n",
263 ws->cpu, strerror(errno));
265 next:
266 nlen = sizeof(naddr);
267 memset(&naddr, 0, sizeof(naddr));
268 errno = 0;
271 if (unlikely(rlen < 0 && errno != EAGAIN))
272 syslog(LOG_ERR, "CPU%u: UDP net read error: %s\n",
273 ws->cpu, strerror(errno));
275 return keep;
278 static int handler_udp(int fd, const struct worker_struct *ws,
279 char *buff, size_t len)
281 int ret = 0;
282 if (fd == ws->parent.tunfd)
283 ret = handler_udp_tun_to_net(fd, ws, buff, len);
284 else
285 ret = handler_udp_net_to_tun(fd, ws, buff, len);
286 return ret;
289 static int handler_tcp_tun_to_net(int fd, const struct worker_struct *ws,
290 char *buff, size_t len)
292 int dfd, state, keep = 1;
293 char *cbuff;
294 ssize_t rlen, err, clen;
295 struct ct_proto *hdr;
296 struct curve25519_proto *p;
297 socklen_t nlen;
298 size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;
300 if (!buff || len <= off) {
301 errno = EINVAL;
302 return 0;
305 errno = 0;
306 memset(buff, 0, len);
307 while ((rlen = read(fd, buff + off, len - off)) > 0) {
308 dfd = -1;
309 p = NULL;
311 hdr = (struct ct_proto *) buff;
312 memset(hdr, 0, sizeof(*hdr));
313 hdr->flags = 0;
315 trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, NULL,
316 (size_t *) &nlen);
317 if (unlikely(dfd < 0)) {
318 syslog(LOG_INFO, "CPU%u: TCP tunnel lookup failed: "
319 "unknown destination\n", ws->cpu);
320 memset(buff, 0, len);
321 continue;
323 err = get_user_by_socket(dfd, &p);
324 if (unlikely(err || !p)) {
325 syslog(LOG_ERR, "CPU%u: User protocol not in cache! "
326 "Dropping connection!\n", ws->cpu);
327 memset(buff, 0, len);
328 continue;
330 clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off -
331 crypto_box_zerobytes), (rlen +
332 crypto_box_zerobytes), (unsigned char **)
333 &cbuff);
334 if (unlikely(clen <= 0)) {
335 syslog(LOG_ERR, "CPU%u: TCP tunnel encrypt error: %zd\n",
336 ws->cpu, clen);
337 memset(buff, 0, len);
338 continue;
341 hdr->payload = htons((uint16_t) clen);
343 state = 1;
344 setsockopt(dfd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
346 err = write_exact(dfd, hdr, sizeof(struct ct_proto), 0);
347 if (unlikely(err < 0))
348 syslog(LOG_ERR, "CPU%u: TCP tunnel write error: %s\n",
349 ws->cpu, strerror(errno));
351 err = write_exact(dfd, cbuff, clen, 0);
352 if (unlikely(err < 0))
353 syslog(LOG_ERR, "CPU%u: TCP tunnel write error: %s\n",
354 ws->cpu, strerror(errno));
356 state = 0;
357 setsockopt(dfd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
359 errno = 0;
360 memset(buff, 0, len);
363 if (unlikely(rlen < 0 && errno != EAGAIN))
364 syslog(LOG_ERR, "CPU%u: TCP tunnel read error: %s\n",
365 ws->cpu, strerror(errno));
367 return keep;
370 ssize_t handler_tcp_read(int fd, char *buff, size_t len)
372 ssize_t rlen;
373 struct ct_proto *hdr = (struct ct_proto *) buff;
375 if (!buff || !len) {
376 errno = EINVAL;
377 return 0;
380 /* May exit on EAGAIN if 0 Byte read */
381 rlen = read_exact(fd, buff, sizeof(struct ct_proto), 1);
382 if (rlen < 0)
383 return rlen;
384 if (unlikely(ntohs(hdr->payload) > len - sizeof(struct ct_proto))) {
385 errno = ENOMEM;
386 return 1; /* Force server to close connection */
388 /* May not exit on EAGAIN if 0 Byte read */
389 rlen = read_exact(fd, buff + sizeof(struct ct_proto),
390 ntohs(hdr->payload), 0);
391 if (rlen < 0)
392 return rlen;
394 return sizeof(struct ct_proto) + rlen;
397 static void handler_tcp_notify_close(int fd)
399 ssize_t err;
400 struct ct_proto hdr;
402 memset(&hdr, 0, sizeof(hdr));
403 hdr.flags |= PROTO_FLAG_EXIT;
404 hdr.payload = 0;
406 err = write(fd, &hdr, sizeof(hdr));
408 if (err < 0)
409 syslog(LOG_ERR, "Error while sending close notification: "
410 "%s!\n", strerror(errno));
413 static int handler_tcp_net_to_tun(int fd, const struct worker_struct *ws,
414 char *buff, size_t len)
416 int keep = 1, count = 0;
417 char *cbuff;
418 ssize_t rlen, err, clen;
419 struct ct_proto *hdr;
420 struct curve25519_proto *p;
422 if (!buff || !len) {
423 errno = EINVAL;
424 return 0;
427 errno = 0;
428 while ((rlen = handler_tcp_read(fd, buff, len)) > 0) {
429 p = NULL;
430 hdr = (struct ct_proto *) buff;
432 if (unlikely(rlen < sizeof(struct ct_proto)))
433 goto close;
434 if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
435 goto close;
436 if (unlikely(ntohs(hdr->payload) == 0))
437 goto close;
438 if (hdr->flags & PROTO_FLAG_EXIT) {
439 close:
440 remove_user_by_socket(fd);
441 trie_addr_remove(fd);
442 handler_tcp_notify_close(fd);
443 rlen = write(ws->parent.efd, &fd, sizeof(fd));
444 if (rlen != sizeof(fd))
445 syslog(LOG_ERR, "CPU%u: TCP event write error: %s\n",
446 ws->cpu, strerror(errno));
447 keep = 0;
448 return keep;
450 if (hdr->flags & PROTO_FLAG_INIT) {
451 if (auth_log)
452 syslog(LOG_INFO, "Got initial userhash from remote end!\n");
453 if (unlikely(rlen - sizeof(*hdr) <
454 sizeof(struct username_struct)))
455 goto close;
456 err = try_register_user_by_socket(ws->c, buff + sizeof(struct ct_proto),
457 rlen - sizeof(struct ct_proto),
458 fd, auth_log);
459 if (unlikely(err))
460 goto close;
461 continue;
464 err = get_user_by_socket(fd, &p);
465 if (unlikely(err || !p)) {
466 syslog(LOG_ERR, "CPU%u: User protocol not in cache! "
467 "Dropping connection!\n", ws->cpu);
468 goto close;
470 clen = curve25519_decode(ws->c, p, (unsigned char *) buff +
471 sizeof(struct ct_proto),
472 rlen - sizeof(struct ct_proto),
473 (unsigned char **) &cbuff, NULL);
474 if (unlikely(clen <= 0)) {
475 syslog(LOG_ERR, "CPU%u: TCP net decryption error: %zd\n",
476 ws->cpu, clen);
477 goto close;
479 cbuff += crypto_box_zerobytes;
480 clen -= crypto_box_zerobytes;
481 err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
482 fd, NULL, 0);
483 if (unlikely(err)) {
484 syslog(LOG_INFO, "CPU%u: Malicious packet dropped "
485 "from id %d\n", ws->cpu, fd);
486 continue;
489 err = write(ws->parent.tunfd, cbuff, clen);
490 if (unlikely(err < 0))
491 syslog(LOG_ERR, "CPU%u: TCP net write error: %s\n",
492 ws->cpu, strerror(errno));
494 count++;
495 if (count == 10) {
496 err = write_exact(ws->efd[1], &fd, sizeof(fd), 1);
497 if (unlikely(err != sizeof(fd)))
498 syslog(LOG_ERR, "CPU%u: TCP net put fd back in "
499 "pipe error: %s\n", ws->cpu, strerror(errno));
500 return keep;
503 errno = 0;
506 if (unlikely(rlen < 0 && errno != EAGAIN && errno != EBADF))
507 syslog(LOG_ERR, "CPU%u: TCP net read error: %s\n",
508 ws->cpu, strerror(errno));
510 return keep;
513 static int handler_tcp(int fd, const struct worker_struct *ws,
514 char *buff, size_t len)
516 int ret = 0;
517 if (fd == ws->parent.tunfd)
518 ret = handler_tcp_tun_to_net(fd, ws, buff, len);
519 else
520 ret = handler_tcp_net_to_tun(fd, ws, buff, len);
521 return ret;
524 static void *worker(void *self)
526 int fd, old_state;
527 ssize_t ret;
528 size_t blen = TUNBUFF_SIZ; //FIXME
529 const struct worker_struct *ws = self;
530 struct pollfd fds;
531 char *buff;
533 fds.fd = ws->efd[0];
534 fds.events = POLLIN;
536 ret = curve25519_alloc_or_maybe_die(ws->c);
537 if (ret < 0)
538 syslog_panic("Cannot init curve25519!\n");
540 buff = xmalloc_aligned(blen, 64);
541 syslog(LOG_INFO, "curvetun thread on CPU%u up!\n", ws->cpu);
542 pthread_cleanup_push(xfree_func, ws->c);
543 pthread_cleanup_push(curve25519_free, ws->c);
544 pthread_cleanup_push(xfree_func, buff);
546 while (likely(!sigint)) {
547 poll(&fds, 1, -1);
548 if ((fds.revents & POLLIN) != POLLIN)
549 continue;
550 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
551 while ((ret = read_exact(ws->efd[0], &fd, sizeof(fd), 1)) > 0) {
552 if (ret != sizeof(fd)) {
553 syslog(LOG_ERR, "CPU%u: Thread could not read "
554 "event descriptor!\n", ws->cpu);
555 sched_yield();
556 continue;
559 ret = ws->handler(fd, ws, buff, blen);
560 if (ret) {
561 ret = write_exact(ws->parent.refd, &fd, sizeof(fd), 1);
562 if (ret != sizeof(fd))
563 syslog(LOG_ERR, "CPU%u: Retriggering failed: "
564 "%s\n", ws->cpu, strerror(errno));
567 pthread_setcancelstate(old_state, NULL);
570 syslog(LOG_INFO, "curvetun thread on CPU%u down!\n", ws->cpu);
571 pthread_cleanup_pop(1);
572 pthread_cleanup_pop(1);
573 pthread_cleanup_pop(1);
574 pthread_exit((void *) ((long) ws->cpu));
577 static void thread_spawn_or_panic(unsigned int cpus, int efd, int refd,
578 int tunfd, int ipv4, int udp)
580 int i, ret;
581 cpu_set_t cpuset;
582 unsigned int threads;
584 threads = cpus * THREADS_PER_CPU;
585 for (i = 0; i < threads; ++i) {
586 CPU_ZERO(&cpuset);
587 threadpool[i].cpu = i % cpus;
588 CPU_SET(threadpool[i].cpu, &cpuset);
590 ret = pipe2(threadpool[i].efd, O_NONBLOCK);
591 if (ret < 0)
592 syslog_panic("Cannot create event socket!\n");
594 threadpool[i].c = xmalloc_aligned(sizeof(*threadpool[i].c), 64);
595 threadpool[i].parent.efd = efd;
596 threadpool[i].parent.refd = refd;
597 threadpool[i].parent.tunfd = tunfd;
598 threadpool[i].parent.ipv4 = ipv4;
599 threadpool[i].parent.udp = udp;
600 threadpool[i].handler = udp ? handler_udp : handler_tcp;
602 ret = pthread_create(&threadpool[i].trid, NULL,
603 worker, &threadpool[i]);
604 if (ret < 0)
605 syslog_panic("Thread creation failed!\n");
607 ret = pthread_setaffinity_np(threadpool[i].trid,
608 sizeof(cpuset), &cpuset);
609 if (ret < 0)
610 syslog_panic("Thread CPU migration failed!\n");
612 pthread_detach(threadpool[i].trid);
615 sleep(1);
618 static void thread_finish(unsigned int cpus)
620 int i;
621 unsigned int threads;
622 threads = cpus * THREADS_PER_CPU;
623 for (i = 0; i < threads; ++i) {
624 while (pthread_join(threadpool[i].trid, NULL) < 0)
626 close(threadpool[i].efd[0]);
627 close(threadpool[i].efd[1]);
631 int server_main(char *home, char *dev, char *port, int udp, int ipv4, int log)
633 int lfd = -1, kdpfd, nfds, nfd, curfds, efd[2], refd[2], tunfd, i, mtu;
634 unsigned int cpus = 0, threads, udp_cpu = 0;
635 ssize_t ret;
636 struct epoll_event ev, *events;
637 struct addrinfo hints, *ahead, *ai;
639 auth_log = !!log;
640 openlog("curvetun", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_DAEMON);
641 syslog(LOG_INFO, "curvetun server booting!\n");
642 if (!auth_log)
643 syslog(LOG_INFO, "curvetun user logging disabled!\n");
645 parse_userfile_and_generate_user_store_or_die(home);
647 memset(&hints, 0, sizeof(hints));
648 hints.ai_family = PF_UNSPEC;
649 hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
650 hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
651 hints.ai_flags = AI_PASSIVE;
653 ret = getaddrinfo(NULL, port, &hints, &ahead);
654 if (ret < 0)
655 syslog_panic("Cannot get address info!\n");
657 for (ai = ahead; ai != NULL && lfd < 0; ai = ai->ai_next) {
658 lfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
659 if (lfd < 0)
660 continue;
661 if (ai->ai_family == AF_INET6) {
662 int one = 1;
663 #ifdef IPV6_V6ONLY
664 ret = setsockopt(lfd, IPPROTO_IPV6, IPV6_V6ONLY,
665 &one, sizeof(one));
666 if (ret < 0) {
667 close(lfd);
668 lfd = -1;
669 continue;
671 #else
672 close(lfd);
673 lfd = -1;
674 continue;
675 #endif /* IPV6_V6ONLY */
677 set_reuseaddr(lfd);
678 mtu = IP_PMTUDISC_DONT;
679 setsockopt(lfd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
680 ret = bind(lfd, ai->ai_addr, ai->ai_addrlen);
681 if (ret < 0) {
682 close(lfd);
683 lfd = -1;
684 continue;
686 if (!udp) {
687 ret = listen(lfd, 5);
688 if (ret < 0) {
689 close(lfd);
690 lfd = -1;
691 continue;
694 if (ipv4 == -1) {
695 ipv4 = (ai->ai_family == AF_INET6 ? 0 :
696 (ai->ai_family == AF_INET ? 1 : -1));
698 if (auth_log) {
699 syslog(LOG_INFO, "curvetun on IPv%d via %s on port %s!\n",
700 ai->ai_family == AF_INET ? 4 : 6,
701 udp ? "UDP" : "TCP", port);
702 syslog(LOG_INFO, "Allowed overlay proto is IPv%d!\n",
703 ipv4 ? 4 : 6);
707 freeaddrinfo(ahead);
708 if (lfd < 0 || ipv4 < 0)
709 syslog_panic("Cannot create socket!\n");
711 tunfd = tun_open_or_die(dev ? dev : DEVNAME_SERVER, IFF_TUN | IFF_NO_PI);
713 ret = pipe2(efd, O_NONBLOCK);
714 if (ret < 0)
715 syslog_panic("Cannot create parent event fd!\n");
717 ret = pipe2(refd, O_NONBLOCK);
718 if (ret < 0)
719 syslog_panic("Cannot create parent (r)event fd!\n");
721 set_nonblocking(lfd);
723 events = xzmalloc(MAX_EPOLL_SIZE * sizeof(*events));
724 for (i = 0; i < MAX_EPOLL_SIZE; ++i)
725 events[i].data.fd = -1;
727 kdpfd = epoll_create(MAX_EPOLL_SIZE);
728 if (kdpfd < 0)
729 syslog_panic("Cannot create socket!\n");
731 memset(&ev, 0, sizeof(ev));
732 ev.events = udp ? EPOLLIN | EPOLLET | EPOLLONESHOT : EPOLLIN;
733 ev.data.fd = lfd;
734 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, lfd, &ev);
735 if (ret < 0)
736 syslog_panic("Cannot add socket for epoll!\n");
738 memset(&ev, 0, sizeof(ev));
739 ev.events = EPOLLIN;
740 ev.data.fd = efd[0];
741 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, efd[0], &ev);
742 if (ret < 0)
743 syslog_panic("Cannot add socket for events!\n");
745 memset(&ev, 0, sizeof(ev));
746 ev.events = EPOLLIN;
747 ev.data.fd = refd[0];
748 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, refd[0], &ev);
749 if (ret < 0)
750 syslog_panic("Cannot add socket for (r)events!\n");
752 memset(&ev, 0, sizeof(ev));
753 ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
754 ev.data.fd = tunfd;
755 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, tunfd, &ev);
756 if (ret < 0)
757 syslog_panic("Cannot add socket for tundev!\n");
759 curfds = 4;
761 trie_init();
763 cpus = get_number_cpus_online();
764 threads = cpus * THREADS_PER_CPU;
765 if (!((threads != 0) && ((threads & (threads - 1)) == 0)))
766 syslog_panic("Thread number not power of two!\n");
767 threadpool = xzmalloc(sizeof(*threadpool) * threads);
768 thread_spawn_or_panic(cpus, efd[1], refd[1], tunfd, ipv4, udp);
770 init_cpusched(threads);
771 register_socket(tunfd);
772 register_socket(lfd);
774 syslog(LOG_INFO, "curvetun up and running!\n");
776 while (likely(!sigint)) {
777 nfds = epoll_wait(kdpfd, events, curfds, -1);
778 if (nfds < 0) {
779 syslog(LOG_ERR, "epoll_wait error: %s\n",
780 strerror(errno));
781 break;
784 for (i = 0; i < nfds; ++i) {
785 if (unlikely(events[i].data.fd < 0))
786 continue;
787 if (events[i].data.fd == lfd && !udp) {
788 int one, ncpu;
789 char hbuff[256], sbuff[256];
790 struct sockaddr_storage taddr;
791 socklen_t tlen;
793 tlen = sizeof(taddr);
794 nfd = accept(lfd, (struct sockaddr *) &taddr,
795 &tlen);
796 if (nfd < 0) {
797 syslog(LOG_ERR, "accept error: %s\n",
798 strerror(errno));
799 continue;
802 if (curfds + 1 > MAX_EPOLL_SIZE) {
803 close(nfd);
804 continue;
807 curfds++;
808 ncpu = register_socket(nfd);
810 memset(hbuff, 0, sizeof(hbuff));
811 memset(sbuff, 0, sizeof(sbuff));
813 getnameinfo((struct sockaddr *) &taddr, tlen,
814 hbuff, sizeof(hbuff),
815 sbuff, sizeof(sbuff),
816 NI_NUMERICHOST | NI_NUMERICSERV);
818 if (auth_log) {
819 syslog(LOG_INFO, "New connection from %s:%s "
820 "with id %d on CPU%d, %d active!\n",
821 hbuff, sbuff, nfd, ncpu, curfds);
824 set_nonblocking(nfd);
826 one = 1;
827 setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE,
828 &one, sizeof(one));
829 one = 1;
830 setsockopt(nfd, IPPROTO_TCP, TCP_NODELAY,
831 &one, sizeof(one));
833 memset(&ev, 0, sizeof(ev));
834 ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
835 ev.data.fd = nfd;
836 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, nfd, &ev);
837 if (ret < 0) {
838 syslog(LOG_ERR, "Epoll ctl add error"
839 "on id %d: %s\n", nfd,
840 strerror(errno));
841 close(nfd);
842 curfds--;
843 continue;
845 } else if (events[i].data.fd == refd[0]) {
846 int fd_one;
848 ret = read_exact(refd[0], &fd_one, sizeof(fd_one), 1);
849 if (ret != sizeof(fd_one) || fd_one <= 0)
850 continue;
852 memset(&ev, 0, sizeof(ev));
853 ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
854 ev.data.fd = fd_one;
855 ret = epoll_ctl(kdpfd, EPOLL_CTL_MOD, fd_one, &ev);
856 if (ret < 0) {
857 syslog(LOG_ERR, "Epoll ctl mod "
858 "error on id %d: %s\n",
859 fd_one, strerror(errno));
860 close(fd_one);
861 continue;
863 } else if (events[i].data.fd == efd[0]) {
864 int fd_del, test;
866 ret = read_exact(efd[0], &fd_del, sizeof(fd_del), 1);
867 if (ret != sizeof(fd_del) || fd_del <= 0)
868 continue;
870 ret = read(fd_del, &test, sizeof(test));
871 if (ret < 0 && errno == EBADF)
872 continue;
874 ret = epoll_ctl(kdpfd, EPOLL_CTL_DEL, fd_del, &ev);
875 if (ret < 0) {
876 syslog(LOG_ERR, "Epoll ctl del "
877 "error on id %d: %s\n",
878 fd_del, strerror(errno));
879 close(fd_del);
880 continue;
882 close(fd_del);
883 curfds--;
884 unregister_socket(fd_del);
886 if (auth_log) {
887 syslog(LOG_INFO, "Closed connection with "
888 "id %d, %d active!\n",
889 fd_del, curfds);
891 } else {
892 int cpu, fd_work = events[i].data.fd;
893 if (!udp)
894 cpu = socket_to_cpu(fd_work);
895 else
896 udp_cpu = (udp_cpu + 1) & (threads - 1);
897 ret = write_exact(threadpool[udp ? udp_cpu : cpu].efd[1],
898 &fd_work, sizeof(fd_work), 1);
899 if (ret != sizeof(fd_work))
900 syslog(LOG_ERR, "Write error on event "
901 "dispatch: %s\n", strerror(errno));
906 syslog(LOG_INFO, "curvetun prepare shut down!\n");
908 close(lfd);
909 close(efd[0]);
910 close(efd[1]);
911 close(refd[0]);
912 close(refd[1]);
913 close(tunfd);
915 thread_finish(cpus);
916 xfree(threadpool);
917 xfree(events);
919 unregister_socket(lfd);
920 unregister_socket(tunfd);
921 destroy_cpusched();
922 trie_cleanup();
923 destroy_user_store();
925 syslog(LOG_INFO, "curvetun shut down!\n");
926 closelog();
928 return 0;