2 #if defined(__OpenBSD__)
5 #include <asm-generic/errno.h>
13 #define in_port_t u_short
15 #define my_tid_t DWORD
17 #include <arpa/inet.h>
21 #include <netinet/in.h>
24 #include <sys/socket.h>
26 #include <sys/types.h>
28 #define my_tid_t pthread_t
31 #include <openssl/bio.h>
32 #include <openssl/err.h>
33 #include <openssl/opensslv.h>
34 #include <openssl/rand.h>
35 #include <openssl/ssl.h>
37 #include "3rdparty/popl.hpp"
39 using namespace std::string_literals
;
41 static unsigned long id_thread(void) {
43 return (unsigned long)GetCurrentThreadId();
45 return (unsigned long)pthread_self();
49 #define debug_print(x) \
52 "Thread %lx:%s:%lld:%d:%s\n", \
60 //#define debug_print(x)
62 static auto closer
= [](int * sock_ptr
) {
64 closesocket(*sock_ptr
);
68 debug_print(("Closed socket="s
+ std::to_string(*sock_ptr
)).c_str());
71 void my_explain_recvfrom_error(int arg
) {
75 "The socket is marked nonblocking and the receive operation would "
77 "block, or a receive timeout had been set and the timeout expired "
79 "before data was received. POSIX.1 allows either error to be "
80 "returned for this case, and does not require these constants to "
82 "have the same value, so a portable application should check for "
83 "both possibilities.");
86 debug_print("The argument sockfd is an invalid file descriptor.");
90 "A remote host refused to allow the network connection( "
91 "typically because it is not running the requested service) "
96 "The receive buffer pointer(s) point outside the process's address "
101 "The receive was interrupted by delivery of a signal before "
102 "any data was available; see signal(7).");
105 debug_print("Invalid argument passed.");
108 debug_print("Could not allocate memory for recvmsg().");
111 debug_print("The socket is associated with a connection-oriented "
113 "not been connected (see connect(2) and accept(2)).");
116 debug_print("The file descriptor sockfd does not refer to a socket.");
120 ("Cannot explain recvfrom error "s
+ std::to_string(errno
)).c_str());
125 struct sockaddr_storage ss
;
126 struct sockaddr_in s4
;
127 struct sockaddr_in6 s6
;
130 std::string
my_ip46_address_to_string(my_ip46_address address_bin
) {
131 char addrbuf
[INET6_ADDRSTRLEN
];
133 if (address_bin
.ss
.ss_family
== AF_INET
) {
135 AF_INET
, &address_bin
.s4
.sin_addr
, addrbuf
, INET6_ADDRSTRLEN
);
136 port
= ntohs(address_bin
.s4
.sin_port
);
140 AF_INET6
, &address_bin
.s6
.sin6_addr
, addrbuf
, INET6_ADDRSTRLEN
);
141 port
= ntohs(address_bin
.s6
.sin6_port
);
144 return "["s
+ addrbuf
+ "]:" + std::to_string(port
);
147 void my_ip46_address_init(my_ip46_address
& address_bin
,
148 char const * address_txt
,
150 // unp address resolution
151 struct addrinfo hints
;
152 struct addrinfo
* res
;
153 struct addrinfo
* ressave
;
154 std::memset(&hints
, 0, sizeof(struct addrinfo
));
155 hints
.ai_flags
= AI_PASSIVE
;
156 hints
.ai_family
= AF_UNSPEC
;
157 hints
.ai_socktype
= SOCK_DGRAM
;
159 // simple ip address code
160 std::memset(&address_bin
, 0, sizeof(struct sockaddr_storage
));
162 ("Initing address "s
+ address_txt
+ ":" + std::to_string(port
))
165 #if !defined(__OpenBSD__)
166 if (inet_pton(AF_INET6
,
167 ("::FFFF:"s
+ address_txt
).c_str(),
168 &address_bin
.s6
.sin6_addr
) == 1) {
169 address_bin
.s6
.sin6_family
= AF_INET6
;
170 address_bin
.s6
.sin6_port
= htons(port
);
173 if (inet_pton(AF_INET
, address_txt
, &address_bin
.s4
.sin_addr
) == 1) {
174 address_bin
.s4
.sin_family
= AF_INET
;
175 debug_print(("It is an ipv4 address "s
).c_str());
178 address_bin
.s4
.sin_len
= sizeof(struct sockaddr_in
);
180 address_bin
.s4
.sin_port
= htons(port
);
181 } else if (inet_pton(AF_INET6
, address_txt
, &address_bin
.s6
.sin6_addr
) ==
183 address_bin
.s6
.sin6_family
= AF_INET6
;
184 debug_print(("It is an ipv6 address "s
).c_str());
186 address_bin
.s6
.sin6_len
= sizeof(struct sockaddr_in6
);
188 address_bin
.s6
.sin6_port
= htons(port
);
189 } else if ((unp_n
= getaddrinfo(address_txt
, NULL
, &hints
, &res
)) == 0) {
191 debug_print("It's a domain name!");
192 address_bin
.ss
.ss_family
= res
->ai_family
;
193 if (res
->ai_family
== AF_INET
) {
194 debug_print(("ipv4 domain name"s
).c_str());
195 std::memcpy(&address_bin
.s4
.sin_addr
,
196 &(((struct sockaddr_in
*)res
->ai_addr
)->sin_addr
),
197 sizeof(struct sockaddr_in
));
198 address_bin
.s4
.sin_port
= htons(port
);
200 address_bin
.s4
.sin_len
= sizeof(struct sockaddr_in
);
202 } else if (res
->ai_family
== AF_INET6
) {
203 debug_print(("ipv6 domain name"s
).c_str());
204 std::memcpy(&address_bin
.s6
.sin6_addr
,
205 &(((struct sockaddr_in6
*)res
->ai_addr
)->sin6_addr
),
206 sizeof(struct sockaddr_in6
));
207 address_bin
.s6
.sin6_port
= htons(port
);
209 address_bin
.s6
.sin6_len
= sizeof(struct sockaddr_in6
);
212 throw std::logic_error("Unknown address type for domain name.");
215 ("Connecting to: "s
+ my_ip46_address_to_string(address_bin
))
219 throw std::out_of_range("cannot set an address from address="s
+
221 " and port=" + std::to_string(port
));
224 // line 1229 connect TODO
226 void my_ip46_connect(int socket
, my_ip46_address remote_addr
) {
227 if (remote_addr
.ss
.ss_family
== AF_INET
) {
229 (struct sockaddr
*)&remote_addr
,
230 sizeof(struct sockaddr_in
))) {
231 perror("my_ip46_connect:connect4");
232 throw std::runtime_error("connect ipv4 failed");
234 } else if (remote_addr
.ss
.ss_family
== AF_INET6
) {
237 socket
, IPPROTO_IPV6
, IPV6_V6ONLY
, (char *)&off
, sizeof(off
));
239 (struct sockaddr
*)&remote_addr
,
240 sizeof(struct sockaddr_in6
))) {
241 perror("my_ip46_connect:connect6");
242 throw std::runtime_error("connect ipv6 failed");
245 debug_print("my_ip46_connect:wrong_family");
246 throw std::logic_error("my_ip46_connect: remote_addr.ss.ss_family not "
247 "AF_INET and AF_INET6");
251 void my_ip46_bind(int socket
, my_ip46_address local_addr
) {
252 std::cout
<< "ss_family=" << local_addr
.ss
.ss_family
<< std::endl
;
253 if (local_addr
.ss
.ss_family
== AF_INET
) {
255 (const struct sockaddr
*)&local_addr
,
256 sizeof(struct sockaddr_in
))) {
257 perror("my_ip46_bind:ipv4");
258 throw std::runtime_error("bind ipv4 failed");
260 } else if (local_addr
.ss
.ss_family
== AF_INET6
) {
263 socket
, IPPROTO_IPV6
, IPV6_V6ONLY
, (char *)&off
, sizeof(off
));
265 (const struct sockaddr
*)&local_addr
,
266 sizeof(struct sockaddr_in6
))) {
267 perror("my_ip46_bind:ipv6");
268 throw std::runtime_error("bind ipv6 failed");
271 debug_print("my_ip46_bind:wrong_family");
272 throw std::logic_error("my_ip46_bind: local_addr.ss.ss_family not "
273 "AF_INET and AF_INET6");
277 typedef struct pass_info
{
278 my_ip46_address server_addr
, client_addr
;
280 int socket_reverse_forward
= -1;
281 int socket_direct_forward
= -1;
282 my_ip46_address udp_ip_and_port
;
283 bool allow_udp_ip_port_from_inbound
= true;
284 unsigned int timeout_sec
= 10;
285 unsigned int ntimeouts
= 3;
288 void my_create_thread(
290 (DWORD WINAPI
)(*thread_function(LPVOID
* info
))
292 void(*thread_function(void * info
))
299 NULL
, 0, (LPTHREAD_START_ROUTINE
)thread_function
, info
, 0, tid
) ==
304 if (pthread_create(tid
, NULL
, thread_function
, info
) != 0) {
305 perror("pthread_create");
312 #define MY_EXIT_THREAD(retval) ExitThread(retval)
314 #define MY_EXIT_THREAD(retval) pthread_exit((void *)retval)
317 #define BUFFER_SIZE (1 << 16)
318 #define COOKIE_SECRET_LENGTH 16
322 unsigned char cookie_secret
[COOKIE_SECRET_LENGTH
];
323 int cookie_initialized
= 0;
326 static HANDLE
* mutex_buf
= NULL
;
328 static pthread_mutex_t
* mutex_buf
= NULL
;
331 static void locking_function(int mode
, int n
, const char * file
, int line
) {
332 if (mode
& CRYPTO_LOCK
)
334 WaitForSingleObject(mutex_buf
[n
], INFINITE
);
336 ReleaseMutex(mutex_buf
[n
]);
338 pthread_mutex_lock(&mutex_buf
[n
]);
340 pthread_mutex_unlock(&mutex_buf
[n
]);
348 mutex_buf
= (HANDLE
*)malloc(CRYPTO_num_locks() * sizeof(HANDLE
));
350 mutex_buf
= (pthread_mutex_t
*)malloc(CRYPTO_num_locks() *
351 sizeof(pthread_mutex_t
));
355 for (i
= 0; i
< CRYPTO_num_locks(); i
++)
357 mutex_buf
[i
] = CreateMutex(NULL
, FALSE
, NULL
);
359 pthread_mutex_init(&mutex_buf
[i
], NULL
);
361 CRYPTO_set_id_callback(id_thread
);
362 CRYPTO_set_locking_callback(locking_function
);
366 int THREAD_cleanup() {
372 CRYPTO_set_id_callback(NULL
);
373 CRYPTO_set_locking_callback(NULL
);
374 for (i
= 0; i
< CRYPTO_num_locks(); i
++)
376 CloseHandle(mutex_buf
[i
]);
378 pthread_mutex_destroy(&mutex_buf
[i
]);
385 int handle_socket_error() {
388 /* Interrupted system call.
391 printf("Interrupted system call!\n");
395 * Must close connection.
397 printf("Invalid socket!\n");
403 * Just ignore, might be an attacker
404 * sending fake ICMP messages.
406 printf("Host is down!\n");
411 /* Connection reset by peer.
412 * Just ignore, might be an attacker
413 * sending fake ICMP messages.
415 printf("Connection reset by peer!\n");
420 * Must close connection.
422 printf("Out of memory!\n");
426 /* Permission denied.
427 * Just ignore, we might be blocked
428 * by some firewall policy. Try again
429 * and hope for the best.
431 printf("Permission denied!\n");
435 /* Something unexpected happened */
436 printf("Unexpected error! (errno = %d)\n", errno
);
437 perror("Perror message");
444 int generate_cookie(SSL
* ssl
,
445 unsigned char * cookie
,
446 unsigned int * cookie_len
) {
447 unsigned char *buffer
, result
[EVP_MAX_MD_SIZE
];
448 unsigned int length
= 0, resultlength
;
449 my_ip46_address peer
;
451 /* Initialize a random secret */
452 if (!cookie_initialized
) {
453 if (!RAND_bytes(cookie_secret
, COOKIE_SECRET_LENGTH
)) {
454 printf("error setting random cookie secret\n");
457 cookie_initialized
= 1;
460 /* Read peer information */
461 (void)BIO_dgram_get_peer(SSL_get_rbio(ssl
), &peer
);
463 /* Create buffer with peer's address and port */
465 switch (peer
.ss
.ss_family
) {
467 length
+= sizeof(struct in_addr
);
470 length
+= sizeof(struct in6_addr
);
476 length
+= sizeof(in_port_t
);
477 buffer
= (unsigned char *)OPENSSL_malloc(length
);
479 if (buffer
== NULL
) {
480 printf("out of memory\n");
484 switch (peer
.ss
.ss_family
) {
486 std::memcpy(buffer
, &peer
.s4
.sin_port
, sizeof(in_port_t
));
487 std::memcpy(buffer
+ sizeof(peer
.s4
.sin_port
),
489 sizeof(struct in_addr
));
492 std::memcpy(buffer
, &peer
.s6
.sin6_port
, sizeof(in_port_t
));
493 std::memcpy(buffer
+ sizeof(in_port_t
),
495 sizeof(struct in6_addr
));
502 /* Calculate HMAC of buffer using the secret */
504 (const void *)cookie_secret
,
505 COOKIE_SECRET_LENGTH
,
506 (const unsigned char *)buffer
,
510 OPENSSL_free(buffer
);
512 std::memcpy(cookie
, result
, resultlength
);
513 *cookie_len
= resultlength
;
518 int verify_cookie(SSL
* ssl
,
519 const unsigned char * cookie
,
520 unsigned int cookie_len
) {
521 unsigned char *buffer
, result
[EVP_MAX_MD_SIZE
];
522 unsigned int length
= 0, resultlength
;
523 my_ip46_address peer
;
525 /* If secret isn't initialized yet, the cookie can't be valid */
526 if (!cookie_initialized
)
529 /* Read peer information */
530 (void)BIO_dgram_get_peer(SSL_get_rbio(ssl
), &peer
);
532 /* Create buffer with peer's address and port */
534 switch (peer
.ss
.ss_family
) {
536 length
+= sizeof(struct in_addr
);
539 length
+= sizeof(struct in6_addr
);
545 length
+= sizeof(in_port_t
);
546 buffer
= (unsigned char *)OPENSSL_malloc(length
);
548 if (buffer
== NULL
) {
549 printf("out of memory\n");
553 switch (peer
.ss
.ss_family
) {
555 std::memcpy(buffer
, &peer
.s4
.sin_port
, sizeof(in_port_t
));
556 std::memcpy(buffer
+ sizeof(in_port_t
),
558 sizeof(struct in_addr
));
561 std::memcpy(buffer
, &peer
.s6
.sin6_port
, sizeof(in_port_t
));
562 std::memcpy(buffer
+ sizeof(in_port_t
),
564 sizeof(struct in6_addr
));
571 /* Calculate HMAC of buffer using the secret */
573 (const void *)cookie_secret
,
574 COOKIE_SECRET_LENGTH
,
575 (const unsigned char *)buffer
,
579 OPENSSL_free(buffer
);
581 if (cookie_len
== resultlength
&&
582 memcmp(result
, cookie
, resultlength
) == 0)
588 int dtls_verify_callback(int ok
, X509_STORE_CTX
* ctx
) {
589 /* This function should ask the user
590 * if he trusts the received certificate.
591 * Here we always trust.
596 #define handle_error_en(en, msg) \
600 exit(EXIT_FAILURE); \
604 DWORD WINAPI
thread_udp_to_dtls(LPVOID
* info
)
606 void * thread_udp_to_dtls(void * info
)
609 debug_print("spawned");
610 int s
= pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
611 debug_print("enabled cancel");
613 handle_error_en(s
, "pthread_setcancelstate: write_dtls");
614 debug_print("handled cancel error");
615 pass_info_t
* pinfo
= static_cast<pass_info_t
*>(info
);
616 SSL
* ssl
= pinfo
->ssl
;
617 int udp_socket
= pinfo
->socket_reverse_forward
;
619 throw std::logic_error("client_reverse_forward_socket is not init");
620 struct sockaddr_storage useless_
;
621 struct sockaddr
* recvfrom_udp_target
=
622 (pinfo
->allow_udp_ip_port_from_inbound
623 ? reinterpret_cast<struct sockaddr
*>(&(pinfo
->udp_ip_and_port
.ss
))
624 : reinterpret_cast<struct sockaddr
*>(&useless_
));
626 char dtls_send_buffer
[BUFFER_SIZE
] = "hello, world";
627 int buffer_len
= strlen(dtls_send_buffer
);
629 struct timeval t_begin
{};
630 gettimeofday(&t_begin
, NULL
);
631 struct timeval t_end
{};
632 while (!(SSL_get_shutdown(ssl
))) { // & SSL_RECEIVED_SHUTDOWN
633 gettimeofday(&t_end
, NULL
);
634 debug_print(("packet processing took "s
+
635 std::to_string((t_end
.tv_sec
- t_begin
.tv_sec
) * 1000000 +
636 (t_end
.tv_usec
- t_begin
.tv_usec
)) +
641 debug_print("-------------------------------------------------------");
642 if (BUFFER_SIZE
< 1600)
643 throw std::logic_error("udp_to_dtls:buffer too small="s
+
644 std::to_string(BUFFER_SIZE
));
645 socklen_t sa_len
= sizeof(sockaddr_storage
);
647 ssize_t udp_read_len
= recvfrom(udp_socket
,
653 int my_errno
= errno
;
654 if (udp_read_len
< 0) {
655 if (errno
== EWOULDBLOCK
) {
656 debug_print("udp_to_dtls:Reading from udp socket timed out."
657 " I need to send something like a keepalive?");
659 } else if (errno
== ECONNREFUSED
) {
661 "udp socket has ECONNREFUSED bogus error. (debug it!)");
663 } else if (errno
== EINTR
) {
665 "udp socket returned EINTR. dropping datagram. (Debug it!)");
669 ("unexpected error when reading from udp socket on client, errno="s
+
670 std::to_string(errno
));
671 debug_print(a
.c_str());
672 my_explain_recvfrom_error(my_errno
);
673 throw std::runtime_error(a
);
679 // "\nThread %lx: got datagram from %s Size=%zd\n",
681 // my_ip46_address_to_string(pinfo->server_last_received_udp_addr)
683 // server_udp_read_len);
685 socklen_t dtls_write_len
=
686 SSL_write(ssl
, dtls_send_buffer
, udp_read_len
);
687 debug_print("wrote one message");
688 switch (SSL_get_error(ssl
, dtls_write_len
)) {
691 debug_print((""s
+ "wrote " + std::to_string(dtls_write_len
) +
697 case SSL_ERROR_WANT_WRITE
:
698 // Can't write because of a renegotiation, so
699 // we actually have to retry sending this message...
700 debug_print("SSL_ERROR_WANT_WRITE");
702 case SSL_ERROR_WANT_READ
:
703 debug_print("SSL_ERROR_WANT_READ");
704 // continue with reading
706 case SSL_ERROR_SYSCALL
:
707 debug_print("udp_to_dtls:SSL_ERROR_SYSCALL:Socket write error: ");
708 if (!handle_socket_error()) {
714 fprintf(stderr
, "udp_to_dtls:SSL write error: SSL_ERROR_SSL");
717 ERR_error_string(ERR_get_error(), dtls_send_buffer
),
718 SSL_get_error(ssl
, dtls_write_len
));
722 fprintf(stderr
, "udp_to_dtls:Unexpected error while writing!\n");
731 DWORD WINAPI
thread_dtls_to_udp(LPVOID
* info
)
733 void * thread_dtls_to_udp(void * info
)
736 // This thread should be reading FROM DTLS, and putting the packets
737 // into the udp socket of the proxied service.
738 debug_print("spawned");
739 int s
= pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
740 debug_print("enabled cancel");
742 handle_error_en(s
, "pthread_setcancelstate: read_dtls");
743 debug_print("handled cancel error");
745 pass_info_t
* pinfo
= static_cast<pass_info_t
*>(info
);
746 SSL
* ssl
= pinfo
->ssl
;
747 // std::unique_ptr<SSL, int (*)(SSL *)> ssl_guard(ssl, SSL_shutdown);
748 int udp_socket
= pinfo
->socket_reverse_forward
;
750 throw std::logic_error("dtls_to_udp:udp socket is not init");
751 int num_timeouts
= 0;
752 int const max_timeouts
= pinfo
->ntimeouts
;
753 char dtls_to_udp_buffer
[BUFFER_SIZE
] = "hello world";
755 struct timeval t_begin
{};
756 gettimeofday(&t_begin
, NULL
);
757 struct timeval t_end
{};
759 while (!(SSL_get_shutdown(ssl
))) { // & SSL_RECEIVED_SHUTDOWN
760 gettimeofday(&t_end
, NULL
);
761 debug_print(("Iteration processing took "s
+
762 std::to_string((t_end
.tv_sec
- t_begin
.tv_sec
) * 1000000 +
763 (t_end
.tv_usec
- t_begin
.tv_usec
)) +
768 debug_print(("dtls_to_udp: already saw "s
+
769 std::to_string(num_timeouts
) + " timeouts")
771 if (num_timeouts
> max_timeouts
) {
772 debug_print(("No data received from dtls for too long: "s
+
773 std::to_string(max_timeouts
) +
774 " timeouts. Breaking dtls_to_udp loop.")
776 // SSL_shutdown(ssl);
780 debug_print("-------------------------------------------------------");
781 ssize_t dtls_read_len
=
782 SSL_read(ssl
, dtls_to_udp_buffer
, sizeof(dtls_to_udp_buffer
));
784 switch (SSL_get_error(ssl
, dtls_read_len
)) {
788 ("dtls_to_udp read " + std::to_string(dtls_read_len
) + " bytes")
791 debug_print("Not printing received packet, not implemented.");
793 case SSL_ERROR_WANT_READ
:
794 // Stop reading on socket timeout, otherwise try again
795 debug_print("DTLS:SSL_ERROR_WANT_READ:on SSL_read().");
796 if (BIO_ctrl(SSL_get_rbio(ssl
),
797 BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP
,
800 debug_print("Timeout! No packet received from dtls.\n");
804 "SSL_ERROR_WANT_READ, but where does it come from? TODO");
809 case SSL_ERROR_ZERO_RETURN
:
810 debug_print("dtls_to_udp:SSL_ERROR_ZERO_RETURN");
811 // Shall we break here? Wtf?
813 case SSL_ERROR_SYSCALL
:
814 if (errno
== EAGAIN
) {
815 // Why does the socket timeout appear here, not in BIO_ctrl?
817 "dtls_to_udp:SSL_ERROR_SYSCALL:dtls read error:0: EAGAIN");
819 "Received nothing from the server for too long. (EAGAIN) "
820 "Breaking connection. This method is bad, because we "
821 "may be sending data, so the connection is still "
822 "valid, but so far let us make a temporary solution.");
826 fprintf(stderr
, "dtls_to_udp:SSL_ERROR_SYSCALL:not EAGAIN\n");
827 if (!handle_socket_error()) {
829 "dtls_to_udp:SSL_ERROR_SYSCALL:Unhandled syscall socket "
830 "error on reading.");
836 "dtls_to_udp:SSL_ERROR_SSL:exiting because of SSL read error: ");
839 ERR_error_string(ERR_get_error(), dtls_to_udp_buffer
),
840 SSL_get_error(ssl
, dtls_read_len
));
843 debug_print("dtls_to_udp:Unexpected error while reading!\n");
846 debug_print("Received a message over dtls");
847 // Processed all the reading crap, and ready to do something with the
848 // data in "server_dtls_receive_buffer", of length
850 // and we send it to pinfo->server_last_received_udp_addr
851 // So, my datagram is in client_dtls_read_buffer, and the real
852 // length of it is ssl_read_len. So, I need something like:
853 // Sendto_flags(sockfd, dataBuffer, 0, pservaddr, servlen);
854 // This will send that datagram to the 2ping-server.
855 // This should be enough for simplicity.
856 // client_reverse_socket is already bound, so it should
857 // sendto_flagsORwrite(client_reverse_socket,client_dtls_read_buffer,ssl_read_len);
858 // write(client_reverse_socket, client_dtls_read_buffer,
860 //! Why exactly I chose "sendto", I am not very sure.
861 //! I did not want to use write(), because it is not
862 //! socket-specific. And sendmsg is a bit annoying with
863 //! its scatter/gather machinery.
865 if (pinfo
->udp_ip_and_port
.ss
.ss_family
== 0) {
867 "No return address received yet from client, or the address is "
868 "not given when starting. Dropping datagram.");
871 socklen_t sa_len
= sizeof(struct sockaddr_storage
);
872 ssize_t dtls_to_udp_write_len
;
874 dtls_to_udp_write_len
= sendto(
879 reinterpret_cast<struct sockaddr
*>(&(pinfo
->udp_ip_and_port
)),
881 } while (dtls_to_udp_write_len
< 0 && errno
== EAGAIN
);
882 int my_errno
= errno
;
884 ("ssl_read_len="s
+ std::to_string(dtls_read_len
)).c_str());
886 ("udp_write_len="s
+ std::to_string(dtls_to_udp_write_len
)).c_str());
888 if (dtls_to_udp_write_len
>= 0 &&
889 dtls_to_udp_write_len
== dtls_read_len
) {
890 debug_print("Written packet to client socket successfully");
893 if (dtls_to_udp_write_len
>= 0 &&
894 dtls_to_udp_write_len
!= dtls_read_len
) {
895 throw std::logic_error("written bytes do not match requested");
898 if (dtls_to_udp_write_len
< 0) {
899 debug_print("Writing to client udp socket failed. Let's see why.");
901 if (my_errno
== EAGAIN
) {
902 debug_print("EAGAIN on writing to udp socket. Why? Dropping "
903 "packet. (this should not happen) TODO.");
904 throw std::logic_error("EAGAIN on writing to udp socket");
907 if (my_errno
== ECONNREFUSED
) {
908 debug_print("Udp socket has no service running, perhaps, "
909 "crashed, or whatever. Dropping packet.");
913 if (dtls_read_len
> SSIZE_MAX
) {
914 debug_print("dtls_to_udp:dtls_read_len > SSIZE_MAX. Logic error. "
916 throw std::logic_error("dtls_read_len > SSIZE_MAX");
919 if (my_errno
== EINVAL
) {
920 debug_print("UDP: EINVAL. Some argument to sendto is wrong");
921 throw std::logic_error(
922 "UDP: EINVAL. Some argument to sendto is wrong");
925 "unexpected error when writing to udp socket on client, errno="s
+
926 std::to_string(my_errno
);
927 debug_print(a
.c_str());
928 my_explain_recvfrom_error(my_errno
);
929 throw std::runtime_error(a
);
932 // SSL_shutdown(ssl);
937 DWORD WINAPI
thread_server_handle_dtls_connection(LPVOID
* info
)
939 void * thread_server_handle_dtls_connection(void * info
)
942 // Start making a new socket for this particular tls connection.
943 auto myInfoGuard
= std::unique_ptr
<pass_info_t
, void (*)(void *)>(
944 reinterpret_cast<pass_info_t
*>(info
), free
);
945 pass_info_t
* pinfo
= reinterpret_cast<pass_info_t
*>(info
);
946 SSL
* ssl
= pinfo
->ssl
;
947 auto mySSLGuard
= std::unique_ptr
<SSL
, void (*)(SSL
*)>(ssl
, SSL_free
);
949 int server_dtls_connection_socket
;
950 auto mySocketGuard
= std::unique_ptr
<int, void (*)(int *)>(
951 &server_dtls_connection_socket
, closer
);
952 if (sizeof(void *) != sizeof(int *))
953 throw std::logic_error("Size of void* too small");
956 ssize_t dtls_message_len
;
957 char buf
[BUFFER_SIZE
];
958 char addrbuf
[INET6_ADDRSTRLEN
];
962 const int on
= 1, off
= 0;
963 struct timeval timeout
;
964 int num_timeouts
= 0;
965 int const max_timeouts
= pinfo
->ntimeouts
;
966 void * pthread_join_retval
= nullptr;
969 pthread_detach(pthread_self());
972 OPENSSL_assert(pinfo
->client_addr
.ss
.ss_family
==
973 pinfo
->server_addr
.ss
.ss_family
);
974 debug_print(("pinfo->client_addr.ss.ss_family="s
+
975 std::to_string(pinfo
->client_addr
.ss
.ss_family
))
977 debug_print(("pinfo->server_addr.ss.ss_family="s
+
978 std::to_string(pinfo
->server_addr
.ss
.ss_family
))
980 server_dtls_connection_socket
=
981 socket(pinfo
->client_addr
.ss
.ss_family
, SOCK_DGRAM
, 0);
982 if (server_dtls_connection_socket
< 0) {
989 setsockopt(server_dtls_connection_socket
,
993 (socklen_t
)sizeof(on
));
995 setsockopt(server_dtls_connection_socket
,
999 (socklen_t
)sizeof(on
));
1000 #if defined(SO_REUSEPORT) && !defined(__linux__)
1001 setsockopt(server_dtls_connection_socket
,
1005 (socklen_t
)sizeof(on
));
1008 switch (pinfo
->client_addr
.ss
.ss_family
) {
1010 debug_print("client_addr.ss.ss_family=AF_INET");
1013 debug_print("client_addr.ss.ss_family=AF_INET6");
1016 debug_print("wrong family");
1022 my_ip46_bind(server_dtls_connection_socket
, pinfo
->server_addr
);
1023 debug_print("Bind worked!");
1024 my_ip46_connect(server_dtls_connection_socket
, pinfo
->client_addr
);
1025 debug_print("Connect worked!");
1026 } catch (std::runtime_error ex
) {
1027 debug_print(("Exception!:"s
+ ex
.what()).c_str());
1030 debug_print(("Big exception!"));
1034 /* Set new fd and set BIO to connected */
1036 SSL_get_rbio(ssl
), server_dtls_connection_socket
, BIO_NOCLOSE
);
1037 BIO_ctrl(SSL_get_rbio(ssl
),
1038 BIO_CTRL_DGRAM_SET_CONNECTED
,
1040 &pinfo
->client_addr
.ss
);
1042 /* Finish handshake */
1044 ret
= SSL_accept(ssl
);
1047 perror("SSL_accept");
1048 fprintf(stderr
, "%s\n", ERR_error_string(ERR_get_error(), buf
));
1053 /* Set and activate timeouts */
1055 timeout
.tv_sec
= pinfo
->timeout_sec
;
1056 timeout
.tv_usec
= 0;
1058 SSL_get_rbio(ssl
), BIO_CTRL_DGRAM_SET_RECV_TIMEOUT
, 0, &timeout
);
1060 #if defined(__OpenBSD__)
1061 BIO_set_buffer_size(SSL_get_rbio(ssl
), 2000000);
1062 BIO_set_read_buffer_size(SSL_get_rbio(ssl
), 2000000);
1064 BIO_set_buffer_size(SSL_get_rbio(ssl
), 20000000);
1065 BIO_set_read_buffer_size(SSL_get_rbio(ssl
), 20000000);
1068 if (pinfo
->client_addr
.ss
.ss_family
== AF_INET
) {
1070 "\nThread %lx: accepted connection from %s:%d\n",
1073 &pinfo
->client_addr
.s4
.sin_addr
,
1076 ntohs(pinfo
->client_addr
.s4
.sin_port
));
1079 "\nThread %lx: accepted connection from %s:%d\n",
1082 &pinfo
->client_addr
.s6
.sin6_addr
,
1085 ntohs(pinfo
->client_addr
.s6
.sin6_port
));
1089 if (veryverbose
&& SSL_get_peer_certificate(ssl
)) {
1092 "------------------------------------------------------------\n");
1094 X509_NAME_print_ex_fp(
1096 X509_get_subject_name(SSL_get_peer_certificate(ssl
)),
1102 SSL_CIPHER_get_name(SSL_get_current_cipher(ssl
)));
1105 "\n------------------------------------------------------------"
1109 // my: so here we have established a connection, and are using something
1110 // (let me check what) for reading and writing.
1111 // (1) ssl is used in SSL_get_shutdown,
1112 // (2) buf although buffers are cheap in C++
1113 // This loop will exist in both threads.
1114 debug_print("before two threads");
1115 my_tid_t tid_thread_server_dtls_to_udp
;
1116 my_tid_t tid_thread_server_udp_to_dtls
;
1118 thread_dtls_to_udp
, info
, &tid_thread_server_dtls_to_udp
);
1119 debug_print("created thread for server_dtls_to_udp");
1121 thread_udp_to_dtls
, info
, &tid_thread_server_udp_to_dtls
);
1122 debug_print("created thread for server_udp_to_dtls");
1124 pthread_join(tid_thread_server_dtls_to_udp
, &pthread_join_retval
);
1125 debug_print("joined thread_server_dtls_to_udp");
1127 // if (pthread_join_retval != 0) {
1128 // // pthread_cancel(tid_write_thread);
1131 pthread_join(tid_thread_server_udp_to_dtls
, &pthread_join_retval
);
1132 debug_print("joined thread_server_udp_to_dtls");
1134 // if (pthread_join_retval != 0)
1137 // Here I will have to wait for these threads to finish, or I will
1138 // never call this shutdown, so I cannot self-detach.
1139 // But what happens if this thread should die?
1140 // I guess, if my dispatcher thread receives a new incoming connection,
1141 // it should publish a tid in some std::set , and the two writing-reading
1142 // threads will have to check that std::set instance, and terminate
1147 fprintf(stderr
, "Thread %lx: done, connection closed.\n", id_thread());
1151 std::pair
<int, my_ip46_address
>
1152 setup_udp_socket(std::string forward_address
,
1154 std::string local_address
,
1156 // const int on = 1, off = 0;
1157 struct timeval socket_timeout
{
1160 my_ip46_address local_udp_addr
;
1161 if (local_address
== ""s
) {
1162 local_udp_addr
.s6
.sin6_family
= AF_INET6
;
1163 #ifdef HAVE_SIN6_LEN
1164 local_udp_addr
.s6
.sin6_len
= sizeof(struct sockaddr_in6
);
1166 local_udp_addr
.s6
.sin6_addr
= in6addr_any
;
1167 local_udp_addr
.s6
.sin6_port
= htons(local_port
);
1169 my_ip46_address_init(
1170 local_udp_addr
, local_address
.c_str(), local_port
);
1172 my_ip46_address forward_addr
{};
1173 if (!forward_address
.empty()) {
1174 my_ip46_address_init(
1175 forward_addr
, forward_address
.c_str(), forward_port
);
1176 debug_print(("making a socket for communicating with "s
+
1177 forward_address
+ ":" + std::to_string(forward_port
))
1180 debug_print(("Making udp socket. udp-local-address="s
+
1181 my_ip46_address_to_string(local_udp_addr
) +
1182 " forward_addr=" + my_ip46_address_to_string(forward_addr
))
1184 int udp_socket
= socket(local_udp_addr
.ss
.ss_family
, SOCK_DGRAM
, 0);
1185 if (udp_socket
< 0) {
1186 perror("server_udp_socket:socket()_fail");
1189 int const off
= 0, on
= 1;
1190 #if !defined(__OpenBSD__)
1192 udp_socket
, IPPROTO_IPV6
, IPV6_V6ONLY
, (char *)&off
, sizeof(off
)) <
1194 throw std::logic_error(
1195 "setup_server_udp_socket failed:setsockopt IPV6_ONLY=off");
1197 #if defined(__OpenBSD__)
1200 int size
= 20000000;
1203 setsockopt(udp_socket
, SOL_SOCKET
, SO_SNDBUF
, &size
, sizeof(size
)))
1204 throw std::logic_error("cannot set UDP SO_SNDBUF");
1206 setsockopt(udp_socket
, SOL_SOCKET
, SO_RCVBUF
, &size
, sizeof(size
)))
1207 throw std::logic_error("cannot set UDP SO_RCVBUF");
1208 my_ip46_bind(udp_socket
, local_udp_addr
);
1209 if (setsockopt(udp_socket
,
1213 sizeof(socket_timeout
)) < 0) {
1214 debug_print("setup_server_udp_socket failed:setsockopt");
1215 throw std::logic_error("setup_server_udp_socket failed:setsockopt");
1217 debug_print("server udp socket succeeded");
1218 return std::make_pair(udp_socket
, forward_addr
);
1221 void start_server_dtls(int port
,
1222 char const * dtls_local_address
,
1224 my_ip46_address forward_address
,
1225 bool allow_update_forward_address
,
1226 std::string cert_path
,
1227 std::string key_path
,
1228 std::string ca_path
,
1229 unsigned int dtls_timeout
,
1230 unsigned int dtls_ntimeouts
) {
1231 int dtls_dispatcher_socket
;
1232 my_ip46_address server_addr
, client_addr
;
1237 debug_print(("Starting dtls server on "s
+ dtls_local_address
+ ":" +
1238 std::to_string(port
))
1240 const int on
= 1, off
= 0;
1242 std::memset(&server_addr
, 0, sizeof(struct sockaddr_storage
));
1243 if (std::strlen(dtls_local_address
) == 0) {
1244 server_addr
.s6
.sin6_family
= AF_INET6
;
1245 #ifdef HAVE_SIN6_LEN
1246 server_addr
.s6
.sin6_len
= sizeof(struct sockaddr_in6
);
1248 server_addr
.s6
.sin6_addr
= in6addr_any
;
1249 server_addr
.s6
.sin6_port
= htons(port
);
1252 my_ip46_address_init(server_addr
, dtls_local_address
, port
);
1259 OpenSSL_add_ssl_algorithms();
1260 SSL_load_error_strings();
1261 ctx
= SSL_CTX_new(DTLS_server_method());
1262 /* We accept all ciphers, including NULL.
1263 * Not recommended beyond testing and debugging
1265 SSL_CTX_set_security_level(ctx
, 0);
1266 SSL_CTX_set_cipher_list(ctx
, "CHACHA20");
1267 SSL_CTX_set_session_cache_mode(ctx
, SSL_SESS_CACHE_OFF
);
1269 if (SSL_CTX_load_verify_locations(ctx
, ca_path
.c_str(), "certs") == 0)
1270 throw std::logic_error("CA directory or file not found.");
1272 if (!SSL_CTX_use_certificate_file(
1273 ctx
, cert_path
.c_str(), SSL_FILETYPE_PEM
))
1274 printf("\nERROR: no certificate found!");
1276 if (!SSL_CTX_use_PrivateKey_file(
1277 ctx
, key_path
.c_str(), SSL_FILETYPE_PEM
))
1278 printf("\nERROR: no private key found!");
1280 if (!SSL_CTX_check_private_key(ctx
))
1281 printf("\nERROR: invalid private key!");
1283 /* Client has to authenticate */
1285 ctx
, SSL_VERIFY_PEER
| SSL_VERIFY_FAIL_IF_NO_PEER_CERT
, NULL
);
1286 // dtls_verify_callback);
1288 SSL_CTX_set_read_ahead(ctx
, 1);
1289 SSL_CTX_set_cookie_generate_cb(ctx
, generate_cookie
);
1290 SSL_CTX_set_cookie_verify_cb(ctx
, &verify_cookie
);
1292 dtls_dispatcher_socket
= socket(server_addr
.ss
.ss_family
, SOCK_DGRAM
, 0);
1293 if (dtls_dispatcher_socket
< 0) {
1294 perror("dtls_dispatch_socket");
1297 #if defined(__OpenBSD__)
1300 int size
= 20000000;
1303 setsockopt(udp_socket
, SOL_SOCKET
, SO_SNDBUF
, &size
, sizeof(size
)))
1304 throw std::logic_error("cannot set UDP SO_SNDBUF");
1306 setsockopt(udp_socket
, SOL_SOCKET
, SO_RCVBUF
, &size
, sizeof(size
)))
1307 throw std::logic_error("cannot set UDP SO_RCVBUF");
1310 setsockopt(dtls_dispatcher_socket
,
1314 (socklen_t
)sizeof(on
));
1316 setsockopt(dtls_dispatcher_socket
,
1320 (socklen_t
)sizeof(on
));
1321 #if defined(SO_REUSEPORT) && !defined(__linux__)
1322 setsockopt(dtls_dispatcher_socket
,
1326 (socklen_t
)sizeof(on
));
1329 my_ip46_bind(dtls_dispatcher_socket
, server_addr
);
1332 debug_print("=============================================");
1334 std::memset(&client_addr
, 0, sizeof(struct sockaddr_storage
));
1337 bio
= BIO_new_dgram(dtls_dispatcher_socket
, BIO_NOCLOSE
);
1339 /* Set and activate timeouts */
1340 struct timeval timeout
;
1341 timeout
.tv_sec
= dtls_timeout
;
1342 timeout
.tv_usec
= 0;
1343 BIO_ctrl(bio
, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT
, 0, &timeout
);
1344 BIO_set_buffer_size(bio
, 2000000);
1345 BIO_set_read_buffer_size(bio
, 2000000);
1348 SSL_set_bio(ssl
, bio
, bio
);
1349 SSL_set_options(ssl
, SSL_OP_COOKIE_EXCHANGE
);
1351 while (DTLSv1_listen(ssl
, (BIO_ADDR
*)&client_addr
) <= 0)
1353 pass_info_t
* dtls_info
;
1355 reinterpret_cast<pass_info_t
*>(malloc(sizeof(pass_info_t
)));
1356 std::memcpy(&dtls_info
->server_addr
,
1358 sizeof(struct sockaddr_storage
));
1359 std::memcpy(&dtls_info
->client_addr
,
1361 sizeof(struct sockaddr_storage
));
1362 dtls_info
->ssl
= ssl
;
1363 dtls_info
->socket_reverse_forward
= udp_socket
;
1364 dtls_info
->udp_ip_and_port
= forward_address
;
1365 dtls_info
->allow_udp_ip_port_from_inbound
=
1366 allow_update_forward_address
;
1367 dtls_info
->timeout_sec
= dtls_timeout
;
1368 dtls_info
->ntimeouts
= dtls_ntimeouts
;
1371 thread_server_handle_dtls_connection
, dtls_info
, &tid
);
1376 void start_client_dtls(char const * remote_address
,
1377 char const * local_address
,
1379 int client_udp_socket
,
1380 my_ip46_address forward_address
,
1381 bool allow_update_forward_address
,
1382 std::string cert_path
,
1383 std::string key_path
,
1384 std::string ca_path
,
1385 unsigned int dtls_timeout
,
1386 unsigned int dtls_ntimeouts
) {
1387 int client_dtls_socket
;
1388 int ssl_connect_retval
;
1389 void * pthread_join_retval
= nullptr;
1390 my_ip46_address remote_addr
;
1391 my_ip46_address local_addr
;
1392 // I will have to somehow prepare a this buffer for writing,
1393 // so that it contains a header with my protocol's metadata.
1394 // The metadata is probably simple:
1396 // bool my_message_or_not_mine;
1398 // float keepalive timeout;
1400 // or something like that.
1401 // char message_buf[BUFFER_SIZE];
1402 // but at the moment I have no header, I just reconnect.
1403 char addrbuf
[INET6_ADDRSTRLEN
];
1410 std::memset((void *)&remote_addr
, 0, sizeof(struct sockaddr_storage
));
1411 std::memset((void *)&local_addr
, 0, sizeof(struct sockaddr_storage
));
1414 my_ip46_address_init(remote_addr
, remote_address
, port
);
1419 client_dtls_socket
= socket(remote_addr
.ss
.ss_family
, SOCK_DGRAM
, 0);
1420 if (client_dtls_socket
< 0) {
1421 perror("client socket");
1424 auto mySocketGuard
=
1425 std::unique_ptr
<int, void (*)(int *)>(&client_dtls_socket
, closer
);
1427 if (strlen(local_address
) > 0) {
1428 debug_print("DTLS:Before local bind. ");
1430 my_ip46_address_init(local_addr
, local_address
, port
);
1435 OPENSSL_assert(remote_addr
.ss
.ss_family
== local_addr
.ss
.ss_family
);
1436 my_ip46_bind(client_dtls_socket
, local_addr
); // throws
1437 debug_print("DTLS:Local bind succeeded.");
1440 OpenSSL_add_ssl_algorithms();
1441 SSL_load_error_strings();
1442 ctx
= SSL_CTX_new(DTLS_client_method());
1443 // SSL_CTX_set_cipher_list(ctx, "eNULL:!MD5");
1444 SSL_CTX_set_security_level(ctx
, 0);
1445 SSL_CTX_set_cipher_list(ctx
, "CHACHA20");
1446 if (SSL_CTX_load_verify_locations(ctx
, ca_path
.c_str(), "certs") == 0)
1447 throw std::logic_error("CA directory not found.");
1449 if (!SSL_CTX_use_certificate_file(
1450 ctx
, cert_path
.c_str(), SSL_FILETYPE_PEM
))
1451 printf("\nERROR: no certificate found!");
1453 if (!SSL_CTX_use_PrivateKey_file(
1454 ctx
, key_path
.c_str(), SSL_FILETYPE_PEM
))
1455 printf("\nERROR: no private key found!");
1457 if (!SSL_CTX_check_private_key(ctx
))
1458 printf("\nERROR: invalid private key!");
1460 // client also verifies server
1462 ctx
, SSL_VERIFY_PEER
| SSL_VERIFY_FAIL_IF_NO_PEER_CERT
, NULL
);
1464 SSL_CTX_set_verify_depth(ctx
, 2);
1465 SSL_CTX_set_read_ahead(ctx
, 1);
1468 std::unique_ptr
<SSL
, void (*)(SSL
*)> ssl_guard(ssl
, SSL_free
);
1470 /* Create BIO, connect and set to already connected */
1471 bio
= BIO_new_dgram(client_dtls_socket
, BIO_CLOSE
);
1472 debug_print("DTLS: before connect.");
1474 my_ip46_connect(client_dtls_socket
, remote_addr
);
1475 } catch (std::runtime_error
& ex
) {
1476 debug_print(("Exception:dtls connect failed: "s
+ ex
.what() +
1477 "ending this attempt.")
1481 debug_print("Unknown exception. Dying.");
1483 debug_print("DTLS: connect succeeded.");
1485 BIO_ctrl(bio
, BIO_CTRL_DGRAM_SET_CONNECTED
, 0, &remote_addr
.ss
);
1487 SSL_set_bio(ssl
, bio
, bio
);
1488 debug_print("DTLS: before SSL_connect.");
1489 // Set and activate timeouts
1492 struct timeval timeout
;
1493 timeout
.tv_sec
= dtls_timeout
;
1494 timeout
.tv_usec
= 0;
1495 BIO_ctrl(bio
, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT
, 0, &timeout
);
1496 BIO_set_buffer_size(bio
, 2000000);
1497 BIO_set_read_buffer_size(bio
, 2000000);
1499 ssl_connect_retval
=
1500 SSL_connect(ssl
); // TODO: for some reason this doesn't timeout when I
1502 debug_print("DTLS: after SSL_connect.");
1503 if (ssl_connect_retval
<= 0) {
1504 switch (SSL_get_error(ssl
, ssl_connect_retval
)) {
1505 case SSL_ERROR_ZERO_RETURN
:
1506 fprintf(stderr
, "SSL_connect failed with SSL_ERROR_ZERO_RETURN\n");
1508 case SSL_ERROR_WANT_READ
:
1509 fprintf(stderr
, "SSL_connect failed with SSL_ERROR_WANT_READ\n");
1511 case SSL_ERROR_WANT_WRITE
:
1512 fprintf(stderr
, "SSL_connect failed with SSL_ERROR_WANT_WRITE\n");
1514 case SSL_ERROR_WANT_CONNECT
:
1515 fprintf(stderr
, "SSL_connect failed with SSL_ERROR_WANT_CONNECT\n");
1517 case SSL_ERROR_WANT_ACCEPT
:
1518 fprintf(stderr
, "SSL_connect failed with SSL_ERROR_WANT_ACCEPT\n");
1520 case SSL_ERROR_WANT_X509_LOOKUP
:
1522 "SSL_connect failed with SSL_ERROR_WANT_X509_LOOKUP\n");
1524 case SSL_ERROR_SYSCALL
:
1525 debug_print("SSL_connect failed with SSL_ERROR_SYSCALL\n");
1526 debug_print("TODO: process this syscall error.");
1530 fprintf(stderr
, "SSL_connect failed with SSL_ERROR_SSL\n");
1533 fprintf(stderr
, "SSL_connect failed with unknown error\n");
1536 // goto cleanup_client;
1537 // exit(EXIT_FAILURE);
1538 debug_print("sleeping 5 seconds");
1540 debug_print("SSL_connect failed, terminating attempt.");
1545 if (remote_addr
.ss
.ss_family
== AF_INET
) {
1547 "\nConnected to %s\n",
1549 AF_INET
, &remote_addr
.s4
.sin_addr
, addrbuf
, INET6_ADDRSTRLEN
));
1552 "\nConnected to %s\n",
1554 AF_INET6
, &remote_addr
.s6
.sin6_addr
, addrbuf
, INET6_ADDRSTRLEN
));
1558 if (veryverbose
&& SSL_get_peer_certificate(ssl
)) {
1560 "------------------------------------------------------------\n");
1561 X509_NAME_print_ex_fp(
1563 X509_get_subject_name(SSL_get_peer_certificate(ssl
)),
1566 printf("\n\n Cipher: %s",
1567 SSL_CIPHER_get_name(SSL_get_current_cipher(ssl
)));
1568 printf("\n------------------------------------------------------------"
1571 // Okay, here we seem to have obtained all the stuff for reading and
1572 // writing to/from the socket.
1573 // So this while loop should be going on in the two threads.
1575 pass_info_t dtls_info
;
1577 &dtls_info
.server_addr
, &remote_addr
, sizeof(struct sockaddr_storage
));
1579 &dtls_info
.client_addr
, &local_addr
, sizeof(struct sockaddr_storage
));
1580 dtls_info
.ssl
= ssl
;
1581 dtls_info
.socket_reverse_forward
= client_udp_socket
;
1582 dtls_info
.udp_ip_and_port
= forward_address
;
1583 dtls_info
.allow_udp_ip_port_from_inbound
= allow_update_forward_address
;
1584 dtls_info
.timeout_sec
= dtls_timeout
;
1585 dtls_info
.ntimeouts
= dtls_ntimeouts
;
1587 debug_print("before two threads");
1588 my_tid_t tid_client_dtls_to_udp
;
1589 my_tid_t tid_client_udp_to_dtls
;
1591 thread_dtls_to_udp
, &dtls_info
, &tid_client_dtls_to_udp
);
1592 debug_print("created reading thread");
1594 thread_udp_to_dtls
, &dtls_info
, &tid_client_udp_to_dtls
);
1595 debug_print("created writing thread");
1596 pthread_join(tid_client_dtls_to_udp
, &pthread_join_retval
);
1597 debug_print("joined client_dtls_to_udp thread");
1599 pthread_join(tid_client_udp_to_dtls
, &pthread_join_retval
);
1600 debug_print("joined client_udp_to_dtls thread");
1603 int main(int argc
, char ** argv
) {
1604 if (EAGAIN
!= EWOULDBLOCK
)
1605 throw std::logic_error("EAGAIN != EWOULDBLOCK, which is an error.");
1607 // char local_addr[INET6_ADDRSTRLEN+1];
1608 // std::memset(local_addr, 0, INET6_ADDRSTRLEN+1);
1610 popl::OptionParser
op("Allowed options");
1612 op
.add
<popl::Switch
>("h", "help", "produce help message");
1613 auto groff_option
= op
.add
<popl::Switch
>(
1614 "", "groff", "produce groff formatted help message");
1616 op
.add
<popl::Switch
>("", "bash", "produce bash completion script");
1617 auto verbose_option
= op
.add
<popl::Switch
, popl::Attribute::optional
>(
1618 "v", "verbose", "be verbose", &arg_verbose
);
1619 auto dtls_local_address_option
= op
.add
<popl::Implicit
<std::string
>>(
1622 "local dtls address ",
1623 std::string('\0', INET6_ADDRSTRLEN
+ 1));
1625 auto remote_address_option
= op
.add
<popl::Value
<std::string
>>(
1626 "R", "remote-address", "remote dtls address");
1627 auto dtls_port_option
=
1628 op
.add
<popl::Implicit
<int>>("p",
1630 "port (default 23232) (TODO: remove or "
1631 "rename. only for compatibility)",
1634 auto server_or_client_option
=
1635 op
.add
<popl::Value
<std::string
>>("", "mode", "server or client");
1637 auto udp_forward_address_option
= op
.add
<popl::Implicit
<std::string
>>(
1640 "forward address for udp socket. Default means that value will be "
1641 "taken from the last client.",
1644 auto udp_local_address_option
= op
.add
<popl::Implicit
<std::string
>>(
1645 "", "udp-local-address", "local bind address for udp socket.", ""s
);
1647 auto udp_forward_port_option
= op
.add
<popl::Implicit
<unsigned short>>(
1650 "UDP packets received over dtls will be forwarded to this address. "
1651 "Default is 0, which means 'get from the last client'",
1654 auto udp_local_port_option
= op
.add
<popl::Implicit
<unsigned short>>(
1657 "UDP packets sent to this port will be forwarded to the dtls",
1660 auto udp_get_addr_from_inbound_packets_option
=
1661 op
.add
<popl::Implicit
<bool>>(
1663 "udp-get-addr-from-inbound-packets",
1664 "UDP target address-port will be updated from incoming packets. "
1665 "Setting this option to false disables auto-update of address and "
1669 auto dtls_public_cert_path_option
= op
.add
<popl::Value
<std::string
>>(
1670 "", "dtls-public-cert-path", "path to a public cert file");
1672 auto dtls_private_key_path_option
= op
.add
<popl::Value
<std::string
>>(
1673 "", "dtls-private-key-path", "path to a private key file");
1675 auto dtls_ca_path_option
= op
.add
<popl::Value
<std::string
>>(
1676 "", "dtls-ca-cert-path", "path to a CA file");
1678 auto dtls_timeout_option
= op
.add
<popl::Implicit
<unsigned int>>(
1681 "How long to wait before timing out. Too short, and your tunnel will "
1682 "not connect on a lossy channel. Too long, and switching between IPs "
1683 "will be a pain. Recommended value 5-10, but you have to experiment.",
1686 auto dtls_ntimeouts_option
= op
.add
<popl::Implicit
<unsigned int>>(
1687 "", "dtls-ntimeouts", "break connection after this many timeouts", 3);
1690 op
.parse(argc
, argv
);
1691 if (help_option
->count() == 1) {
1692 std::cout
<< op
<< "\n";
1696 if (groff_option
->is_set()) {
1697 popl::GroffOptionPrinter
option_printer(&op
);
1698 std::cout
<< option_printer
.print();
1702 if (bash_option
->is_set()) {
1703 popl::BashCompletionOptionPrinter
option_printer(&op
,
1705 std::cout
<< option_printer
.print();
1708 if (!(server_or_client_option
->is_set())) {
1709 std::cerr
<< "--mode= option must be server or client" << std::endl
;
1713 if (verbose_option
->is_set()) {
1717 } catch (const popl::invalid_option
& e
) {
1718 std::cerr
<< "Invalid Option Exception: " << e
.what() << "\n";
1719 std::cerr
<< "error: ";
1720 if (e
.error() == popl::invalid_option::Error::missing_argument
)
1721 std::cerr
<< "missing_argument\n";
1722 else if (e
.error() == popl::invalid_option::Error::invalid_argument
)
1723 std::cerr
<< "invalid_argument\n";
1724 else if (e
.error() == popl::invalid_option::Error::too_many_arguments
)
1725 std::cerr
<< "too_many_arguments\n";
1726 else if (e
.error() == popl::invalid_option::Error::missing_option
)
1727 std::cerr
<< "missing_option\n";
1729 if (e
.error() == popl::invalid_option::Error::missing_option
) {
1730 std::string
option_name(
1731 e
.option()->name(popl::OptionName::short_name
, true));
1732 if (option_name
.empty())
1733 option_name
= e
.option()->name(popl::OptionName::long_name
, true);
1734 std::cerr
<< "option: " << option_name
<< "\n";
1736 std::cerr
<< "option: " << e
.option()->name(e
.what_name()) << "\n";
1737 std::cerr
<< "value: " << e
.value() << "\n";
1739 std::cout
<< op
<< "\n";
1740 return EXIT_FAILURE
;
1741 } catch (const std::exception
& e
) {
1742 std::cerr
<< "Exception: " << e
.what() << "\n";
1743 return EXIT_FAILURE
;
1746 if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER
) {
1747 printf("Warning: OpenSSL version mismatch!\n");
1748 printf("Compiled against %s\n", OPENSSL_VERSION_TEXT
);
1749 printf("Linked against %s\n", OpenSSL_version(OPENSSL_VERSION
));
1751 if (OpenSSL_version_num() >> 20 != OPENSSL_VERSION_NUMBER
>> 20) {
1753 "Error: Major and minor version numbers must match, exiting.\n");
1756 } else if (verbose
) {
1757 printf("Using %s\n", OpenSSL_version(OPENSSL_VERSION
));
1760 if (OPENSSL_VERSION_NUMBER
< 0x1010102fL
) {
1762 "Error: %s is unsupported, use OpenSSL Version 1.1.1a or higher\n",
1763 OpenSSL_version(OPENSSL_VERSION
));
1770 WSAStartup(MAKEWORD(2, 2), &wsaData
);
1773 auto [udp_socket
, forward_addr
] = setup_udp_socket
1774 /**/ (udp_forward_address_option
->value().c_str(),
1775 udp_forward_port_option
->value(),
1776 udp_local_address_option
->value(),
1777 udp_local_port_option
->value());
1779 debug_print(("udp_socket="s
+ std::to_string(udp_socket
)).c_str());
1781 if (server_or_client_option
->value() == "client") {
1784 "=======================================================");
1785 start_client_dtls(remote_address_option
->value().c_str(),
1786 dtls_local_address_option
->value().c_str(),
1787 dtls_port_option
->value(),
1790 udp_get_addr_from_inbound_packets_option
->value(),
1791 dtls_public_cert_path_option
->value(),
1792 dtls_private_key_path_option
->value(),
1793 dtls_ca_path_option
->value(),
1794 dtls_timeout_option
->value(),
1795 dtls_ntimeouts_option
->value());
1796 debug_print("Client dtls connection died. Sleeping and restarting.");
1797 fprintf(stderr
, "\n\n");
1801 } else if (server_or_client_option
->value() == "server") {
1802 start_server_dtls(dtls_port_option
->value(),
1803 dtls_local_address_option
->value().c_str(),
1806 udp_get_addr_from_inbound_packets_option
->value(),
1807 dtls_public_cert_path_option
->value(),
1808 dtls_private_key_path_option
->value(),
1809 dtls_ca_path_option
->value(),
1810 dtls_timeout_option
->value(),
1811 dtls_ntimeouts_option
->value());