OpenVPN 3 Core Library
Loading...
Searching...
No Matches
bio_memq_dgram.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// This code implements an OpenSSL BIO object for datagrams based on the
13// MemQ buffer queue object.
14
15#ifndef OPENVPN_OPENSSL_BIO_BIO_MEMQ_DGRAM_H
16#define OPENVPN_OPENSSL_BIO_BIO_MEMQ_DGRAM_H
17
18#include <cstring> // for std::strlen
19
20#include <openssl/err.h>
21#include <openssl/bio.h>
22
27
29
30class MemQ : public MemQDgram
31{
32 public:
34 {
35 mtu = 0;
37 std::memset(&next_timeout, 0, sizeof(next_timeout));
38 }
39
40 void set_mtu(long mtu)
41 {
43 }
44 const struct timeval *get_next_timeout(void) const
45 {
46 return &next_timeout;
47 }
48
49 long ctrl(BIO *b, int cmd, long num, void *ptr)
50 {
51 long ret = 1;
52
53 switch (cmd)
54 {
55 case BIO_CTRL_RESET:
56 clear();
57 break;
58 case BIO_CTRL_EOF:
59 ret = (long)empty();
60 break;
61 case BIO_C_SET_BUF_MEM_EOF_RETURN:
62 return_eof_on_empty = (num == 0);
63 break;
64 case BIO_CTRL_GET_CLOSE:
65 ret = (long)(BIO_get_shutdown(b));
66 break;
67 case BIO_CTRL_SET_CLOSE:
68 BIO_set_shutdown(b, (int)num);
69 break;
70 case BIO_CTRL_WPENDING:
71 ret = 0L;
72 break;
73 case BIO_CTRL_PENDING:
74 ret = (long)pending();
75 break;
76 case BIO_CTRL_DUP:
77 case BIO_CTRL_FLUSH:
78 ret = 1;
79 break;
80 case BIO_CTRL_DGRAM_QUERY_MTU:
82 break;
83 case BIO_CTRL_DGRAM_GET_MTU:
84 ret = mtu;
85 break;
86 case BIO_CTRL_DGRAM_SET_MTU:
87 ret = mtu = num;
88 break;
89 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
90 std::memcpy(&next_timeout, ptr, sizeof(struct timeval));
91 break;
92 default:
93 // OPENVPN_LOG("*** MemQ-dgram unimplemented ctrl method=" << cmd);
94 ret = 0;
95 break;
96 }
97 return (ret);
98 }
99
100 private:
101 long mtu;
104 struct timeval next_timeout;
105};
106
107namespace bio_memq_internal {
108static int memq_method_type = 0;
109static BIO_METHOD *memq_method = nullptr;
110
111inline int memq_new(BIO *b)
112{
113 MemQ *bmq = new (std::nothrow) MemQ();
114 if (!bmq)
115 return 0;
116 BIO_set_shutdown(b, 1);
117 BIO_set_init(b, 1);
118 b->return_eof_on_empty = false;
119 BIO_set_data(b, (void *)bmq);
120 return 1;
121}
122
123inline int memq_free(BIO *b)
124{
125 if (b == nullptr)
126 return (0);
127 if (BIO_get_shutdown(b))
128 {
129 MemQ *bmq = (MemQ *)(BIO_get_data(b));
130 if (BIO_get_init(b) && (bmq != nullptr))
131 {
132 delete bmq;
133 BIO_set_data(b, nullptr);
134 }
135 }
136 return 1;
137}
138
139inline int memq_write(BIO *b, const char *in, int len)
140{
141 MemQ *bmq = (MemQ *)(BIO_get_data(b));
142 if (in)
143 {
144 BIO_clear_retry_flags(b);
145 try
146 {
147 if (len)
148 bmq->write((const unsigned char *)in, (size_t)len);
149 return len;
150 }
151 catch (...)
152 {
153 BIOerr(BIO_F_MEM_WRITE, BIO_R_INVALID_ARGUMENT);
154 return -1;
155 }
156 }
157 else
158 {
159 BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER);
160 return -1;
161 }
162}
163
164inline int memq_read(BIO *b, char *out, int size)
165{
166 MemQ *bmq = (MemQ *)(BIO_get_data(b));
167 int ret = -1;
168 BIO_clear_retry_flags(b);
169 if (!bmq->empty())
170 {
171 try
172 {
173 ret = (int)bmq->read((unsigned char *)out, (size_t)size);
174 }
175 catch (...)
176 {
177 BIOerr(BIO_F_MEM_READ, BIO_R_INVALID_ARGUMENT);
178 return -1;
179 }
180 }
181 else
182 {
183 ret = b->num;
184 if (ret != 0)
185 BIO_set_retry_read(b);
186 }
187 return ret;
188}
189
190inline long memq_ctrl(BIO *b, int cmd, long arg1, void *arg2)
191{
192 MemQ *bmq = (MemQ *)(BIO_get_data(b));
193 return bmq->ctrl(b, cmd, arg1, arg2);
194}
195
196inline int memq_puts(BIO *b, const char *str)
197{
198 const int len = std::strlen(str);
199 const int ret = memq_write(b, str, len);
200 return ret;
201}
202
203inline void create_bio_method()
204{
205 if (!memq_method_type)
206 memq_method_type = BIO_get_new_index();
207
208 memq_method = BIO_meth_new(memq_method_type, "datagram memory queue");
209 BIO_meth_set_write(memq_method, memq_write);
210 BIO_meth_set_read(memq_read);
211 BIO_meth_set_puts(memq_puts);
212 BIO_meth_set_create(memq_new);
213 BIO_meth_set_destroy(memq_destroy);
214 BIO_meth_set_gets(nullptr);
215 BIO_meth_set_ctrl(memq_method, memq_ctrl);
216}
217
218inline void free_bio_method()
219{
220 BIO_meth_free(memq_method);
221}
222} // namespace bio_memq_internal
223
224inline BIO_METHOD *BIO_s_memq(void)
225{
226 // TODO: call free in some cleanup
229}
230
231inline MemQ *memq_from_bio(BIO *b)
232{
233 if (BIO_method_type(b) == bio_memq_internal::memq_method_type)
234 return (MemQ *)(BIO_get_data(b));
235 else
236 return nullptr;
237}
238
239inline const MemQ *const_memq_from_bio(const BIO *b)
240{
241 if (BIO_method_type(b) == bio_memq_internal::memq_method_type)
242 return (const MemQ *)(BIO_get_data(const_cast<BIO *>(b)));
243 else
244 return nullptr;
245}
246
248{
249 mtu = 0;
250 query_mtu_return = 0;
251 std::memset(&next_timeout, 0, sizeof(next_timeout));
252
254}
255
260} // namespace openvpn::bmq_dgram
261
262#endif // OPENVPN_OPENSSL_BIO_BIO_MEMQ_DGRAM_H
bool empty() const
Definition memq.hpp:37
size_t pending() const
void write(const unsigned char *data, size_t size)
size_t read(unsigned char *data, size_t len)
long ctrl(BIO *b, int cmd, long num, void *ptr)
const struct timeval * get_next_timeout(void) const
int memq_puts(BIO *b, const char *str)
int memq_read(BIO *b, char *out, int size)
long memq_ctrl(BIO *b, int cmd, long arg1, void *arg2)
int memq_write(BIO *b, const char *in, int len)
BIO_METHOD * BIO_s_memq(void)
MemQ * memq_from_bio(BIO *b)
const MemQ * const_memq_from_bio(const BIO *b)
os<< "Session Name: "<< tbc-> session_name<< '\n';os<< "Layer: "<< tbc-> layer str()<< '\n'
std::string ret
static std::stringstream out
Definition test_path.cpp:10