Coverage Report

Created: 2023-06-08 06:41

/src/openssl/crypto/bio/bss_dgram_pair.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include <errno.h>
12
#include "bio_local.h"
13
#include "internal/cryptlib.h"
14
#include "internal/safe_math.h"
15
16
#if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
17
18
OSSL_SAFE_MATH_UNSIGNED(size_t, size_t)
19
20
/* ===========================================================================
21
 * Byte-wise ring buffer which supports pushing and popping blocks of multiple
22
 * bytes at a time.
23
 */
24
struct ring_buf {
25
    unsigned char *start; /* start of buffer */
26
    size_t len; /* size of buffer allocation in bytes */
27
    size_t count; /* number of bytes currently pushed */
28
    /*
29
     * These index into start. Where idx[0] == idx[1], the buffer is full
30
     * (if count is nonzero) and empty otherwise.
31
     */
32
    size_t idx[2]; /* 0: head, 1: tail */
33
};
34
35
static int ring_buf_init(struct ring_buf *r, size_t nbytes)
36
0
{
37
0
    r->start = OPENSSL_malloc(nbytes);
38
0
    if (r->start == NULL)
39
0
        return 0;
40
41
0
    r->len = nbytes;
42
0
    r->idx[0] = r->idx[1] = r->count = 0;
43
0
    return 1;
44
0
}
45
46
static void ring_buf_destroy(struct ring_buf *r)
47
0
{
48
0
    OPENSSL_free(r->start);
49
0
    r->start    = NULL;
50
0
    r->len      = 0;
51
0
    r->count    = 0;
52
0
}
53
54
/*
55
 * Get a pointer to the next place to write data to be pushed to the ring buffer
56
 * (idx=0), or the next data to be popped from the ring buffer (idx=1). The
57
 * pointer is written to *buf and the maximum number of bytes which can be
58
 * read/written are written to *len. After writing data to the buffer, call
59
 * ring_buf_push/pop() with the number of bytes actually read/written, which
60
 * must not exceed the returned length.
61
 */
62
static void ring_buf_head_tail(struct ring_buf *r, int idx, uint8_t **buf, size_t *len)
63
0
{
64
0
    size_t max_len = r->len - r->idx[idx];
65
66
0
    if (idx == 0 && max_len > r->len - r->count)
67
0
        max_len = r->len - r->count;
68
0
    if (idx == 1 && max_len > r->count)
69
0
        max_len = r->count;
70
71
0
    *buf = (uint8_t *)r->start + r->idx[idx];
72
0
    *len = max_len;
73
0
}
74
75
0
#define ring_buf_head(r, buf, len) ring_buf_head_tail((r), 0, (buf), (len))
76
0
#define ring_buf_tail(r, buf, len) ring_buf_head_tail((r), 1, (buf), (len))
77
78
/*
79
 * Commit bytes to the ring buffer previously filled after a call to
80
 * ring_buf_head().
81
 */
82
static void ring_buf_push_pop(struct ring_buf *r, int idx, size_t num_bytes)
83
0
{
84
0
    size_t new_idx;
85
86
    /* A single push/pop op cannot wrap around, though it can reach the end.
87
     * If the caller adheres to the convention of using the length returned
88
     * by ring_buf_head/tail(), this cannot happen.
89
     */
90
0
    if (!ossl_assert(num_bytes <= r->len - r->idx[idx]))
91
0
        return;
92
93
    /*
94
     * Must not overfill the buffer, or pop more than is in the buffer either.
95
     */
96
0
    if (!ossl_assert(idx != 0 ? num_bytes <= r->count
97
0
                              : num_bytes + r->count <= r->len))
98
0
        return;
99
100
    /* Update the index. */
101
0
    new_idx = r->idx[idx] + num_bytes;
102
0
    if (new_idx == r->len)
103
0
        new_idx = 0;
104
105
0
    r->idx[idx] = new_idx;
106
0
    if (idx != 0)
107
0
        r->count -= num_bytes;
108
0
    else
109
0
        r->count += num_bytes;
110
0
}
111
112
0
#define ring_buf_push(r, num_bytes) ring_buf_push_pop((r), 0, (num_bytes))
113
0
#define ring_buf_pop(r, num_bytes) ring_buf_push_pop((r), 1, (num_bytes))
114
115
static void ring_buf_clear(struct ring_buf *r)
116
0
{
117
0
    r->idx[0] = r->idx[1] = r->count = 0;
118
0
}
119
120
static int ring_buf_resize(struct ring_buf *r, size_t nbytes)
121
0
{
122
0
    unsigned char *new_start;
123
124
0
    if (r->start == NULL)
125
0
        return ring_buf_init(r, nbytes);
126
127
0
    if (nbytes == r->len)
128
0
        return 1;
129
130
0
    if (r->count > 0 && nbytes < r->len)
131
        /* fail shrinking the ring buffer when there is any data in it */
132
0
        return 0;
133
134
0
    new_start = OPENSSL_realloc(r->start, nbytes);
135
0
    if (new_start == NULL)
136
0
        return 0;
137
138
    /* Moving tail if it is after (or equal to) head */
139
0
    if (r->count > 0) {
140
0
        if (r->idx[0] <= r->idx[1]) {
141
0
            size_t offset = nbytes - r->len;
142
143
0
            memmove(new_start + r->idx[1] + offset, new_start + r->idx[1],
144
0
                    r->len - r->idx[1]);
145
0
            r->idx[1] += offset;
146
0
        }
147
0
    } else {
148
        /* just reset the head/tail because it might be pointing outside */
149
0
        r->idx[0] = r->idx[1] = 0;
150
0
    }
151
152
0
    r->start = new_start;
153
0
    r->len = nbytes;
154
155
0
    return 1;
156
0
}
157
158
/* ===========================================================================
159
 * BIO_s_dgram_pair is documented in BIO_s_dgram_pair(3).
160
 *
161
 * INTERNAL DATA STRUCTURE
162
 *
163
 * This is managed internally by using a bytewise ring buffer which supports
164
 * pushing and popping spans of multiple bytes at once. The ring buffer stores
165
 * internal packets which look like this:
166
 *
167
 *   struct dgram_hdr hdr;
168
 *   uint8_t data[];
169
 *
170
 * The header contains the length of the data and metadata such as
171
 * source/destination addresses.
172
 *
173
 * The datagram pair BIO is designed to support both traditional
174
 * BIO_read/BIO_write (likely to be used by applications) as well as
175
 * BIO_recvmmsg/BIO_sendmmsg.
176
 */
