write_or_die: renamed to more appropriate name, changed other files that have ref...
[netsniff-ng.git] / src / ct_server.c
blobe226a82ffabd2fc86bfabfb1fc87e68e5e4e2f8b
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 "netdev.h"
34 #include "xio.h"
35 #include "psched.h"
36 #include "xmalloc.h"
37 #include "curvetun.h"
38 #include "curve.h"
39 #include "compiler.h"
40 #include "usermgmt.h"
41 #include "cpusched.h"
42 #include "trie.h"
44 struct parent_info {
45 int efd;
46 int refd;
47 int tunfd;
48 int ipv4;
49 int udp;
52 struct worker_struct {
53 pthread_t trid;
54 int efd[2];
55 unsigned int cpu;
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;
87 char *cbuff;
88 ssize_t rlen, err, clen;
89 struct ct_proto *hdr;
90 struct curve25519_proto *p;
91 struct sockaddr_storage naddr;
92 socklen_t nlen;
93 size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;
95 if (!buff || len <= off) {
96 errno = EINVAL;
97 return 0;
100 errno = 0;
101 memset(buff, 0, len);
102 while ((rlen = read(fd, buff + off, len - off)) > 0) {
103 dfd = -1;
104 nlen = 0;
105 p = NULL;
106 memset(&naddr, 0, sizeof(naddr));
108 hdr = (struct ct_proto *) buff;
109 memset(hdr, 0, sizeof(*hdr));
110 hdr->flags = 0;
112 trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, &naddr,
113 (size_t *) &nlen);
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);
118 continue;
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);
125 continue;
127 clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off -
128 crypto_box_zerobytes), (rlen +
129 crypto_box_zerobytes), (unsigned char **)
130 &cbuff);
131 if (unlikely(clen <= 0)) {
132 syslog(LOG_ERR, "CPU%u: UDP tunnel encrypt error: %zd\n",
133 ws->cpu, clen);
134 memset(buff, 0, len);
135 continue;
138 hdr->payload = htons((uint16_t) clen);
140 state = 1;
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,
150 nlen);
151 if (unlikely(err < 0))
152 syslog(LOG_ERR, "CPU%u: UDP tunnel write error: %s\n",
153 ws->cpu, strerror(errno));
155 state = 0;
156 setsockopt(dfd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
158 errno = 0;
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));
166 return keep;
169 static void handler_udp_notify_close(int fd, struct sockaddr_storage *addr)
171 ssize_t err;
172 struct ct_proto hdr;
174 memset(&hdr, 0, sizeof(hdr));
175 hdr.flags |= PROTO_FLAG_EXIT;
176 hdr.payload = 0;
178 err = sendto(fd, &hdr, sizeof(hdr), 0, (struct sockaddr *) addr, sizeof(*addr));
180 if (err < 0)
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)
188 int keep = 1;
189 char *cbuff;
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);
196 if (!buff || !len) {
197 errno = EINVAL;
198 return 0;
201 memset(&naddr, 0, sizeof(naddr));
203 errno = 0;
204 while ((rlen = recvfrom(fd, buff, len, 0, (struct sockaddr *) &naddr,
205 &nlen)) > 0) {
206 p = NULL;
207 hdr = (struct ct_proto *) buff;
209 if (unlikely(rlen < sizeof(struct ct_proto)))
210 goto close;
211 if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
212 goto close;
213 if (unlikely(ntohs(hdr->payload) == 0))
214 goto close;
215 if (hdr->flags & PROTO_FLAG_EXIT) {
216 close:
217 remove_user_by_sockaddr(&naddr, nlen);
218 trie_addr_remove_addr(&naddr, nlen);
219 handler_udp_notify_close(fd, &naddr);
220 return keep;
222 if (hdr->flags & PROTO_FLAG_INIT) {
223 if (auth_log)
224 syslog(LOG_INFO, "Got initial userhash from remote end!\n");
225 if (unlikely(rlen - sizeof(*hdr) <
226 sizeof(struct username_struct)))
227 goto close;
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);
231 if (unlikely(err))
232 goto close;
233 goto next;
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);
240 goto close;
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",
248 ws->cpu, clen);
249 goto close;
251 cbuff += crypto_box_zerobytes;
252 clen -= crypto_box_zerobytes;
253 err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
254 fd, &naddr, nlen);
255 if (unlikely(err)) {
256 syslog(LOG_INFO, "CPU%u: Malicious packet dropped "
257 "from id %d\n", ws->cpu, fd);
258 goto next;
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));
266 next:
267 nlen = sizeof(naddr);
268 memset(&naddr, 0, sizeof(naddr));
269 errno = 0;
272 if (unlikely(rlen < 0 && errno != EAGAIN))
273 syslog(LOG_ERR, "CPU%u: UDP net read error: %s\n",
274 ws->cpu, strerror(errno));
276 return keep;
279 static int handler_udp(int fd, const struct worker_struct *ws,
280 char *buff, size_t len)
282 int ret = 0;
283 if (fd == ws->parent.tunfd)
284 ret = handler_udp_tun_to_net(fd, ws, buff, len);
285 else
286 ret = handler_udp_net_to_tun(fd, ws, buff, len);
287 return ret;
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;
294 char *cbuff;
295 ssize_t rlen, err, clen;
296 struct ct_proto *hdr;
297 struct curve25519_proto *p;
298 socklen_t nlen;
299 size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;
301 if (!buff || len <= off) {
302 errno = EINVAL;
303 return 0;
306 errno = 0;
307 memset(buff, 0, len);
308 while ((rlen = read(fd, buff + off, len - off)) > 0) {
309 dfd = -1;
310 p = NULL;
312 hdr = (struct ct_proto *) buff;
313 memset(hdr, 0, sizeof(*hdr));
314 hdr->flags = 0;
316 trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, NULL,
317 (size_t *) &nlen);
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);
322 continue;
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);
329 continue;
331 clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off -
332 crypto_box_zerobytes), (rlen +
333 crypto_box_zerobytes), (unsigned char **)
334 &cbuff);
335 if (unlikely(clen <= 0)) {
336 syslog(LOG_ERR, "CPU%u: TCP tunnel encrypt error: %zd\n",
337 ws->cpu, clen);
338 memset(buff, 0, len);
339 continue;
342 hdr->payload = htons((uint16_t) clen);
344 state = 1;
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));
357 state = 0;
358 setsockopt(dfd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
360 errno = 0;
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));
368 return keep;
371 ssize_t handler_tcp_read(int fd, char *buff, size_t len)
373 ssize_t rlen;
374 struct ct_proto *hdr = (struct ct_proto *) buff;
376 if (!buff || !len) {
377 errno = EINVAL;
378 return 0;
381 /* May exit on EAGAIN if 0 Byte read */
382 rlen = read_exact(fd, buff, sizeof(struct ct_proto), 1);
383 if (rlen < 0)
384 return rlen;
385 if (unlikely(ntohs(hdr->payload) > len - sizeof(struct ct_proto))) {
386 errno = ENOMEM;
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);
392 if (rlen < 0)
393 return rlen;
395 return sizeof(struct ct_proto) + rlen;
398 static void handler_tcp_notify_close(int fd)
400 ssize_t err;
401 struct ct_proto hdr;
403 memset(&hdr, 0, sizeof(hdr));
404 hdr.flags |= PROTO_FLAG_EXIT;
405 hdr.payload = 0;
407 err = write(fd, &hdr, sizeof(hdr));
409 if (err < 0)
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;
418 char *cbuff;
419 ssize_t rlen, err, clen;
420 struct ct_proto *hdr;
421 struct curve25519_proto *p;
423 if (!buff || !len) {
424 errno = EINVAL;
425 return 0;
428 errno = 0;
429 while ((rlen = handler_tcp_read(fd, buff, len)) > 0) {
430 p = NULL;
431 hdr = (struct ct_proto *) buff;
433 if (unlikely(rlen < sizeof(struct ct_proto)))
434 goto close;
435 if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
436 goto close;
437 if (unlikely(ntohs(hdr->payload) == 0))
438 goto close;
439 if (hdr->flags & PROTO_FLAG_EXIT) {
440 close:
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));
448 keep = 0;
449 return keep;
451 if (hdr->flags & PROTO_FLAG_INIT) {
452 if (auth_log)
453 syslog(LOG_INFO, "Got initial userhash from remote end!\n");
454 if (unlikely(rlen - sizeof(*hdr) <
455 sizeof(struct username_struct)))
456 goto close;
457 err = try_register_user_by_socket(ws->c, buff + sizeof(struct ct_proto),
458 rlen - sizeof(struct ct_proto),
459 fd, auth_log);
460 if (unlikely(err))
461 goto close;
462 continue;
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);
469 goto close;
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",
477 ws->cpu, clen);
478 goto close;
480 cbuff += crypto_box_zerobytes;
481 clen -= crypto_box_zerobytes;
482 err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
483 fd, NULL, 0);
484 if (unlikely(err)) {
485 syslog(LOG_INFO, "CPU%u: Malicious packet dropped "
486 "from id %d\n", ws->cpu, fd);
487 continue;
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));
495 count++;
496 if (count == 10) {
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));
501 return keep;
504 errno = 0;
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));
511 return keep;
514 static int handler_tcp(int fd, const struct worker_struct *ws,
515 char *buff, size_t len)
517 int ret = 0;
518 if (fd == ws->parent.tunfd)
519 ret = handler_tcp_tun_to_net(fd, ws, buff, len);
520 else
521 ret = handler_tcp_net_to_tun(fd, ws, buff, len);
522 return ret;
525 static void *worker(void *self)
527 int fd, old_state;
528 ssize_t ret;
529 size_t blen = TUNBUFF_SIZ; //FIXME
530 const struct worker_struct *ws = self;
531 struct pollfd fds;
532 char *buff;
534 fds.fd = ws->efd[0];
535 fds.events = POLLIN;
537 ret = curve25519_alloc_or_maybe_die(ws->c);
538 if (ret < 0)
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)) {
548 poll(&fds, 1, -1);
549 if ((fds.revents & POLLIN) != POLLIN)
550 continue;
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);
556 sched_yield();
557 continue;
560 ret = ws->handler(fd, ws, buff, blen);
561 if (ret) {
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)
581 int i, ret;
582 cpu_set_t cpuset;
583 unsigned int threads;
585 threads = cpus * THREADS_PER_CPU;
586 for (i = 0; i < threads; ++i) {
587 CPU_ZERO(&cpuset);
588 threadpool[i].cpu = i % cpus;
589 CPU_SET(threadpool[i].cpu, &cpuset);
591 ret = pipe2(threadpool[i].efd, O_NONBLOCK);
592 if (ret < 0)
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]);
605 if (ret < 0)
606 syslog_panic("Thread creation failed!\n");
608 ret = pthread_setaffinity_np(threadpool[i].trid,
609 sizeof(cpuset), &cpuset);
610 if (ret < 0)
611 syslog_panic("Thread CPU migration failed!\n");
613 pthread_detach(threadpool[i].trid);
616 sleep(1);
619 static void thread_finish(unsigned int cpus)
621 int i;
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;
636 ssize_t ret;
637 struct epoll_event ev, *events;
638 struct addrinfo hints, *ahead, *ai;
640 auth_log = !!log;
641 openlog("curvetun", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_DAEMON);
642 syslog(LOG_INFO, "curvetun server booting!\n");
643 if (!auth_log)
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);
655 if (ret < 0)
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);
660 if (lfd < 0)
661 continue;
662 if (ai->ai_family == AF_INET6) {
663 int one = 1;
664 #ifdef IPV6_V6ONLY
665 ret = setsockopt(lfd, IPPROTO_IPV6, IPV6_V6ONLY,
666 &one, sizeof(one));
667 if (ret < 0) {
668 close(lfd);
669 lfd = -1;
670 continue;
672 #else
673 close(lfd);
674 lfd = -1;
675 continue;
676 #endif /* IPV6_V6ONLY */
678 set_reuseaddr(lfd);
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);
682 if (ret < 0) {
683 close(lfd);
684 lfd = -1;
685 continue;
687 if (!udp) {
688 ret = listen(lfd, 5);
689 if (ret < 0) {
690 close(lfd);
691 lfd = -1;
692 continue;
695 if (ipv4 == -1) {
696 ipv4 = (ai->ai_family == AF_INET6 ? 0 :
697 (ai->ai_family == AF_INET ? 1 : -1));
699 if (auth_log) {
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",
704 ipv4 ? 4 : 6);
708 freeaddrinfo(ahead);
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);
715 if (ret < 0)
716 syslog_panic("Cannot create parent event fd!\n");
718 ret = pipe2(refd, O_NONBLOCK);
719 if (ret < 0)
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);
729 if (kdpfd < 0)
730 syslog_panic("Cannot create socket!\n");
732 memset(&ev, 0, sizeof(ev));
733 ev.events = udp ? EPOLLIN | EPOLLET | EPOLLONESHOT : EPOLLIN;
734 ev.data.fd = lfd;
735 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, lfd, &ev);
736 if (ret < 0)
737 syslog_panic("Cannot add socket for epoll!\n");
739 memset(&ev, 0, sizeof(ev));
740 ev.events = EPOLLIN;
741 ev.data.fd = efd[0];
742 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, efd[0], &ev);
743 if (ret < 0)
744 syslog_panic("Cannot add socket for events!\n");
746 memset(&ev, 0, sizeof(ev));
747 ev.events = EPOLLIN;
748 ev.data.fd = refd[0];
749 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, refd[0], &ev);
750 if (ret < 0)
751 syslog_panic("Cannot add socket for (r)events!\n");
753 memset(&ev, 0, sizeof(ev));
754 ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
755 ev.data.fd = tunfd;
756 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, tunfd, &ev);
757 if (ret < 0)
758 syslog_panic("Cannot add socket for tundev!\n");
760 curfds = 4;
762 trie_init();
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);
779 if (nfds < 0) {
780 syslog(LOG_ERR, "epoll_wait error: %s\n",
781 strerror(errno));
782 break;
785 for (i = 0; i < nfds; ++i) {
786 if (unlikely(events[i].data.fd < 0))
787 continue;
788 if (events[i].data.fd == lfd && !udp) {
789 int one, ncpu;
790 char hbuff[256], sbuff[256];
791 struct sockaddr_storage taddr;
792 socklen_t tlen;
794 tlen = sizeof(taddr);
795 nfd = accept(lfd, (struct sockaddr *) &taddr,
796 &tlen);
797 if (nfd < 0) {
798 syslog(LOG_ERR, "accept error: %s\n",
799 strerror(errno));
800 continue;
803 if (curfds + 1 > MAX_EPOLL_SIZE) {
804 close(nfd);
805 continue;
808 curfds++;
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);
819 if (auth_log) {
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);
827 one = 1;
828 setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE,
829 &one, sizeof(one));
830 one = 1;
831 setsockopt(nfd, IPPROTO_TCP, TCP_NODELAY,
832 &one, sizeof(one));
834 memset(&ev, 0, sizeof(ev));
835 ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
836 ev.data.fd = nfd;
837 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, nfd, &ev);
838 if (ret < 0) {
839 syslog(LOG_ERR, "Epoll ctl add error"
840 "on id %d: %s\n", nfd,
841 strerror(errno));
842 close(nfd);
843 curfds--;
844 continue;
846 } else if (events[i].data.fd == refd[0]) {
847 int fd_one;
849 ret = read_exact(refd[0], &fd_one, sizeof(fd_one), 1);
850 if (ret != sizeof(fd_one) || fd_one <= 0)
851 continue;
853 memset(&ev, 0, sizeof(ev));
854 ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
855 ev.data.fd = fd_one;
856 ret = epoll_ctl(kdpfd, EPOLL_CTL_MOD, fd_one, &ev);
857 if (ret < 0) {
858 syslog(LOG_ERR, "Epoll ctl mod "
859 "error on id %d: %s\n",
860 fd_one, strerror(errno));
861 close(fd_one);
862 continue;
864 } else if (events[i].data.fd == efd[0]) {
865 int fd_del, test;
867 ret = read_exact(efd[0], &fd_del, sizeof(fd_del), 1);
868 if (ret != sizeof(fd_del) || fd_del <= 0)
869 continue;
871 ret = read(fd_del, &test, sizeof(test));
872 if (ret < 0 && errno == EBADF)
873 continue;
875 ret = epoll_ctl(kdpfd, EPOLL_CTL_DEL, fd_del, &ev);
876 if (ret < 0) {
877 syslog(LOG_ERR, "Epoll ctl del "
878 "error on id %d: %s\n",
879 fd_del, strerror(errno));
880 close(fd_del);
881 continue;
883 close(fd_del);
884 curfds--;
885 unregister_socket(fd_del);
887 if (auth_log) {
888 syslog(LOG_INFO, "Closed connection with "
889 "id %d, %d active!\n",
890 fd_del, curfds);
892 } else {
893 int cpu, fd_work = events[i].data.fd;
894 if (!udp)
895 cpu = socket_to_cpu(fd_work);
896 else
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");
909 close(lfd);
910 close(efd[0]);
911 close(efd[1]);
912 close(refd[0]);
913 close(refd[1]);
914 close(tunfd);
916 thread_finish(cpus);
917 xfree(threadpool);
918 xfree(events);
920 unregister_socket(lfd);
921 unregister_socket(tunfd);
922 destroy_cpusched();
923 trie_cleanup();
924 destroy_user_store();
926 syslog(LOG_INFO, "curvetun shut down!\n");
927 closelog();
929 return 0;