docs: fixed minor typo
[netsniff-ng.git] / src / ct_server.c
blob908eb5a31a92eb5b738081311fe78c273e45cab1
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;
93 if (!buff || len <= off) {
94 errno = EINVAL;
95 return 0;
97 errno = 0;
98 memset(buff, 0, len);
99 while ((rlen = read(fd, buff + off, len - off)) > 0) {
100 dfd = -1;
101 nlen = 0;
102 p = NULL;
103 memset(&naddr, 0, sizeof(naddr));
104 hdr = (struct ct_proto *) buff;
105 memset(hdr, 0, sizeof(*hdr));
106 hdr->flags = 0;
107 trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, &naddr,
108 (size_t *) &nlen);
109 if (unlikely(dfd < 0 || nlen == 0)) {
110 syslog(LOG_INFO, "CPU%u: UDP tunnel lookup failed: "
111 "unknown destination\n", ws->cpu);
112 memset(buff, 0, len);
113 continue;
115 err = get_user_by_sockaddr(&naddr, nlen, &p);
116 if (unlikely(err || !p)) {
117 syslog(LOG_ERR, "CPU%u: User protocol not in cache! "
118 "Dropping connection!\n", ws->cpu);
119 memset(buff, 0, len);
120 continue;
122 clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off -
123 crypto_box_zerobytes), (rlen +
124 crypto_box_zerobytes), (unsigned char **)
125 &cbuff);
126 if (unlikely(clen <= 0)) {
127 syslog(LOG_ERR, "CPU%u: UDP tunnel encrypt error: %zd\n",
128 ws->cpu, clen);
129 memset(buff, 0, len);
130 continue;
132 hdr->payload = htons((uint16_t) clen);
133 state = 1;
134 setsockopt(dfd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
135 err = sendto(dfd, hdr, sizeof(struct ct_proto), 0,
136 (struct sockaddr *) &naddr, nlen);
137 if (unlikely(err < 0))
138 syslog(LOG_ERR, "CPU%u: UDP tunnel write error: %s\n",
139 ws->cpu, strerror(errno));
140 err = sendto(dfd, cbuff, clen, 0, (struct sockaddr *) &naddr,
141 nlen);
142 if (unlikely(err < 0))
143 syslog(LOG_ERR, "CPU%u: UDP tunnel write error: %s\n",
144 ws->cpu, strerror(errno));
145 state = 0;
146 setsockopt(dfd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
147 errno = 0;
148 memset(buff, 0, len);
150 if (unlikely(rlen < 0 && errno != EAGAIN))
151 syslog(LOG_ERR, "CPU%u: UDP tunnel read error: %s\n",
152 ws->cpu, strerror(errno));
153 return keep;
156 static void handler_udp_notify_close(int fd, struct sockaddr_storage *addr)
158 ssize_t err;
159 struct ct_proto hdr;
160 memset(&hdr, 0, sizeof(hdr));
161 hdr.flags |= PROTO_FLAG_EXIT;
162 hdr.payload = 0;
163 err = sendto(fd, &hdr, sizeof(hdr), 0, (struct sockaddr *) addr, sizeof(*addr));
164 if (err < 0)
165 syslog(LOG_ERR, "Error while sending close notification: "
166 "%s!\n", strerror(errno));
169 static int handler_udp_net_to_tun(int fd, const struct worker_struct *ws,
170 char *buff, size_t len)
172 int keep = 1;
173 char *cbuff;
174 ssize_t rlen, err, clen;
175 struct ct_proto *hdr;
176 struct curve25519_proto *p;
177 struct sockaddr_storage naddr;
178 socklen_t nlen = sizeof(naddr);
179 if (!buff || !len) {
180 errno = EINVAL;
181 return 0;
183 memset(&naddr, 0, sizeof(naddr));
184 errno = 0;
185 while ((rlen = recvfrom(fd, buff, len, 0, (struct sockaddr *) &naddr,
186 &nlen)) > 0) {
187 p = NULL;
188 hdr = (struct ct_proto *) buff;
189 if (unlikely(rlen < sizeof(struct ct_proto)))
190 goto close;
191 if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
192 goto close;
193 if (unlikely(ntohs(hdr->payload) == 0))
194 goto close;
195 if (hdr->flags & PROTO_FLAG_EXIT) {
196 close:
197 remove_user_by_sockaddr(&naddr, nlen);
198 trie_addr_remove_addr(&naddr, nlen);
199 handler_udp_notify_close(fd, &naddr);
200 return keep;
202 if (hdr->flags & PROTO_FLAG_INIT) {
203 if (auth_log)
204 syslog(LOG_INFO, "Got initial userhash from remote end!\n");
205 if (unlikely(rlen - sizeof(*hdr) <
206 sizeof(struct username_struct)))
207 goto close;
208 err = try_register_user_by_sockaddr(ws->c, buff + sizeof(struct ct_proto),
209 rlen - sizeof(struct ct_proto),
210 &naddr, nlen, auth_log);
211 if (unlikely(err))
212 goto close;
213 goto next;
215 err = get_user_by_sockaddr(&naddr, nlen, &p);
216 if (unlikely(err || !p)) {
217 syslog(LOG_ERR, "CPU%u: User protocol not in cache! "
218 "Dropping connection!\n", ws->cpu);
219 goto close;
221 clen = curve25519_decode(ws->c, p, (unsigned char *) buff +
222 sizeof(struct ct_proto),
223 rlen - sizeof(struct ct_proto),
224 (unsigned char **) &cbuff, NULL);
225 if (unlikely(clen <= 0)) {
226 syslog(LOG_ERR, "CPU%u: UDP net decryption error: %zd\n",
227 ws->cpu, clen);
228 goto close;
230 cbuff += crypto_box_zerobytes;
231 clen -= crypto_box_zerobytes;
232 err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
233 fd, &naddr, nlen);
234 if (unlikely(err)) {
235 syslog(LOG_INFO, "CPU%u: Malicious packet dropped "
236 "from id %d\n", ws->cpu, fd);
237 goto next;
240 err = write(ws->parent.tunfd, cbuff, clen);
241 if (unlikely(err < 0))
242 syslog(LOG_ERR, "CPU%u: UDP net write error: %s\n",
243 ws->cpu, strerror(errno));
244 next:
245 nlen = sizeof(naddr);
246 memset(&naddr, 0, sizeof(naddr));
247 errno = 0;
249 if (unlikely(rlen < 0 && errno != EAGAIN))
250 syslog(LOG_ERR, "CPU%u: UDP net read error: %s\n",
251 ws->cpu, strerror(errno));
252 return keep;
255 static int handler_udp(int fd, const struct worker_struct *ws,
256 char *buff, size_t len)
258 int ret = 0;
259 if (fd == ws->parent.tunfd)
260 ret = handler_udp_tun_to_net(fd, ws, buff, len);
261 else
262 ret = handler_udp_net_to_tun(fd, ws, buff, len);
263 return ret;
266 static int handler_tcp_tun_to_net(int fd, const struct worker_struct *ws,
267 char *buff, size_t len)
269 int dfd, state, keep = 1;
270 char *cbuff;
271 ssize_t rlen, err, clen;
272 struct ct_proto *hdr;
273 struct curve25519_proto *p;
274 socklen_t nlen;
275 size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;
276 if (!buff || len <= off) {
277 errno = EINVAL;
278 return 0;
280 errno = 0;
281 memset(buff, 0, len);
282 while ((rlen = read(fd, buff + off, len - off)) > 0) {
283 dfd = -1;
284 p = NULL;
285 hdr = (struct ct_proto *) buff;
286 memset(hdr, 0, sizeof(*hdr));
287 hdr->flags = 0;
288 trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, NULL,
289 (size_t *) &nlen);
290 if (unlikely(dfd < 0)) {
291 syslog(LOG_INFO, "CPU%u: TCP tunnel lookup failed: "
292 "unknown destination\n", ws->cpu);
293 memset(buff, 0, len);
294 continue;
296 err = get_user_by_socket(dfd, &p);
297 if (unlikely(err || !p)) {
298 syslog(LOG_ERR, "CPU%u: User protocol not in cache! "
299 "Dropping connection!\n", ws->cpu);
300 memset(buff, 0, len);
301 continue;
303 clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off -
304 crypto_box_zerobytes), (rlen +
305 crypto_box_zerobytes), (unsigned char **)
306 &cbuff);
307 if (unlikely(clen <= 0)) {
308 syslog(LOG_ERR, "CPU%u: TCP tunnel encrypt error: %zd\n",
309 ws->cpu, clen);
310 memset(buff, 0, len);
311 continue;
313 hdr->payload = htons((uint16_t) clen);
314 state = 1;
315 setsockopt(dfd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
316 err = write_exact(dfd, hdr, sizeof(struct ct_proto), 0);
317 if (unlikely(err < 0))
318 syslog(LOG_ERR, "CPU%u: TCP tunnel write error: %s\n",
319 ws->cpu, strerror(errno));
320 err = write_exact(dfd, cbuff, clen, 0);
321 if (unlikely(err < 0))
322 syslog(LOG_ERR, "CPU%u: TCP tunnel write error: %s\n",
323 ws->cpu, strerror(errno));
324 state = 0;
325 setsockopt(dfd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
326 errno = 0;
327 memset(buff, 0, len);
329 if (unlikely(rlen < 0 && errno != EAGAIN))
330 syslog(LOG_ERR, "CPU%u: TCP tunnel read error: %s\n",
331 ws->cpu, strerror(errno));
332 return keep;
335 ssize_t handler_tcp_read(int fd, char *buff, size_t len)
337 ssize_t rlen;
338 struct ct_proto *hdr = (struct ct_proto *) buff;
339 if (!buff || !len) {
340 errno = EINVAL;
341 return 0;
343 /* May exit on EAGAIN if 0 Byte read */
344 rlen = read_exact(fd, buff, sizeof(struct ct_proto), 1);
345 if (rlen < 0)
346 return rlen;
347 if (unlikely(ntohs(hdr->payload) > len - sizeof(struct ct_proto))) {
348 errno = ENOMEM;
349 return 1; /* Force server to close connection */
351 /* May not exit on EAGAIN if 0 Byte read */
352 rlen = read_exact(fd, buff + sizeof(struct ct_proto),
353 ntohs(hdr->payload), 0);
354 if (rlen < 0)
355 return rlen;
356 return sizeof(struct ct_proto) + rlen;
359 static void handler_tcp_notify_close(int fd)
361 ssize_t err;
362 struct ct_proto hdr;
363 memset(&hdr, 0, sizeof(hdr));
364 hdr.flags |= PROTO_FLAG_EXIT;
365 hdr.payload = 0;
366 err = write(fd, &hdr, sizeof(hdr));
367 if (err < 0)
368 syslog(LOG_ERR, "Error while sending close notification: "
369 "%s!\n", strerror(errno));
372 static int handler_tcp_net_to_tun(int fd, const struct worker_struct *ws,
373 char *buff, size_t len)
375 int keep = 1, count = 0;
376 char *cbuff;
377 ssize_t rlen, err, clen;
378 struct ct_proto *hdr;
379 struct curve25519_proto *p;
380 if (!buff || !len) {
381 errno = EINVAL;
382 return 0;
384 errno = 0;
385 while ((rlen = handler_tcp_read(fd, buff, len)) > 0) {
386 p = NULL;
387 hdr = (struct ct_proto *) buff;
388 if (unlikely(rlen < sizeof(struct ct_proto)))
389 goto close;
390 if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
391 goto close;
392 if (unlikely(ntohs(hdr->payload) == 0))
393 goto close;
394 if (hdr->flags & PROTO_FLAG_EXIT) {
395 close:
396 remove_user_by_socket(fd);
397 trie_addr_remove(fd);
398 handler_tcp_notify_close(fd);
399 rlen = write(ws->parent.efd, &fd, sizeof(fd));
400 if (rlen != sizeof(fd))
401 syslog(LOG_ERR, "CPU%u: TCP event write error: %s\n",
402 ws->cpu, strerror(errno));
403 keep = 0;
404 return keep;
406 if (hdr->flags & PROTO_FLAG_INIT) {
407 if (auth_log)
408 syslog(LOG_INFO, "Got initial userhash from remote end!\n");
409 if (unlikely(rlen - sizeof(*hdr) <
410 sizeof(struct username_struct)))
411 goto close;
412 err = try_register_user_by_socket(ws->c, buff + sizeof(struct ct_proto),
413 rlen - sizeof(struct ct_proto),
414 fd, auth_log);
415 if (unlikely(err))
416 goto close;
417 continue;
419 err = get_user_by_socket(fd, &p);
420 if (unlikely(err || !p)) {
421 syslog(LOG_ERR, "CPU%u: User protocol not in cache! "
422 "Dropping connection!\n", ws->cpu);
423 goto close;
425 clen = curve25519_decode(ws->c, p, (unsigned char *) buff +
426 sizeof(struct ct_proto),
427 rlen - sizeof(struct ct_proto),
428 (unsigned char **) &cbuff, NULL);
429 if (unlikely(clen <= 0)) {
430 syslog(LOG_ERR, "CPU%u: TCP net decryption error: %zd\n",
431 ws->cpu, clen);
432 goto close;
434 cbuff += crypto_box_zerobytes;
435 clen -= crypto_box_zerobytes;
436 err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
437 fd, NULL, 0);
438 if (unlikely(err)) {
439 syslog(LOG_INFO, "CPU%u: Malicious packet dropped "
440 "from id %d\n", ws->cpu, fd);
441 continue;
443 err = write(ws->parent.tunfd, cbuff, clen);
444 if (unlikely(err < 0))
445 syslog(LOG_ERR, "CPU%u: TCP net write error: %s\n",
446 ws->cpu, strerror(errno));
447 count++;
448 if (count == 10) {
449 err = write_exact(ws->efd[1], &fd, sizeof(fd), 1);
450 if (unlikely(err != sizeof(fd)))
451 syslog(LOG_ERR, "CPU%u: TCP net put fd back in "
452 "pipe error: %s\n", ws->cpu, strerror(errno));
453 return keep;
455 errno = 0;
457 if (unlikely(rlen < 0 && errno != EAGAIN && errno != EBADF))
458 syslog(LOG_ERR, "CPU%u: TCP net read error: %s\n",
459 ws->cpu, strerror(errno));
460 return keep;
463 static int handler_tcp(int fd, const struct worker_struct *ws,
464 char *buff, size_t len)
466 int ret = 0;
467 if (fd == ws->parent.tunfd)
468 ret = handler_tcp_tun_to_net(fd, ws, buff, len);
469 else
470 ret = handler_tcp_net_to_tun(fd, ws, buff, len);
471 return ret;
474 static void *worker(void *self)
476 int fd, old_state;
477 ssize_t ret;
478 size_t blen = TUNBUFF_SIZ; //FIXME
479 const struct worker_struct *ws = self;
480 struct pollfd fds;
481 char *buff;
482 fds.fd = ws->efd[0];
483 fds.events = POLLIN;
484 ret = curve25519_alloc_or_maybe_die(ws->c);
485 if (ret < 0)
486 syslog_panic("Cannot init curve25519!\n");
487 buff = xmalloc_aligned(blen, 64);
488 syslog(LOG_INFO, "curvetun thread on CPU%u up!\n", ws->cpu);
489 pthread_cleanup_push(xfree_func, ws->c);
490 pthread_cleanup_push(curve25519_free, ws->c);
491 pthread_cleanup_push(xfree_func, buff);
492 while (likely(!sigint)) {
493 poll(&fds, 1, -1);
494 if ((fds.revents & POLLIN) != POLLIN)
495 continue;
496 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
497 while ((ret = read_exact(ws->efd[0], &fd, sizeof(fd), 1)) > 0) {
498 if (ret != sizeof(fd)) {
499 syslog(LOG_ERR, "CPU%u: Thread could not read "
500 "event descriptor!\n", ws->cpu);
501 sched_yield();
502 continue;
504 ret = ws->handler(fd, ws, buff, blen);
505 if (ret) {
506 ret = write_exact(ws->parent.refd, &fd, sizeof(fd), 1);
507 if (ret != sizeof(fd))
508 syslog(LOG_ERR, "CPU%u: Retriggering failed: "
509 "%s\n", ws->cpu, strerror(errno));
512 pthread_setcancelstate(old_state, NULL);
514 syslog(LOG_INFO, "curvetun thread on CPU%u down!\n", ws->cpu);
515 pthread_cleanup_pop(1);
516 pthread_cleanup_pop(1);
517 pthread_cleanup_pop(1);
518 pthread_exit((void *) ((long) ws->cpu));
521 static void thread_spawn_or_panic(unsigned int cpus, int efd, int refd,
522 int tunfd, int ipv4, int udp)
524 int i, ret;
525 cpu_set_t cpuset;
526 unsigned int threads;
527 threads = cpus * THREADS_PER_CPU;
528 for (i = 0; i < threads; ++i) {
529 CPU_ZERO(&cpuset);
530 threadpool[i].cpu = i % cpus;
531 CPU_SET(threadpool[i].cpu, &cpuset);
532 ret = pipe2(threadpool[i].efd, O_NONBLOCK);
533 if (ret < 0)
534 syslog_panic("Cannot create event socket!\n");
535 threadpool[i].c = xmalloc_aligned(sizeof(*threadpool[i].c), 64);
536 threadpool[i].parent.efd = efd;
537 threadpool[i].parent.refd = refd;
538 threadpool[i].parent.tunfd = tunfd;
539 threadpool[i].parent.ipv4 = ipv4;
540 threadpool[i].parent.udp = udp;
541 threadpool[i].handler = udp ? handler_udp : handler_tcp;
542 ret = pthread_create(&threadpool[i].trid, NULL,
543 worker, &threadpool[i]);
544 if (ret < 0)
545 syslog_panic("Thread creation failed!\n");
546 ret = pthread_setaffinity_np(threadpool[i].trid,
547 sizeof(cpuset), &cpuset);
548 if (ret < 0)
549 syslog_panic("Thread CPU migration failed!\n");
550 pthread_detach(threadpool[i].trid);
552 sleep(1);
555 static void thread_finish(unsigned int cpus)
557 int i;
558 unsigned int threads;
559 threads = cpus * THREADS_PER_CPU;
560 for (i = 0; i < threads; ++i) {
561 while (pthread_join(threadpool[i].trid, NULL) < 0)
563 close(threadpool[i].efd[0]);
564 close(threadpool[i].efd[1]);
568 int server_main(char *home, char *dev, char *port, int udp, int ipv4, int log)
570 int lfd = -1, kdpfd, nfds, nfd, curfds, efd[2], refd[2], tunfd, i, mtu;
571 unsigned int cpus = 0, threads, udp_cpu = 0;
572 ssize_t ret;
573 struct epoll_event ev, *events;
574 struct addrinfo hints, *ahead, *ai;
575 auth_log = !!log;
576 openlog("curvetun", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_DAEMON);
577 syslog(LOG_INFO, "curvetun server booting!\n");
578 if (!auth_log)
579 syslog(LOG_INFO, "curvetun user logging disabled!\n");
580 parse_userfile_and_generate_user_store_or_die(home);
581 memset(&hints, 0, sizeof(hints));
582 hints.ai_family = PF_UNSPEC;
583 hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
584 hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
585 hints.ai_flags = AI_PASSIVE;
586 ret = getaddrinfo(NULL, port, &hints, &ahead);
587 if (ret < 0)
588 syslog_panic("Cannot get address info!\n");
589 for (ai = ahead; ai != NULL && lfd < 0; ai = ai->ai_next) {
590 lfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
591 if (lfd < 0)
592 continue;
593 if (ai->ai_family == AF_INET6) {
594 int one = 1;
595 #ifdef IPV6_V6ONLY
596 ret = setsockopt(lfd, IPPROTO_IPV6, IPV6_V6ONLY,
597 &one, sizeof(one));
598 if (ret < 0) {
599 close(lfd);
600 lfd = -1;
601 continue;
603 #else
604 close(lfd);
605 lfd = -1;
606 continue;
607 #endif /* IPV6_V6ONLY */
609 set_reuseaddr(lfd);
610 mtu = IP_PMTUDISC_DONT;
611 setsockopt(lfd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
612 ret = bind(lfd, ai->ai_addr, ai->ai_addrlen);
613 if (ret < 0) {
614 close(lfd);
615 lfd = -1;
616 continue;
618 if (!udp) {
619 ret = listen(lfd, 5);
620 if (ret < 0) {
621 close(lfd);
622 lfd = -1;
623 continue;
626 if (ipv4 == -1) {
627 ipv4 = (ai->ai_family == AF_INET6 ? 0 :
628 (ai->ai_family == AF_INET ? 1 : -1));
630 if (auth_log) {
631 syslog(LOG_INFO, "curvetun on IPv%d via %s on port %s!\n",
632 ai->ai_family == AF_INET ? 4 : 6,
633 udp ? "UDP" : "TCP", port);
634 syslog(LOG_INFO, "Allowed overlay proto is IPv%d!\n",
635 ipv4 ? 4 : 6);
638 freeaddrinfo(ahead);
639 if (lfd < 0 || ipv4 < 0)
640 syslog_panic("Cannot create socket!\n");
641 tunfd = tun_open_or_die(dev ? dev : DEVNAME_SERVER, IFF_TUN | IFF_NO_PI);
642 ret = pipe2(efd, O_NONBLOCK);
643 if (ret < 0)
644 syslog_panic("Cannot create parent event fd!\n");
645 ret = pipe2(refd, O_NONBLOCK);
646 if (ret < 0)
647 syslog_panic("Cannot create parent (r)event fd!\n");
648 set_nonblocking(lfd);
649 events = xzmalloc(MAX_EPOLL_SIZE * sizeof(*events));
650 for (i = 0; i < MAX_EPOLL_SIZE; ++i)
651 events[i].data.fd = -1;
652 kdpfd = epoll_create(MAX_EPOLL_SIZE);
653 if (kdpfd < 0)
654 syslog_panic("Cannot create socket!\n");
655 memset(&ev, 0, sizeof(ev));
656 ev.events = udp ? EPOLLIN | EPOLLET | EPOLLONESHOT : EPOLLIN;
657 ev.data.fd = lfd;
658 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, lfd, &ev);
659 if (ret < 0)
660 syslog_panic("Cannot add socket for epoll!\n");
661 memset(&ev, 0, sizeof(ev));
662 ev.events = EPOLLIN;
663 ev.data.fd = efd[0];
664 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, efd[0], &ev);
665 if (ret < 0)
666 syslog_panic("Cannot add socket for events!\n");
667 memset(&ev, 0, sizeof(ev));
668 ev.events = EPOLLIN;
669 ev.data.fd = refd[0];
670 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, refd[0], &ev);
671 if (ret < 0)
672 syslog_panic("Cannot add socket for (r)events!\n");
673 memset(&ev, 0, sizeof(ev));
674 ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
675 ev.data.fd = tunfd;
676 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, tunfd, &ev);
677 if (ret < 0)
678 syslog_panic("Cannot add socket for tundev!\n");
679 curfds = 4;
680 trie_init();
681 cpus = get_number_cpus_online();
682 threads = cpus * THREADS_PER_CPU;
683 if (!((threads != 0) && ((threads & (threads - 1)) == 0)))
684 syslog_panic("Thread number not power of two!\n");
685 threadpool = xzmalloc(sizeof(*threadpool) * threads);
686 thread_spawn_or_panic(cpus, efd[1], refd[1], tunfd, ipv4, udp);
687 init_cpusched(threads);
688 register_socket(tunfd);
689 register_socket(lfd);
690 syslog(LOG_INFO, "curvetun up and running!\n");
691 while (likely(!sigint)) {
692 nfds = epoll_wait(kdpfd, events, curfds, -1);
693 if (nfds < 0) {
694 syslog(LOG_ERR, "epoll_wait error: %s\n",
695 strerror(errno));
696 break;
698 for (i = 0; i < nfds; ++i) {
699 if (unlikely(events[i].data.fd < 0))
700 continue;
701 if (events[i].data.fd == lfd && !udp) {
702 int one, ncpu;
703 char hbuff[256], sbuff[256];
704 struct sockaddr_storage taddr;
705 socklen_t tlen;
706 tlen = sizeof(taddr);
707 nfd = accept(lfd, (struct sockaddr *) &taddr,
708 &tlen);
709 if (nfd < 0) {
710 syslog(LOG_ERR, "accept error: %s\n",
711 strerror(errno));
712 continue;
714 if (curfds + 1 > MAX_EPOLL_SIZE) {
715 close(nfd);
716 continue;
718 curfds++;
719 ncpu = register_socket(nfd);
720 memset(hbuff, 0, sizeof(hbuff));
721 memset(sbuff, 0, sizeof(sbuff));
722 getnameinfo((struct sockaddr *) &taddr, tlen,
723 hbuff, sizeof(hbuff),
724 sbuff, sizeof(sbuff),
725 NI_NUMERICHOST | NI_NUMERICSERV);
726 if (auth_log) {
727 syslog(LOG_INFO, "New connection from %s:%s "
728 "with id %d on CPU%d, %d active!\n",
729 hbuff, sbuff, nfd, ncpu, curfds);
731 set_nonblocking(nfd);
732 one = 1;
733 setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE,
734 &one, sizeof(one));
735 one = 1;
736 setsockopt(nfd, IPPROTO_TCP, TCP_NODELAY,
737 &one, sizeof(one));
738 memset(&ev, 0, sizeof(ev));
739 ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
740 ev.data.fd = nfd;
741 ret = epoll_ctl(kdpfd, EPOLL_CTL_ADD, nfd, &ev);
742 if (ret < 0) {
743 syslog(LOG_ERR, "Epoll ctl add error"
744 "on id %d: %s\n", nfd,
745 strerror(errno));
746 close(nfd);
747 curfds--;
748 continue;
750 } else if (events[i].data.fd == refd[0]) {
751 int fd_one;
752 ret = read_exact(refd[0], &fd_one, sizeof(fd_one), 1);
753 if (ret != sizeof(fd_one) || fd_one <= 0)
754 continue;
755 memset(&ev, 0, sizeof(ev));
756 ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
757 ev.data.fd = fd_one;
758 ret = epoll_ctl(kdpfd, EPOLL_CTL_MOD, fd_one, &ev);
759 if (ret < 0) {
760 syslog(LOG_ERR, "Epoll ctl mod "
761 "error on id %d: %s\n",
762 fd_one, strerror(errno));
763 close(fd_one);
764 continue;
766 } else if (events[i].data.fd == efd[0]) {
767 int fd_del, test;
768 ret = read_exact(efd[0], &fd_del, sizeof(fd_del), 1);
769 if (ret != sizeof(fd_del) || fd_del <= 0)
770 continue;
771 ret = read(fd_del, &test, sizeof(test));
772 if (ret < 0 && errno == EBADF)
773 continue;
774 ret = epoll_ctl(kdpfd, EPOLL_CTL_DEL, fd_del, &ev);
775 if (ret < 0) {
776 syslog(LOG_ERR, "Epoll ctl del "
777 "error on id %d: %s\n",
778 fd_del, strerror(errno));
779 close(fd_del);
780 continue;
782 close(fd_del);
783 curfds--;
784 unregister_socket(fd_del);
785 if (auth_log) {
786 syslog(LOG_INFO, "Closed connection with "
787 "id %d, %d active!\n",
788 fd_del, curfds);
790 } else {
791 int cpu, fd_work = events[i].data.fd;
792 if (!udp)
793 cpu = socket_to_cpu(fd_work);
794 else
795 udp_cpu = (udp_cpu + 1) & (threads - 1);
796 ret = write_exact(threadpool[udp ? udp_cpu : cpu].efd[1],
797 &fd_work, sizeof(fd_work), 1);
798 if (ret != sizeof(fd_work))
799 syslog(LOG_ERR, "Write error on event "
800 "dispatch: %s\n", strerror(errno));
804 syslog(LOG_INFO, "curvetun prepare shut down!\n");
805 close(lfd);
806 close(efd[0]);
807 close(efd[1]);
808 close(refd[0]);
809 close(refd[1]);
810 close(tunfd);
811 thread_finish(cpus);
812 xfree(threadpool);
813 xfree(events);
814 unregister_socket(lfd);
815 unregister_socket(tunfd);
816 destroy_cpusched();
817 trie_cleanup();
818 destroy_user_store();
819 syslog(LOG_INFO, "curvetun shut down!\n");
820 closelog();
821 return 0;