177
struct bio_dgram_pair_st;
178
static int dgram_pair_write(BIO *bio, const char *buf, int sz_);
179
static int dgram_pair_read(BIO *bio, char *buf, int sz_);
180
static int dgram_mem_read(BIO *bio, char *buf, int sz_);
181
static long dgram_pair_ctrl(BIO *bio, int cmd, long num, void *ptr);
182
static long dgram_mem_ctrl(BIO *bio, int cmd, long num, void *ptr);
183
static int dgram_pair_init(BIO *bio);
184
static int dgram_mem_init(BIO *bio);
185
static int dgram_pair_free(BIO *bio);
186
static int dgram_pair_sendmmsg(BIO *b, BIO_MSG *msg, size_t stride,
187
                               size_t num_msg, uint64_t flags,
188
                               size_t *num_processed);
189
static int dgram_pair_recvmmsg(BIO *b, BIO_MSG *msg, size_t stride,
190
                               size_t num_msg, uint64_t flags,
191
                               size_t *num_processed);
192
193
static int dgram_pair_ctrl_destroy_bio_pair(BIO *bio1);
194
static size_t dgram_pair_read_inner(struct bio_dgram_pair_st *b, uint8_t *buf,
195
                                    size_t sz);
196
197
0
#define BIO_MSG_N(array, n) (*(BIO_MSG *)((char *)(array) + (n)*stride))
198
199
static const BIO_METHOD dgram_pair_method = {
200
    BIO_TYPE_DGRAM_PAIR,
201
    "BIO dgram pair",
202
    bwrite_conv,
203
    dgram_pair_write,
204
    bread_conv,
205
    dgram_pair_read,
206
    NULL, /* dgram_pair_puts */
207
    NULL, /* dgram_pair_gets */
208
    dgram_pair_ctrl,
209
    dgram_pair_init,
210
    dgram_pair_free,
211
    NULL, /* dgram_pair_callback_ctrl */
212
    dgram_pair_sendmmsg,
213
    dgram_pair_recvmmsg,
214
};
215
216
static const BIO_METHOD dgram_mem_method = {
217
    BIO_TYPE_DGRAM_MEM,
218
    "BIO dgram mem",
219
    bwrite_conv,
220
    dgram_pair_write,
221
    bread_conv,
222
    dgram_mem_read,
223
    NULL, /* dgram_pair_puts */
224
    NULL, /* dgram_pair_gets */
225
    dgram_mem_ctrl,
226
    dgram_mem_init,
227
    dgram_pair_free,
228
    NULL, /* dgram_pair_callback_ctrl */
229
    dgram_pair_sendmmsg,
230
    dgram_pair_recvmmsg,
231
};
232
233
const BIO_METHOD *BIO_s_dgram_pair(void)
234
0
{
235
0
    return &dgram_pair_method;
236
0
}
237
238
const BIO_METHOD *BIO_s_dgram_mem(void)
239
0
{
240
0
    return &dgram_mem_method;
241
0
}
242
243
struct dgram_hdr {
244
    size_t len; /* payload length in bytes, not including this struct */
245
    BIO_ADDR src_addr, dst_addr; /* family == 0: not present */
246
};
247
248
struct bio_dgram_pair_st {
249
    /* The other half of the BIO pair. NULL for dgram_mem. */
250
    BIO *peer;
251
    /* Writes are directed to our own ringbuf and reads to our peer. */
252
    struct ring_buf rbuf;
253
    /* Requested size of rbuf buffer in bytes once we initialize. */
254
    size_t req_buf_len;
255
    /* Largest possible datagram size */
256
    size_t mtu;
257
    /* Capability flags. */
258
    uint32_t cap;
259
    /*
260
     * This lock protects updates to our rbuf. Since writes are directed to our
261
     * own rbuf, this means we use this lock for writes and our peer's lock for
262
     * reads.
263
     */
264
    CRYPTO_RWLOCK *lock;
265
    unsigned int no_trunc          : 1; /* Reads fail if they would truncate */
266
    unsigned int local_addr_enable : 1; /* Can use BIO_MSG->local? */
267
    unsigned int role              : 1; /* Determines lock order */
268
    unsigned int fixed_size        : 1; /* Affects BIO_s_dgram_mem only */
269
};
270
271
0
#define MIN_BUF_LEN (1024)
272
273
0
#define is_dgram_pair(b) (b->peer != NULL)
274
275
static int dgram_pair_init(BIO *bio)
276
0
{
277
0
    struct bio_dgram_pair_st *b = OPENSSL_zalloc(sizeof(*b));
278
279
0
    if (b == NULL)
280
0
        return 0;
281
282
0
    b->req_buf_len = 17*1024; /* default buffer size */
283
0
    b->mtu         = 1472;    /* conservative default MTU */
284
285
0
    b->lock = CRYPTO_THREAD_lock_new();
286
0
    if (b->lock == NULL) {
287
0
        OPENSSL_free(b);
288
0
        return 0;
289
0
    }
290
291
0
    bio->ptr = b;
292
0
    return 1;
293
0
}
294
295
static int dgram_mem_init(BIO *bio)
296
0
{
297
0
    struct bio_dgram_pair_st *b;
298
299
0
    if (!dgram_pair_init(bio))
300
0
        return 0;
301
302
0
    b = bio->ptr;
303
304
0
    if (ring_buf_init(&b->rbuf, b->req_buf_len) == 0) {
305
0
        ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
306
0
        return 0;
307
0
    }
308
309
0
    bio->init = 1;
310
0
    return 1;
311
0
}
312
313
static int dgram_pair_free(BIO *bio)
314
0
{
315
0
    struct bio_dgram_pair_st *b;
316
317
0
    if (bio == NULL)
318
0
        return 0;
319
320
0
    b = bio->ptr;
321
0
    if (!ossl_assert(b != NULL))
322
0
        return 0;
323
324
    /* We are being freed. Disconnect any peer and destroy buffers. */
325
0
    dgram_pair_ctrl_destroy_bio_pair(bio);
326
327
0
    CRYPTO_THREAD_lock_free(b->lock);
328
0
    OPENSSL_free(b);
329
0
    return 1;
330
0
}
331
332
/* BIO_make_bio_pair (BIO_C_MAKE_BIO_PAIR) */
333
static int dgram_pair_ctrl_make_bio_pair(BIO *bio1, BIO *bio2)
334
0
{
335
0
    struct bio_dgram_pair_st *b1, *b2;
336
337
    /* peer must be non-NULL. */
338
0
    if (bio1 == NULL || bio2 == NULL) {
339
0
        ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
340
0
        return 0;
341
0
    }
342
343
    /* Ensure the BIO we have been passed is actually a dgram pair BIO. */
344
0
    if (bio1->method != &dgram_pair_method || bio2->method != &dgram_pair_method) {
345
0
        ERR_raise_data(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT,
346
0
                       "both BIOs must be BIO_dgram_pair");
347
0
        return 0;
348
0
    }
349
350
0
    b1 = bio1->ptr;
351
0
    b2 = bio2->ptr;
352
353
0
    if (!ossl_assert(b1 != NULL && b2 != NULL)) {
354
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
355
0
        return 0;
356
0
    }
357
358
    /*
359
     * This ctrl cannot be used to associate a BIO pair half which is already
360
     * associated.
361
     */
362
0
    if (b1->peer != NULL || b2->peer != NULL) {
363
0
        ERR_raise_data(ERR_LIB_BIO, BIO_R_IN_USE,
364
0
                       "cannot associate a BIO_dgram_pair which is already in use");
365
0
        return 0;
366
0
    }
367
368
0
    if (!ossl_assert(b1->req_buf_len >= MIN_BUF_LEN
369
0
                        && b2->req_buf_len >= MIN_BUF_LEN)) {
370
0
        ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
371
0
        return 0;
372
0
    }
373
374
0
    if (b1->rbuf.len != b1->req_buf_len)
375
0
        if (ring_buf_init(&b1->rbuf, b1->req_buf_len) == 0) {
376
0
            ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
377
0
            return 0;
378
0
        }
379
380
0
    if (b2->rbuf.len != b2->req_buf_len)
381
0
        if (ring_buf_init(&b2->rbuf, b2->req_buf_len) == 0) {
382
0
            ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
383
0
            ring_buf_destroy(&b1->rbuf);
384
0
            return 0;
385
0
        }
386
387
0
    b1->peer    = bio2;
388
0
    b2->peer    = bio1;
389
0
    b1->role    = 0;
390
0
    b2->role    = 1;
391
0
    bio1->init  = 1;
392
0
    bio2->init  = 1;
393
0
    return 1;
394
0
}
395
396
/* BIO_destroy_bio_pair (BIO_C_DESTROY_BIO_PAIR) */
397
static int dgram_pair_ctrl_destroy_bio_pair(BIO *bio1)
398
0
{
399
0
    BIO *bio2;
400
0
    struct bio_dgram_pair_st *b1 = bio1->ptr, *b2;
401
402
0
    ring_buf_destroy(&b1->rbuf);
403
0
    bio1->init = 0;
404
405
    /* Early return if we don't have a peer. */
406
0
    if (b1->peer == NULL)
407
0
        return 1;
408
409
0
    bio2 = b1->peer;
410
0
    b2 = bio2->ptr;
411
412
    /* Invariant. */
413
0
    if (!ossl_assert(b2->peer == bio1))
414
0
        return 0;
415
416
    /* Free buffers. */
417
0
    ring_buf_destroy(&b2->rbuf);
418
419
0
    bio2->init = 0;
420
0
    b1->peer = NULL;
421
0
    b2->peer = NULL;
422
0
    return 1;
423
0
}
424
425
/* BIO_eof (BIO_CTRL_EOF) */
426
static int dgram_pair_ctrl_eof(BIO *bio)
427
0
{
428
0
    struct bio_dgram_pair_st *b = bio->ptr, *peerb;
429
430
0
    if (!ossl_assert(b != NULL))
431
0
        return -1;
432
433
    /* If we aren't initialized, we can never read anything */
434
0
    if (!bio->init)
435
0
        return 1;
436
0
    if (!is_dgram_pair(b))
437
0
        return 0;
438
439
440
0
    peerb = b->peer->ptr;
441
0
    if (!ossl_assert(peerb != NULL))
442
0
        return -1;
443
444
    /*
445
     * Since we are emulating datagram semantics, never indicate EOF so long as
446
     * we have a peer.
447
     */
448
0
    return 0;
449
0
}
450
451
/* BIO_set_write_buf_size (BIO_C_SET_WRITE_BUF_SIZE) */
452
static int dgram_pair_ctrl_set_write_buf_size(BIO *bio, size_t len)
453
0
{
454
0
    struct bio_dgram_pair_st *b = bio->ptr;
455
456
    /* Changing buffer sizes is not permitted while a peer is connected. */
457
0
    if (b->peer != NULL) {
458
0
        ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE);
459
0
        return 0;
460
0
    }
