236 if (!wg.on) shared::stat = INIT;
239 const std::string TNAME = wg.on ?
"WIREGUARD" :
"NETWORK";
250 queue local_in, local_out;
251 queue& thread_in = wg.on ? local_in : in;
252 queue& thread_out = wg.on ? local_out: out;
257 std::map<con_t, fd_t> fds;
263 uint64_t last_second = 0;
266 auto thread_self = self;
290 auto send_fd = [&TNAME, &wg, &fds](
const udp::packet& p,
const fd_t& fd) {
293 auto buffer = p.buffer();
299 switch (poll(&f, 1, 100)) {
300 case -1:
output(
"Send Error (poll)", TNAME, ERROR);
break;
303 fds.erase(p.destination().num);
306 if (send(fd, buffer.c_str(), buffer.length(), MSG_NOSIGNAL) < 1)
307 throw std::runtime_error(
"Failed to send packet.");
318 auto open_socket = [&TNAME, &wg](
const port_t& p) {
321 output(
"Setting up Listening Socket...", TNAME, INFO);
322 auto sock = socket(AF_INET, SOCK_STREAM, 0);
324 output(
"Failed to initialize socket!", TNAME, ERROR);
325 if (!wg.on) shared::stat = TERMINATE;
328 sockaddr_in server = {
329 .sin_family = AF_INET,
330 .sin_port = htons(p),
331 .sin_addr = {.s_addr = INADDR_ANY}
337 struct timeval timeout = {.tv_usec = 100};
339 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout,
sizeof(timeout));
340 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(yes));
343 if (bind(sock, (
struct sockaddr*)&server,
sizeof(server)) == -1) {
344 output(
"Failed to bind to socket!", TNAME, ERROR);
345 if (!wg.on) shared::stat = TERMINATE;
364 auto establish_connection = [&TNAME, &send_fd, &wg, &thread_self](
const connection& dest) {
365 output(
"New destination! Establishing connection...", TNAME, INFO);
368 auto fd = socket(AF_INET, SOCK_STREAM, 0);
370 output(
"Failed to create socket to destination!", TNAME, WARN);
374 .sin_family = AF_INET,
375 .sin_port = htons(dest.pair.p),
376 .sin_addr = {.s_addr = dest.pair.a},
381 output(
"Failed to connect to destination!", TNAME, WARN);
386 int flags = fcntl(fd, F_GETFL, 0);
387 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
392 send_fd({thread_self, dest,
"Hello!"}, fd);
395 catch (std::runtime_error& c) {
return -1;}
405 auto cleanup = [&sock, &fds, &thread_in, &thread_out, &wg, &TNAME]() {
406 output(
"Shutting down...", TNAME, INFO);
408 for (
auto f = fds.begin(); f != fds.end(); ++f) close(f->second);
416 thread_in.packets.clear(); thread_out.packets.clear();
417 thread_in.lock.unlock(); thread_out.lock.unlock();
419 output(
"Goodbye!", TNAME, INFO);
420 if (!wg.on) shared::stat = TERMINATE;
432 auto wait_for = [&thread_in](
const fd_t& fd,
const tag& tag) {
437 if (response.
data()[0] == tag)
break;
440 else thread_in.enqueue(response);
442 catch (std::runtime_error&) {}
457 output(
"Hello :)", TNAME, INFO);
463 std::uniform_int_distribution<std::mt19937::result_type> port_dist(2000,9000);
465 port = port_dist(rng);
466 sock = open_socket(port);
467 }
while (sock == -1);
469 else sock = open_socket(port);
471 output(
"Failed to open socket!", TNAME, ERROR);
474 thread_self.pair.p = port;
478 output(
"Listening!", TNAME, INFO);
479 if (!wg.on) shared::stat = READY;
493 output(
"Sending location to client", TNAME, INFO);
494 client_fd = establish_connection(wg.src);
498 info.source = thread_self;
500 send_fd(packet, client_fd);
503 fds[wg.src.num] = client_fd;
560 while(shared::stat != TERMINATE) {
599 bool fatal = time_since > wireguard::RJECT_TIME || wg.recv > wireguard::RJECT_MSGS;
602 if (time_since > wireguard::REKEY_TIME || wg.recv > wireguard::REKEY_MSGS) {
605 auto seconds = *
reinterpret_cast<uint64_t*
>(current.bytes());
608 if (seconds % wireguard::REKEY_TOUT == 0 && seconds != last_second) {
611 last_second = seconds;
614 sys_packet info = {.source = thread_self, .rekey =
true};
615 memcpy(&info.pub[0], wireguard::pair.pub().bytes(), 32);
617 auto fd = fds[wg.src.num];
626 auto pub = wait_for(fd, SYS).cast<
sys_packet>();
640 send_fd({peer, init_packet.
Serialize()}, fd);
642 auto response = wait_for(fd, WG_HANDSHAKE);
646 packet = wireguard::TransportPacket::Create(wg, {peer,
"Hello!"});
649 output(
"Completed Re-Exchange!", TNAME, INFO);
652 wg.timestamp = current;
672 catch (std::runtime_error&) {}
674 output(
"Client refused wireguard::REKEY after exceeding rejection limit! WireGuard connection is terminating!", TNAME, ERROR);
677 output(
"Client refused wireguard::REKEY after exceeding wireguard::REKEY threshold. Packets will not be processed until a re-key has been completed", TNAME, WARN);
699 if (listen(sock, 255) != 0) {
700 output(
"Failed to listen to socket!", TNAME, ERROR);
707 socklen_t size =
sizeof(peer);
708 fd_t
connection = accept(sock, (
struct sockaddr*)&peer, &size);
714 output(
"New connection!", TNAME, INFO);
724 auto src = p.source();
726 output(
"Connected!", TNAME, INFO);
730 catch (std::runtime_error& c) {
output(c.what(), TNAME, ERROR);}
743 while (!thread_out.empty()) {
746 auto p = thread_out.pop();
747 auto dest = p.destination();
757 if (p.source().num == 0 && fds.count(dest.num)) {
759 close(fds[dest.num]);
765 if (!fds.count(dest.num)) {
766 fds[dest.num] = establish_connection(dest);
770 auto fd = fds.at(dest.num);
775 catch (std::runtime_error& c) {
output(c.what(), TNAME, WARN);}
811 if (fds.size() != 0) {
814 struct pollfd fs[fds.size()] = {};
818 for (
auto f = fds.begin(); f != fds.end();) {
820 send_fd(heartbeat, f->second);
823 fs[x].fd = f->second;
824 fs[x].events = POLLIN;
829 catch (std::runtime_error& c) {
830 output(
"Heartbeat failure. Removing connection", TNAME, INFO);
837 if (f->first == wg.src.num) {
838 output(
"Client disconnected. Thank you for using WireGuard!", TNAME, INFO);
847 auto ready = poll(&fs[0], x, 100);
851 output(
"Failed to poll connections!", TNAME, ERROR);
856 else if (ready > 0) {
857 for (
size_t y = 0; y < x; ++y) {
859 if (fs[y].revents & POLLIN) {
868 if (packet.source().num == wg.src.num) {
869 output(
"Received packet from client. Decrypting and routing", TNAME, INFO);
871 decrypted.set_source(thread_self);
872 thread_out.enqueue(decrypted);
877 output(
"Received packet from another peer. Sending to client", TNAME, INFO);
878 auto encrypted = wireguard::TransportPacket::Create(wg, packet);
879 thread_out.enqueue(encrypted);
885 thread_in.enqueue(packet);
892 catch (std::runtime_error& c) {}
895 catch (std::length_error&) {
896 output(
"Failed to read from connection!", TNAME, WARN);