Line data Source code
1 : /*
2 : * Copyright (c) 2021 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : #include <openssl/bio.h>
17 : #include <openssl/err.h>
18 :
19 : #include <vnet/session/session.h>
20 : #include <vnet/session/application_interface.h>
21 :
22 : static inline session_t *
23 2042 : bio_session (BIO *bio)
24 : {
25 4084 : return session_get_from_handle (pointer_to_uword (BIO_get_data (bio)));
26 : }
27 :
28 : static int
29 4 : bio_dtls_alloc (BIO *bio)
30 : {
31 4 : BIO_set_init (bio, 0);
32 4 : BIO_set_data (bio, 0);
33 4 : BIO_set_flags (bio, 0);
34 4 : BIO_set_shutdown (bio, 0);
35 4 : return 1;
36 : }
37 :
38 : static int
39 4 : bio_dtls_free (BIO *bio)
40 : {
41 4 : if (!bio)
42 0 : return 0;
43 :
44 4 : if (BIO_get_shutdown (bio))
45 : {
46 0 : if (BIO_get_init (bio))
47 0 : session_close (bio_session (bio));
48 0 : BIO_set_init (bio, 0);
49 0 : BIO_set_flags (bio, 0);
50 : }
51 4 : return 1;
52 : }
53 :
54 : static int
55 1010 : bio_dtls_read (BIO *b, char *out, int outl)
56 : {
57 : app_session_transport_t at;
58 : session_t *s;
59 : int rv;
60 :
61 1010 : if (PREDICT_FALSE (!out))
62 0 : return 0;
63 :
64 1010 : s = bio_session (b);
65 1010 : if (!s)
66 : {
67 0 : clib_warning ("no session");
68 0 : errno = EBADFD;
69 0 : return -1;
70 : }
71 :
72 1010 : rv = app_recv_dgram_raw (s->rx_fifo, (u8 *) out, outl, &at,
73 : 0 /* clear evt */, 0 /* peek */);
74 :
75 1010 : if (rv < 0)
76 : {
77 0 : BIO_set_retry_read (b);
78 0 : errno = EAGAIN;
79 0 : return -1;
80 : }
81 :
82 1010 : if (svm_fifo_is_empty_cons (s->rx_fifo))
83 96 : svm_fifo_unset_event (s->rx_fifo);
84 :
85 1010 : BIO_clear_retry_flags (b);
86 :
87 1010 : return rv;
88 : }
89 :
90 : static int
91 1006 : bio_dtls_write (BIO *b, const char *in, int inl)
92 : {
93 1006 : app_session_transport_t at = { 0 };
94 : svm_msg_q_t *mq;
95 : session_t *s;
96 : int rv;
97 :
98 1006 : if (PREDICT_FALSE (!in))
99 0 : return 0;
100 :
101 1006 : s = bio_session (b);
102 1006 : if (!s)
103 : {
104 0 : clib_warning ("no session");
105 0 : errno = EBADFD;
106 0 : return -1;
107 : }
108 :
109 1006 : mq = session_main_get_vpp_event_queue (s->thread_index);
110 1006 : rv = app_send_dgram_raw (s->tx_fifo, &at, mq, (u8 *) in, inl,
111 : SESSION_IO_EVT_TX, 1 /* do_evt */, 0 /* noblock */);
112 :
113 1006 : if (rv <= 0)
114 : {
115 0 : BIO_set_retry_read (b);
116 0 : errno = EAGAIN;
117 0 : return -1;
118 : }
119 :
120 1006 : BIO_clear_retry_flags (b);
121 :
122 1006 : return rv;
123 : }
124 :
125 : static int
126 24 : dtls_dgram_overhead (BIO *b)
127 : {
128 24 : session_t *s = bio_session (b);
129 24 : if (session_type_is_ip4 (s->session_type))
130 : /* 20B ip 8B udp */
131 24 : return 28;
132 : else
133 : /* 40B ip 8B udp */
134 0 : return 48;
135 : }
136 :
137 : static u16
138 2 : dtls_dgram_mss (BIO *b)
139 : {
140 2 : session_t *s = bio_session (b);
141 : transport_send_params_t sp;
142 :
143 2 : transport_connection_snd_params (session_get_transport (s), &sp);
144 :
145 2 : return sp.snd_mss;
146 : }
147 :
148 : long
149 54 : bio_dtls_ctrl (BIO *b, int cmd, long larg, void *parg)
150 : {
151 54 : long ret = 1;
152 :
153 54 : switch (cmd)
154 : {
155 0 : case BIO_C_SET_FD:
156 0 : os_panic ();
157 0 : break;
158 0 : case BIO_C_GET_FD:
159 0 : os_panic ();
160 0 : break;
161 0 : case BIO_CTRL_GET_CLOSE:
162 0 : ret = BIO_get_shutdown (b);
163 0 : break;
164 0 : case BIO_CTRL_SET_CLOSE:
165 0 : BIO_set_shutdown (b, (int) larg);
166 0 : break;
167 6 : case BIO_CTRL_PENDING:
168 : case BIO_CTRL_WPENDING:
169 6 : ret = 0;
170 6 : break;
171 6 : case BIO_CTRL_DUP:
172 : case BIO_CTRL_FLUSH:
173 6 : ret = 1;
174 6 : break;
175 2 : case BIO_CTRL_DGRAM_QUERY_MTU:
176 2 : ret = dtls_dgram_mss (b);
177 2 : break;
178 0 : case BIO_CTRL_DGRAM_SET_MTU:
179 0 : ret = 0;
180 0 : break;
181 12 : case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
182 12 : ret = 0;
183 12 : break;
184 24 : case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
185 24 : ret = dtls_dgram_overhead (b);
186 24 : break;
187 4 : default:
188 4 : ret = 0;
189 4 : break;
190 : }
191 54 : return ret;
192 : }
193 :
194 : BIO *
195 4 : BIO_new_dtls (session_handle_t sh)
196 : {
197 : static BIO_METHOD *dtls_bio_method;
198 : BIO *b;
199 :
200 4 : if (!dtls_bio_method)
201 : {
202 1 : dtls_bio_method = BIO_meth_new (BIO_TYPE_SOCKET, "dtls_bio");
203 1 : BIO_meth_set_write (dtls_bio_method, bio_dtls_write);
204 1 : BIO_meth_set_read (dtls_bio_method, bio_dtls_read);
205 1 : BIO_meth_set_create (dtls_bio_method, bio_dtls_alloc);
206 1 : BIO_meth_set_destroy (dtls_bio_method, bio_dtls_free);
207 1 : BIO_meth_set_ctrl (dtls_bio_method, bio_dtls_ctrl);
208 : }
209 :
210 4 : b = BIO_new (dtls_bio_method);
211 :
212 : /* Initialize the BIO */
213 4 : BIO_set_data (b, uword_to_pointer (sh, void *));
214 4 : BIO_set_init (b, 1);
215 :
216 4 : return b;
217 : }
218 :
219 : /*
220 : * fd.io coding-style-patch-verification: ON
221 : *
222 : * Local Variables:
223 : * eval: (c-set-style "gnu")
224 : * End:
225 : */
|