461
462
    /* Enforce minimum size. */
463
0
    if (len < MIN_BUF_LEN)
464
0
        len = MIN_BUF_LEN;
465
466
0
    if (b->rbuf.start != NULL) {
467
0
        if (!ring_buf_resize(&b->rbuf, len))
468
0
            return 0;
469
0
    }
470
471
0
    b->req_buf_len = len;
472
0
    b->fixed_size = 1;
473
0
    return 1;
474
0
}
475
476
/* BIO_reset (BIO_CTRL_RESET) */
477
static int dgram_pair_ctrl_reset(BIO *bio)
478
0
{
479
0
    struct bio_dgram_pair_st *b = bio->ptr;
480
481
0
    ring_buf_clear(&b->rbuf);
482
0
    return 1;
483
0
}
484
485
/* BIO_pending (BIO_CTRL_PENDING) (Threadsafe) */
486
static size_t dgram_pair_ctrl_pending(BIO *bio)
487
0
{
488
0
    size_t saved_idx, saved_count;
489
0
    struct bio_dgram_pair_st *b = bio->ptr, *readb;
490
0
    struct dgram_hdr hdr;
491
0
    size_t l;
492
493
    /* Safe to check; init may not change during this call */
494
0
    if (!bio->init)
495
0
        return 0;
496
0
    if (is_dgram_pair(b))
497
0
        readb = b->peer->ptr;
498
0
    else
499
0
        readb = b;
500
501
0
    if (CRYPTO_THREAD_write_lock(readb->lock) == 0)
502
0
        return 0;
503
504
0
    saved_idx   = readb->rbuf.idx[1];
505
0
    saved_count = readb->rbuf.count;
506
507
0
    l = dgram_pair_read_inner(readb, (uint8_t *)&hdr, sizeof(hdr));
508
509
0
    readb->rbuf.idx[1] = saved_idx;
510
0
    readb->rbuf.count  = saved_count;
511
512
0
    CRYPTO_THREAD_unlock(readb->lock);
513
514
0
    if (!ossl_assert(l == 0 || l == sizeof(hdr)))
515
0
        return 0;
516
517
0
    return l > 0 ? hdr.len : 0;
518
0
}
519
520
/* BIO_get_write_guarantee (BIO_C_GET_WRITE_GUARANTEE) (Threadsafe) */
521
static size_t dgram_pair_ctrl_get_write_guarantee(BIO *bio)
522
0
{
523
0
    size_t l;
524
0
    struct bio_dgram_pair_st *b = bio->ptr;
525
526
0
    if (CRYPTO_THREAD_read_lock(b->lock) == 0)
527
0
        return 0;
528
529
0
    l = b->rbuf.len - b->rbuf.count;
530
0
    if (l >= sizeof(struct dgram_hdr))
531
0
        l -= sizeof(struct dgram_hdr);
532
533
    /*
534
     * If the amount of buffer space would not be enough to accommodate the
535
     * worst-case size of a datagram, report no space available.
536
     */
537
0
    if (l < b->mtu)
538
0
        l = 0;
539
540
0
    CRYPTO_THREAD_unlock(b->lock);
541
0
    return l;
542
0
}
543
544
/* BIO_dgram_get_local_addr_cap (BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP) */
545
static int dgram_pair_ctrl_get_local_addr_cap(BIO *bio)
546
0
{
547
0
    struct bio_dgram_pair_st *b = bio->ptr, *readb;
548
549
0
    if (!bio->init)
550
0
        return 0;
551
552
0
    if (is_dgram_pair(b))
553
0
        readb = b->peer->ptr;
554
0
    else
555
0
        readb = b;
556
557
0
    return (~readb->cap & (BIO_DGRAM_CAP_HANDLES_SRC_ADDR
558
0
                           | BIO_DGRAM_CAP_PROVIDES_DST_ADDR)) == 0;
559
0
}
560
561
/* BIO_dgram_get_effective_caps (BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS) */
562
static int dgram_pair_ctrl_get_effective_caps(BIO *bio)
563
0
{
564
0
    struct bio_dgram_pair_st *b = bio->ptr, *peerb;
565
566
0
    if (b->peer == NULL)
567
0
        return 0;
568
569
0
    peerb = b->peer->ptr;
570
571
0
    return peerb->cap;
572
0
}
573
574
/* BIO_dgram_get_caps (BIO_CTRL_DGRAM_GET_CAPS) */
575
static uint32_t dgram_pair_ctrl_get_caps(BIO *bio)
576
0
{
577
0
    struct bio_dgram_pair_st *b = bio->ptr;
578
579
0
    return b->cap;
580
0
}
581
582
/* BIO_dgram_set_caps (BIO_CTRL_DGRAM_SET_CAPS) */
583
static int dgram_pair_ctrl_set_caps(BIO *bio, uint32_t caps)
584
0
{
585
0
    struct bio_dgram_pair_st *b = bio->ptr;
586
587
0
    b->cap = caps;
588
0
    return 1;
589
0
}
590
591
/* BIO_dgram_get_local_addr_enable (BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE) */
592
static int dgram_pair_ctrl_get_local_addr_enable(BIO *bio)
593
0
{
594
0
    struct bio_dgram_pair_st *b = bio->ptr;
595
596
0
    return b->local_addr_enable;
597
0
}
598
599
/* BIO_dgram_set_local_addr_enable (BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE) */
600
static int dgram_pair_ctrl_set_local_addr_enable(BIO *bio, int enable)
601
0
{
602
0
    struct bio_dgram_pair_st *b = bio->ptr;
603
604
0
    if (dgram_pair_ctrl_get_local_addr_cap(bio) == 0)
605
0
        return 0;
606
607
0
    b->local_addr_enable = (enable != 0 ? 1 : 0);
608
0
    return 1;
609
0
}
610
611
/* BIO_dgram_get_mtu (BIO_CTRL_DGRAM_GET_MTU) */
612
static int dgram_pair_ctrl_get_mtu(BIO *bio)
613
0
{
614
0
    struct bio_dgram_pair_st *b = bio->ptr;
615
616
0
    return b->mtu;
617
0
}
618
619
/* BIO_dgram_set_mtu (BIO_CTRL_DGRAM_SET_MTU) */
620
static int dgram_pair_ctrl_set_mtu(BIO *bio, size_t mtu)
621
0
{
622
0
    struct bio_dgram_pair_st *b = bio->ptr, *peerb;
623
624
0
    b->mtu = mtu;
625
626
0
    if (b->peer != NULL) {
627
0
        peerb = b->peer->ptr;
628
0
        peerb->mtu = mtu;
629
0
    }
630
631
0
    return 1;
632
0
}
633
634
/* Partially threadsafe (some commands) */
635
static long dgram_mem_ctrl(BIO *bio, int cmd, long num, void *ptr)
636
0
{
637
0
    long ret = 1;
638
0
    struct bio_dgram_pair_st *b = bio->ptr;
639
640
0
    if (!ossl_assert(b != NULL))
641
0
        return 0;
642
643
0
    switch (cmd) {
644
    /*
645
     * BIO_set_write_buf_size: Set the size of the ring buffer used for storing
646
     * datagrams. No more writes can be performed once the buffer is filled up,
647
     * until reads are performed. This cannot be used after a peer is connected.
648
     */
649
0
    case BIO_C_SET_WRITE_BUF_SIZE: /* Non-threadsafe */
650
0
        ret = (long)dgram_pair_ctrl_set_write_buf_size(bio, (size_t)num);
651
0
        break;
652
653
    /*
654
     * BIO_get_write_buf_size: Get ring buffer size.
655
     */
656
0
    case BIO_C_GET_WRITE_BUF_SIZE: /* Non-threadsafe */
657
0
        ret = (long)b->req_buf_len;
658
0
        break;
659
660
    /*
661
     * BIO_reset: Clear all data which was written to this side of the pair.
662
     */
663
0
    case BIO_CTRL_RESET: /* Non-threadsafe */
664
0
        dgram_pair_ctrl_reset(bio);
665
0
        break;
666
667
    /*
668
     * BIO_get_write_guarantee: Any BIO_write providing a buffer less than or
669
     * equal to this value is guaranteed to succeed.
670
     */
671
0
    case BIO_C_GET_WRITE_GUARANTEE: /* Threadsafe */
672
0
        ret = (long)dgram_pair_ctrl_get_write_guarantee(bio);
673
0
        break;
674
675
    /* BIO_pending: Bytes available to read. */
676
0
    case BIO_CTRL_PENDING: /* Threadsafe */
677
0
        ret = (long)dgram_pair_ctrl_pending(bio);
678
0
        break;
679
680
    /* BIO_flush: No-op. */
681
0
    case BIO_CTRL_FLUSH: /* Threadsafe */
682
0
        break;
683
684
    /* BIO_dgram_get_no_trunc */
685
0
    case BIO_CTRL_DGRAM_GET_NO_TRUNC: /* Non-threadsafe */
686
0
        ret = (long)b->no_trunc;
687
0
        break;
688
689
    /* BIO_dgram_set_no_trunc */
690
0
    case BIO_CTRL_DGRAM_SET_NO_TRUNC: /* Non-threadsafe */
691
0
        b->no_trunc = (num > 0);
692
0
        break;
693
694
    /* BIO_dgram_get_local_addr_enable */
695
0
    case BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE: /* Non-threadsafe */
696
0
        ret = (long)dgram_pair_ctrl_get_local_addr_enable(bio);
697
0
        break;
698
699
    /* BIO_dgram_set_local_addr_enable */
700
0
    case BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE: /* Non-threadsafe */
701
0
        ret = (long)dgram_pair_ctrl_set_local_addr_enable(bio, num);
702
0
        break;
703
704
    /* BIO_dgram_get_local_addr_cap: Can local addresses be supported? */
705
0
    case BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP: /* Non-threadsafe */
706
0
        ret = (long)dgram_pair_ctrl_get_local_addr_cap(bio);
707
0
        break;
708
709
    /* BIO_dgram_get_effective_caps */
710
0
    case BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS: /* Non-threadsafe */
711
    /* BIO_dgram_get_caps */
712
0
    case BIO_CTRL_DGRAM_GET_CAPS: /* Non-threadsafe */
713
0
        ret = (long)dgram_pair_ctrl_get_caps(bio);
714
0
        break;
715
716
    /* BIO_dgram_set_caps */
717
0
    case BIO_CTRL_DGRAM_SET_CAPS: /* Non-threadsafe */
718
0
        ret = (long)dgram_pair_ctrl_set_caps(bio, (uint32_t)num);
719
0
        break;
720
721
    /* BIO_dgram_get_mtu */
722
0
    case BIO_CTRL_DGRAM_GET_MTU: /* Non-threadsafe */
723
0
        ret = (long)dgram_pair_ctrl_get_mtu(bio);
724
0
        break;
725
726
    /* BIO_dgram_set_mtu */
727
0
    case BIO_CTRL_DGRAM_SET_MTU: /* Non-threadsafe */
728
0
        ret = (long)dgram_pair_ctrl_set_mtu(bio, (uint32_t)num);
729
0
        break;
730
731
    /*
732
     * BIO_eof: Returns whether this half of the BIO pair is empty of data to
733
     * read.
734
     */
735
0
    case BIO_CTRL_EOF: /* Non-threadsafe */
736
0
        ret = (long)dgram_pair_ctrl_eof(bio);
737
0
        break;
738
739
0
    default:
740
0
        ret = 0;
741
0
        break;
742
0
    }
743
744
0
    return ret;
745
0
}
746
747
static long dgram_pair_ctrl(BIO *bio, int cmd, long num, void *ptr)
748
0
{
749
0
    long ret = 1;
750
751
0
    switch (cmd) {
752
    /*
753
     * BIO_make_bio_pair: this is usually used by BIO_new_dgram_pair, though it
754
     * may be used manually after manually creating each half of a BIO pair
755
     * using BIO_new. This only needs to be called on one of the BIOs.
756
     */
757
0
    case BIO_C_MAKE_BIO_PAIR: /* Non-threadsafe */
758
0
        ret = (long)dgram_pair_ctrl_make_bio_pair(bio, (BIO *)ptr);
759
0
        break;
760
761
    /*
762
     * BIO_destroy_bio_pair: Manually disconnect two halves of a BIO pair so
763
     * that they are no longer peers.
764
     */
765
0
    case BIO_C_DESTROY_BIO_PAIR: /* Non-threadsafe */
766
0
        dgram_pair_ctrl_destroy_bio_pair(bio);
767
0
        break;
768
769
    /* BIO_dgram_get_effective_caps */
770
0
    case BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS: /* Non-threadsafe */
771
0
        ret = (long)dgram_pair_ctrl_get_effective_caps(bio);
772
0
        break;
773
774
0
    default:
775
0
        ret = dgram_mem_ctrl(bio, cmd, num, ptr);
776
0
        break;
777
0
    }
778
779
0
    return ret;
780
0
}
781
782
int BIO_new_bio_dgram_pair(BIO **pbio1, size_t writebuf1,
783
                           BIO **pbio2, size_t writebuf2)
