Skip to content

Commit

Permalink
MT#55283 switch to BIO_set_callback_arg
Browse files Browse the repository at this point in the history
Use a BIO WRITE callback instead of BIO_read'ing from the BIO after each
operation. This is a more direct way to intercept data that needs to be
sent out.

Implement MTU-related BIO callbacks.

Deduct the assumed IP MTU overhead from the configured MTU during
startup.

Unlike the previous code, this does not necessarily send DTLS from the
same socket that received a message, nor to the same address that sent
one, and instead always uses the selected_sfd and ->endpoint. This may
or may not be a regression.

Closes #1806

Change-Id: I4d4456df3f378d00782cbfa64afdb2a038217e6c
(cherry picked from commit 0833216)
  • Loading branch information
rfuchs committed Oct 1, 2024
1 parent 442884c commit dd7e56d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 37 deletions.
90 changes: 53 additions & 37 deletions daemon/dtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,51 @@ static int try_connect(struct dtls_connection *d) {
return ret;
}

static long dtls_bio_callback(BIO *bio, int oper, const char *argp, size_t len, int argi, long argl,
int ret, size_t *proc)
{
if (oper == (BIO_CB_CTRL | BIO_CB_RETURN)) {
if (argi == BIO_CTRL_DGRAM_QUERY_MTU)
return rtpe_config.dtls_mtu; // this is with overhead already subtracted
if (argi == BIO_CTRL_DGRAM_GET_MTU_OVERHEAD)
return DTLS_MTU_OVERHEAD;
return ret;
}

if (oper != BIO_CB_WRITE)
return ret;
if (!argp || len <= 0)
return ret;

struct packet_stream *ps = (struct packet_stream *) BIO_get_callback_arg(bio);
if (!ps)
return ret;
struct stream_fd *sfd = ps->selected_sfd;
if (!sfd)
return ret;
struct dtls_connection *d = dtls_ptr(sfd);
if (!d)
return ret;

__DBG("dtls packet output: len %zu %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
len,
argp[0], argp[1], argp[2], argp[3],
argp[4], argp[5], argp[6], argp[7],
argp[8], argp[9], argp[10], argp[11],
argp[12], argp[13], argp[14], argp[15]);

const endpoint_t *fsin = &ps->endpoint;
if (fsin->port == 9 || fsin->address.family == NULL)
return ret;

ilogs(srtp, LOG_DEBUG, "Sending DTLS packet");
socket_sendto(&sfd->socket, argp, len, fsin);
atomic64_inc_na(&ps->stats_out->packets);
atomic64_add_na(&ps->stats_out->bytes, len);

return ret;
}

int dtls_connection_init(struct dtls_connection *d, struct packet_stream *ps, int active,
struct dtls_cert *cert)
{
Expand Down Expand Up @@ -656,6 +701,14 @@ int dtls_connection_init(struct dtls_connection *d, struct packet_stream *ps, in
if (!d->r_bio || !d->w_bio)
goto error;

BIO_set_callback_ex(d->w_bio, dtls_bio_callback);
BIO_set_callback_arg(d->w_bio, (char *) ps);

#if defined(BIO_CTRL_DGRAM_SET_MTU)
BIO_ctrl(d->w_bio, BIO_CTRL_DGRAM_SET_MTU, rtpe_config.dtls_mtu, NULL);
BIO_ctrl(d->r_bio, BIO_CTRL_DGRAM_SET_MTU, rtpe_config.dtls_mtu, NULL);
#endif

SSL_set_app_data(d->ssl, d);
SSL_set_bio(d->ssl, d->r_bio, d->w_bio);
d->init = 1;
Expand Down Expand Up @@ -792,7 +845,6 @@ static int dtls_setup_crypto(struct packet_stream *ps, struct dtls_connection *d
int dtls(stream_fd *sfd, const str *s, const endpoint_t *fsin) {
struct packet_stream *ps = sfd->stream;
int ret;
unsigned char buf[0x10000];

if (!ps)
return 0;
Expand Down Expand Up @@ -856,42 +908,6 @@ int dtls(stream_fd *sfd, const str *s, const endpoint_t *fsin) {
}
}

while (1) {
ret = BIO_ctrl_pending(d->w_bio);
if (ret <= 0)
break;

if (ret > sizeof(buf)) {
ilogs(srtp, LOG_ERROR, "BIO buffer overflow");
(void) BIO_reset(d->w_bio);
break;
}

ret = BIO_read(d->w_bio, buf, ret);
if (ret <= 0)
break;

__DBG("dtls packet output: len %u %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
ret,
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7],
buf[8], buf[9], buf[10], buf[11],
buf[12], buf[13], buf[14], buf[15]);

if (!fsin) {
fsin = &ps->endpoint;
if (fsin->port == 9 || fsin->address.family == NULL)
fsin = NULL;
}

if (fsin) {
ilogs(srtp, LOG_DEBUG, "Sending DTLS packet");
socket_sendto(&sfd->socket, buf, ret, fsin);
atomic64_inc_na(&ps->stats_out->packets);
atomic64_add_na(&ps->stats_out->bytes, ret);
}
}

return dret;
}

Expand Down
2 changes: 2 additions & 0 deletions daemon/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,8 @@ static void options(int *argc, char ***argv) {
However, this does not preclude link layers with an MTU smaller than this minimum MTU from conveying IP data. Internet IPv4 path MTU is 68 bytes.*/
die("Invalid --dtls-mtu (%i)", rtpe_config.dtls_mtu);

rtpe_config.dtls_mtu -= DTLS_MTU_OVERHEAD;

if (rtpe_config.jb_length < 0)
die("Invalid negative jitter buffer size");

Expand Down
1 change: 1 addition & 0 deletions include/dtls.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "types.h"

#define DTLS_MAX_DIGEST_LEN 64
#define DTLS_MTU_OVERHEAD 48 // 40 bytes IPv6 + 8 bytes UDP

struct packet_stream;
struct sockaddr_in6;
Expand Down

0 comments on commit dd7e56d

Please sign in to comment.