784
0
{
785
0
    int ret = 0;
786
0
    long r;
787
0
    BIO *bio1 = NULL, *bio2 = NULL;
788
789
0
    bio1 = BIO_new(BIO_s_dgram_pair());
790
0
    if (bio1 == NULL)
791
0
        goto err;
792
793
0
    bio2 = BIO_new(BIO_s_dgram_pair());
794
0
    if (bio2 == NULL)
795
0
        goto err;
796
797
0
    if (writebuf1 > 0) {
798
0
        r = BIO_set_write_buf_size(bio1, writebuf1);
799
0
        if (r == 0)
800
0
            goto err;
801
0
    }
802
803
0
    if (writebuf2 > 0) {
804
0
        r = BIO_set_write_buf_size(bio2, writebuf2);
805
0
        if (r == 0)
806
0
            goto err;
807
0
    }
808
809
0
    r = BIO_make_bio_pair(bio1, bio2);
810
0
    if (r == 0)
811
0
        goto err;
812
813
0
    ret = 1;
814
0
err:
815
0
    if (ret == 0) {
816
0
        BIO_free(bio1);
817
0
        bio1 = NULL;
818
0
        BIO_free(bio2);
819
0
        bio2 = NULL;
820
0
    }
821
822
0
    *pbio1 = bio1;
823
0
    *pbio2 = bio2;
824
0
    return ret;
825
0
}
826
827
/* Must hold peer write lock */
828
static size_t dgram_pair_read_inner(struct bio_dgram_pair_st *b, uint8_t *buf, size_t sz)
829
0
{
830
0
    size_t total_read = 0;
831
832
    /*
833
     * We repeat pops from the ring buffer for as long as we have more
834
     * application *buffer to fill until we fail. We may not be able to pop
835
     * enough data to fill the buffer in one operation if the ring buffer wraps
836
     * around, but there may still be more data available.
837
     */
838
0
    while (sz > 0) {
839
0
        uint8_t *src_buf = NULL;
840
0
        size_t src_len = 0;
841
842
        /*
843
         * There are two BIO instances, each with a ringbuf. We read from the
844
         * peer ringbuf and write to our own ringbuf.
845
         */
846
0
        ring_buf_tail(&b->rbuf, &src_buf, &src_len);
847
0
        if (src_len == 0)
848
0
            break;
849
850
0
        if (src_len > sz)
851
0
            src_len = sz;
852
853
0
        if (buf != NULL)
854
0
            memcpy(buf, src_buf, src_len);
855
856
0
        ring_buf_pop(&b->rbuf, src_len);
857
858
0
        if (buf != NULL)
859
0
            buf += src_len;
860
0
        total_read  += src_len;
861
0
        sz          -= src_len;
862
0
    }
863
864
0
    return total_read;
865
0
}
866
867
/*
868
 * Must hold peer write lock. Returns number of bytes processed or negated BIO
869
 * response code.
870
 */
871
static ossl_ssize_t dgram_pair_read_actual(BIO *bio, char *buf, size_t sz,
872
                                           BIO_ADDR *local, BIO_ADDR *peer,
873
                                           int is_multi)
874
0
{
875
0
    size_t l, trunc = 0, saved_idx, saved_count;
876
0
    struct bio_dgram_pair_st *b = bio->ptr, *readb;
877
0
    struct dgram_hdr hdr;
878
879
0
    if (!is_multi)
880
0
        BIO_clear_retry_flags(bio);
881
882
0
    if (!bio->init)
883
0
        return -BIO_R_UNINITIALIZED;
884
885
0
    if (!ossl_assert(b != NULL))
886
0
        return -BIO_R_TRANSFER_ERROR;
887
888
0
    if (is_dgram_pair(b))
889
0
        readb = b->peer->ptr;
890
0
    else
891
0
        readb = b;
892
0
    if (!ossl_assert(readb != NULL && readb->rbuf.start != NULL))
893
0
        return -BIO_R_TRANSFER_ERROR;
894
895
0
    if (sz > 0 && buf == NULL)
896
0
        return -BIO_R_INVALID_ARGUMENT;
897
898
    /* If the caller wants to know the local address, it must be enabled */
899
0
    if (local != NULL && b->local_addr_enable == 0)
900
0
        return -BIO_R_LOCAL_ADDR_NOT_AVAILABLE;
901
902
    /* Read the header. */
903
0
    saved_idx   = readb->rbuf.idx[1];
904
0
    saved_count = readb->rbuf.count;
905
0
    l = dgram_pair_read_inner(readb, (uint8_t *)&hdr, sizeof(hdr));
906
0
    if (l == 0) {
907
        /* Buffer was empty. */
908
0
        if (!is_multi)
909
0
            BIO_set_retry_read(bio);
910
0
        return -BIO_R_NON_FATAL;
911
0
    }
912
913
0
    if (!ossl_assert(l == sizeof(hdr)))
914
        /*
915
         * This should not be possible as headers (and their following payloads)
916
         * should always be written atomically.
917
         */
918
0
        return -BIO_R_BROKEN_PIPE;
919
920
0
    if (sz > hdr.len) {
921
0
        sz = hdr.len;
922
0
    } else if (sz < hdr.len) {
923
        /* Truncation is occurring. */
924
0
        trunc = hdr.len - sz;
925
0
        if (b->no_trunc) {
926
            /* Restore original state. */
927
0
            readb->rbuf.idx[1] = saved_idx;
928
0
            readb->rbuf.count  = saved_count;
929
0
            return -BIO_R_NON_FATAL;
930
0
        }
931
0
    }
932
933
0
    l = dgram_pair_read_inner(readb, (uint8_t *)buf, sz);
934
0
    if (!ossl_assert(l == sz))
935
        /* We were somehow not able to read the entire datagram. */
936
0
        return -BIO_R_TRANSFER_ERROR;
937
938
    /*
939
     * If the datagram was truncated due to an inadequate buffer, discard the
940
     * remainder.
941
     */
942
0
    if (trunc > 0 && !ossl_assert(dgram_pair_read_inner(readb, NULL, trunc) == trunc))
943
        /* We were somehow not able to read/skip the entire datagram. */
944
0
        return -BIO_R_TRANSFER_ERROR;
945
946
0
    if (local != NULL)
947
0
        *local = hdr.dst_addr;
948
0
    if (peer != NULL)
949
0
        *peer  = hdr.src_addr;
950
951
0
    return (ossl_ssize_t)l;
952
0
}
953
954
/* Threadsafe */
955
static int dgram_pair_lock_both_write(struct bio_dgram_pair_st *a,
956
                                      struct bio_dgram_pair_st *b)
957
0
{
958
0
    struct bio_dgram_pair_st *x, *y;
959
960
0
    x = (a->role == 1) ? a : b;
961
0
    y = (a->role == 1) ? b : a;
962
963
0
    if (!ossl_assert(a->role != b->role))
964
0
        return 0;
965
966
0
    if (!ossl_assert(a != b && x != y))
967
0
        return 0;
968
969
0
    if (CRYPTO_THREAD_write_lock(x->lock) == 0)
970
0
        return 0;
971
972
0
    if (CRYPTO_THREAD_write_lock(y->lock) == 0) {
973
0
        CRYPTO_THREAD_unlock(x->lock);
974
0
        return 0;
975
0
    }
976
977
0
    return 1;
978
0
}
979
980
static void dgram_pair_unlock_both(struct bio_dgram_pair_st *a,
981
                                   struct bio_dgram_pair_st *b)
982
0
{
983
0
    CRYPTO_THREAD_unlock(a->lock);
984
0
    CRYPTO_THREAD_unlock(b->lock);
985
0
}
986
987
/* Threadsafe */
988
static int dgram_pair_read(BIO *bio, char *buf, int sz_)
989
0
{
990
0
    int ret;
991
0
    ossl_ssize_t l;
992
0
    struct bio_dgram_pair_st *b = bio->ptr, *peerb;
993
994
0
    if (sz_ < 0) {
995
0
        ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
996
0
        return -1;
997
0
    }
998
999
0
    if (b->peer == NULL) {
1000
0
        ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
1001
0
        return -1;
1002
0
    }
1003
1004
0
    peerb = b->peer->ptr;
1005
1006
    /*
1007
     * For BIO_read we have to acquire both locks because we touch the retry
1008
     * flags on the local bio. (This is avoided in the recvmmsg case as it does
1009
     * not touch the retry flags.)
1010
     */
1011
0
    if (dgram_pair_lock_both_write(peerb, b) == 0) {
1012
0
        ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1013
0
        return -1;
1014
0
    }
1015
1016
0
    l = dgram_pair_read_actual(bio, buf, (size_t)sz_, NULL, NULL, 0);
1017
0
    if (l < 0) {
1018
0
        if (l != -BIO_R_NON_FATAL)
1019
0
            ERR_raise(ERR_LIB_BIO, -l);
1020
0
        ret = -1;
1021
0
    } else {
1022
0
        ret = (int)l;
1023
0
    }
1024
1025
0
    dgram_pair_unlock_both(peerb, b);
1026
0
    return ret;
1027
0
}
1028
1029
/* Threadsafe */
1030
static int dgram_pair_recvmmsg(BIO *bio, BIO_MSG *msg,
1031
                               size_t stride, size_t num_msg,
1032
                               uint64_t flags,
1033
                               size_t *num_processed)
1034
0
{
1035
0
    int ret;
1036
0
    ossl_ssize_t l;
1037
0
    BIO_MSG *m;
1038
0
    size_t i;
1039
0
    struct bio_dgram_pair_st *b = bio->ptr, *readb;
1040
1041
0
    if (num_msg == 0) {
1042
0
        *num_processed = 0;
1043
0
        return 1;
1044
0
    }
1045
1046
0
    if (!bio->init) {
1047
0
        ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
1048
0
        *num_processed = 0;
1049
0
        return 0;
1050
0
    }
1051
1052
0
    if (is_dgram_pair(b))
1053
0
        readb = b->peer->ptr;
1054
0
    else
1055
0
        readb = b;
1056
1057
0
    if (CRYPTO_THREAD_write_lock(readb->lock) == 0) {
1058
0
        ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1059
0
        *num_processed = 0;
1060
0
        return 0;
1061
0
    }
1062
1063
0
    for (i = 0; i < num_msg; ++i) {
1064
0
        m = &BIO_MSG_N(msg, i);
1065
0
        l = dgram_pair_read_actual(bio, m->data, m->data_len,
1066
0
                                   m->local, m->peer, 1);
1067
0
        if (l < 0) {
1068
0
            *num_processed = i;
1069
0
            if (i > 0) {
1070
0
                ret = 1;
1071
0
            } else {
1072
0
                ERR_raise(ERR_LIB_BIO, -l);
1073
0
                ret = 0;
1074
0
            }
1075
0
            goto out;
1076
0
        }
1077
1078
0
        m->data_len = l;
1079
0
        m->flags    = 0;
1080
0
    }
1081
1082
0
    *num_processed = i;
1083
0
    ret = 1;
1084
0
out:
1085
0
    CRYPTO_THREAD_unlock(readb->lock);
1086
0
    return ret;
1087
0
}
1088
1089
/* Threadsafe */
1090
static int dgram_mem_read(BIO *bio, char *buf, int sz_)
1091
0
{
1092
0
    int ret;
1093
0
    ossl_ssize_t l;
1094
0
    struct bio_dgram_pair_st *b = bio->ptr;
1095
1096
0
    if (sz_ < 0) {
1097
0
        ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
1098
0
        return -1;
1099
0
    }
1100
1101
0
    if (CRYPTO_THREAD_write_lock(b->lock) == 0) {
1102
0
        ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1103
0
        return -1;
1104
0
    }
1105
1106
0
    l = dgram_pair_read_actual(bio, buf, (size_t)sz_, NULL, NULL, 0);
1107
0
    if (l < 0) {
1108
0
        if (l != -BIO_R_NON_FATAL)
1109
0
            ERR_raise(ERR_LIB_BIO, -l);
1110
0
        ret = -1;
1111
0
    } else {
1112
0
        ret = (int)l;
1113
0
    }
1114
1115
0
    CRYPTO_THREAD_unlock(b->lock);
1116
0
    return ret;
1117
0
}
1118
1119
/*
1120
 * Calculate the array growth based on the target size.
1121
 *
1122
 * The growth factor is a rational number and is defined by a numerator
1123
 * and a denominator.  According to Andrew Koenig in his paper "Why Are
1124
 * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less
1125
 * than the golden ratio (1.618...).
1126
 *
1127
 * We use an expansion factor of 8 / 5 = 1.6
1128
 */
1129
static const size_t max_rbuf_size = SIZE_MAX / 2; /* unlimited in practice */
1130
static ossl_inline size_t compute_rbuf_growth(size_t target, size_t current)
1131
0
{
1132
0
    int err = 0;
1133
1134
0
    while (current < target) {
1135
0
        if (current >= max_rbuf_size)
1136
0
            return 0;
1137
1138
0
        current = safe_muldiv_size_t(current, 8, 5, &err);
1139
0
        if (err)
1140
0
            return 0;
1141
0
        if (current >= max_rbuf_size)
1142
0
            current = max_rbuf_size;
1143
0
    }
1144
0
    return current;
1145
0
}
1146
1147
/* Must hold local write lock */
1148
static size_t dgram_pair_write_inner(struct bio_dgram_pair_st *b, const uint8_t *buf, size_t sz)
1149
0
{
1150
0
    size_t total_written = 0;
1151
1152
    /*
1153
     * We repeat pushes to the ring buffer for as long as we have data until we
1154
     * fail. We may not be able to push in one operation if the ring buffer
1155
     * wraps around, but there may still be more room for data.
1156
     */
1157
0
    while (sz > 0) {
1158
0
        size_t dst_len;
1159
0
        uint8_t *dst_buf;
1160
1161
        /*
1162
         * There are two BIO instances, each with a ringbuf. We write to our own
1163
         * ringbuf and read from the peer ringbuf.
1164
         */
1165
0
        ring_buf_head(&b->rbuf, &dst_buf, &dst_len);
1166
0
        if (dst_len == 0) {
1167
0
            size_t new_len;
1168
1169
0
            if (!b->fixed_size) /* resizeable only unless size not set explicitly */
1170
0
                break;
1171
            /* increase the size */
1172
0
            new_len = compute_rbuf_growth(b->req_buf_len + sz, b->req_buf_len);
1173
0
            if (new_len == 0 || !ring_buf_resize(&b->rbuf, new_len))
1174
0
                break;
1175
0
            b->req_buf_len = new_len;
1176
0
        }
1177
1178
0
        if (dst_len > sz)
1179
0
            dst_len = sz;
1180
1181
0
        memcpy(dst_buf, buf, dst_len);
1182
0
        ring_buf_push(&b->rbuf, dst_len);
1183
1184
0
        buf             += dst_len;
1185
0
        sz              -= dst_len;
1186
0
        total_written   += dst_len;
1187
0
    }
1188
1189
0
    return total_written;
1190
0
}
1191
1192
/*
1193
 * Must hold local write lock. Returns number of bytes processed or negated BIO
1194
 * response code.
1195
 */
1196
static ossl_ssize_t dgram_pair_write_actual(BIO *bio, const char *buf, size_t sz,
1197
                                            const BIO_ADDR *local, const BIO_ADDR *peer,
1198
                                            int is_multi)
1199
0
{
1200
0
    static const BIO_ADDR zero_addr;
1201
0
    size_t saved_idx, saved_count;
1202
0
    struct bio_dgram_pair_st *b = bio->ptr, *readb;
1203
0
    struct dgram_hdr hdr = {0};
1204
1205
0
    if (!is_multi)
1206
0
        BIO_clear_retry_flags(bio);
1207
1208
0
    if (!bio->init)
1209
0
        return -BIO_R_UNINITIALIZED;
1210
1211
0
    if (!ossl_assert(b != NULL && b->rbuf.start != NULL))
1212
0
        return -BIO_R_TRANSFER_ERROR;
1213
1214
0
    if (sz > 0 && buf == NULL)
1215
0
        return -BIO_R_INVALID_ARGUMENT;
1216
1217
0
    if (local != NULL && b->local_addr_enable == 0)
1218
0
        return -BIO_R_LOCAL_ADDR_NOT_AVAILABLE;
1219
1220
0
    if (is_dgram_pair(b))
1221
0
        readb = b->peer->ptr;
1222
0
    else
1223
0
        readb = b;
1224
0
    if (peer != NULL && (readb->cap & BIO_DGRAM_CAP_HANDLES_DST_ADDR) == 0)
1225
0
        return -BIO_R_PEER_ADDR_NOT_AVAILABLE;
1226
1227
0
    hdr.len = sz;
1228
0
    hdr.dst_addr = (peer != NULL ? *peer : zero_addr);
1229
0
    hdr.src_addr = (local != NULL ? *local : zero_addr);
1230
1231
0
    saved_idx   = b->rbuf.idx[0];
1232
0
    saved_count = b->rbuf.count;
1233
0
    if (dgram_pair_write_inner(b, (const uint8_t *)&hdr, sizeof(hdr)) != sizeof(hdr)
1234
0
            || dgram_pair_write_inner(b, (const uint8_t *)buf, sz) != sz) {
1235
        /*
1236
         * We were not able to push the header and the entirety of the payload
1237
         * onto the ring buffer, so abort and roll back the ring buffer state.
1238
         */
1239
0
        b->rbuf.idx[0] = saved_idx;
1240
0
        b->rbuf.count  = saved_count;
1241
0
        if (!is_multi)
1242
0
            BIO_set_retry_write(bio);
1243
0
        return -BIO_R_NON_FATAL;
1244
0
    }
1245
1246
0
    return sz;
1247
0
}
1248
1249
/* Threadsafe */
1250
static int dgram_pair_write(BIO *bio, const char *buf, int sz_)
1251
0
{
1252
0
    int ret;
1253
0
    ossl_ssize_t l;
1254
0
    struct bio_dgram_pair_st *b = bio->ptr;
1255
1256
0
    if (sz_ < 0) {
1257
0
        ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
1258
0
        return -1;
1259
0
    }
1260
1261
0
    if (CRYPTO_THREAD_write_lock(b->lock) == 0) {
1262
0
        ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1263
0
        return -1;
1264
0
    }
1265
1266
0
    l = dgram_pair_write_actual(bio, buf, (size_t)sz_, NULL, NULL, 0);
1267
0
    if (l < 0) {
1268
0
        ERR_raise(ERR_LIB_BIO, -l);
1269
0
        ret = -1;
1270
0
    } else {
1271
0
        ret = (int)l;
1272
0
    }
1273
1274
0
    CRYPTO_THREAD_unlock(b->lock);
1275
0
    return ret;
1276
0
}
1277
1278
/* Threadsafe */
1279
static int dgram_pair_sendmmsg(BIO *bio, BIO_MSG *msg,
1280
                               size_t stride, size_t num_msg,
1281
                               uint64_t flags, size_t *num_processed)
1282
0
{
1283
0
    ossl_ssize_t ret, l;
1284
0
    BIO_MSG *m;
1285
0
    size_t i;
1286
0
    struct bio_dgram_pair_st *b = bio->ptr;
1287
1288
0
    if (num_msg == 0) {
1289
0
        *num_processed = 0;
1290
0
        return 1;
1291
0
    }
1292
1293
0
    if (CRYPTO_THREAD_write_lock(b->lock) == 0) {
1294
0
        ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1295
0
        *num_processed = 0;
1296
0
        return 0;
1297
0
    }
1298
1299
0
    for (i = 0; i < num_msg; ++i) {
1300
0
        m = &BIO_MSG_N(msg, i);
1301
0
        l = dgram_pair_write_actual(bio, m->data, m->data_len,
1302
0
                                    m->local, m->peer, 1);
1303
0
        if (l < 0) {
1304
0
            *num_processed = i;
1305
0
            if (i > 0) {
1306
0
                ret = 1;
1307
0
            } else {
1308
0
                ERR_raise(ERR_LIB_BIO, -l);
1309
0
                ret = 0;
1310
0
            }
1311
0
            goto out;
1312
0
        }
1313
1314
0
        m->flags = 0;
1315
0
    }
1316
1317
0
    *num_processed = i;
1318
0
    ret = 1;
1319
0
out:
1320
0
    CRYPTO_THREAD_unlock(b->lock);
1321
0
    return ret;
1322
0
}
1323
1324
#endif