Line data Source code
1 :
2 : /*
3 : * Copyright (c) 2020 Cisco and/or its affiliates.
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at:
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : */
16 : #include <openssl/bio.h>
17 : #include <openssl/err.h>
18 : #include <vnet/session/session.h>
19 : #include <vnet/session/application_interface.h>
20 :
21 : static inline session_t *
22 4243 : bio_session (BIO * bio)
23 : {
24 8486 : return session_get_from_handle (pointer_to_uword (BIO_get_data (bio)));
25 : }
26 :
27 : static int
28 8 : bio_tls_alloc (BIO * bio)
29 : {
30 8 : BIO_set_init (bio, 0);
31 8 : BIO_set_data (bio, 0);
32 8 : BIO_set_flags (bio, 0);
33 8 : BIO_set_shutdown (bio, 0);
34 8 : return 1;
35 : }
36 :
37 : static int
38 4 : bio_tls_free (BIO * bio)
39 : {
40 4 : if (!bio)
41 0 : return 0;
42 :
43 4 : if (BIO_get_shutdown (bio))
44 : {
45 0 : if (BIO_get_init (bio))
46 0 : session_close (bio_session (bio));
47 0 : BIO_set_init (bio, 0);
48 0 : BIO_set_flags (bio, 0);
49 : }
50 :
51 4 : return 1;
52 : }
53 :
54 : static int
55 3199 : bio_tls_read (BIO * b, char *out, int outl)
56 : {
57 : session_t *s;
58 : int rv;
59 :
60 3199 : if (PREDICT_FALSE (!out))
61 0 : return 0;
62 :
63 3199 : s = bio_session (b);
64 3199 : if (!s)
65 : {
66 0 : clib_warning ("no session");
67 0 : errno = EBADFD;
68 0 : return -1;
69 : }
70 :
71 3199 : rv = app_recv_stream_raw (s->rx_fifo, (u8 *) out, outl,
72 : 0 /* clear evt */ , 0 /* peek */ );
73 3199 : if (rv < 0)
74 : {
75 635 : BIO_set_retry_read (b);
76 635 : errno = EAGAIN;
77 635 : return -1;
78 : }
79 :
80 2564 : if (svm_fifo_needs_deq_ntf (s->rx_fifo, rv))
81 : {
82 0 : svm_fifo_clear_deq_ntf (s->rx_fifo);
83 0 : session_send_io_evt_to_thread (s->rx_fifo, SESSION_IO_EVT_RX);
84 : }
85 :
86 2564 : if (svm_fifo_is_empty_cons (s->rx_fifo))
87 467 : svm_fifo_unset_event (s->rx_fifo);
88 :
89 2564 : BIO_clear_retry_flags (b);
90 :
91 2564 : return rv;
92 : }
93 :
94 : static int
95 1044 : bio_tls_write (BIO * b, const char *in, int inl)
96 : {
97 : svm_msg_q_t *mq;
98 : session_t *s;
99 : int rv;
100 :
101 1044 : if (PREDICT_FALSE (!in))
102 0 : return 0;
103 :
104 1044 : s = bio_session (b);
105 1044 : if (!s)
106 : {
107 0 : clib_warning ("no session");
108 0 : errno = EBADFD;
109 0 : return -1;
110 : }
111 :
112 1044 : mq = session_main_get_vpp_event_queue (s->thread_index);
113 1044 : rv = app_send_stream_raw (s->tx_fifo, mq, (u8 *) in, inl,
114 : SESSION_IO_EVT_TX, 1 /* do_evt */ ,
115 : 0 /* noblock */ );
116 1044 : if (rv < 0)
117 : {
118 0 : BIO_set_retry_write (b);
119 0 : errno = EAGAIN;
120 0 : return -1;
121 : }
122 :
123 1044 : BIO_clear_retry_flags (b);
124 :
125 1044 : return rv;
126 : }
127 :
128 : long
129 34 : bio_tls_ctrl (BIO * b, int cmd, long larg, void *ptr)
130 : {
131 34 : long ret = 1;
132 :
133 34 : switch (cmd)
134 : {
135 0 : case BIO_C_SET_FD:
136 0 : ASSERT (0);
137 0 : break;
138 0 : case BIO_C_GET_FD:
139 0 : ASSERT (0);
140 0 : break;
141 0 : case BIO_CTRL_GET_CLOSE:
142 0 : ret = BIO_get_shutdown (b);
143 0 : break;
144 0 : case BIO_CTRL_SET_CLOSE:
145 0 : BIO_set_shutdown (b, (int) larg);
146 0 : break;
147 14 : case BIO_CTRL_DUP:
148 : case BIO_CTRL_FLUSH:
149 14 : ret = 1;
150 14 : break;
151 4 : case BIO_CTRL_PENDING:
152 4 : ret = 0;
153 4 : break;
154 16 : default:
155 16 : ret = 0;
156 16 : break;
157 : }
158 34 : return ret;
159 : }
160 :
161 : BIO *
162 8 : BIO_new_tls (session_handle_t sh)
163 : {
164 : static BIO_METHOD *tls_bio_method;
165 : BIO *b;
166 8 : if (!tls_bio_method)
167 : {
168 2 : tls_bio_method = BIO_meth_new (BIO_TYPE_SOCKET, "tls_bio");
169 2 : BIO_meth_set_write (tls_bio_method, bio_tls_write);
170 2 : BIO_meth_set_read (tls_bio_method, bio_tls_read);
171 2 : BIO_meth_set_create (tls_bio_method, bio_tls_alloc);
172 2 : BIO_meth_set_destroy (tls_bio_method, bio_tls_free);
173 2 : BIO_meth_set_ctrl (tls_bio_method, bio_tls_ctrl);
174 : }
175 8 : b = BIO_new (tls_bio_method);
176 : /* Initialize the BIO */
177 8 : BIO_set_data (b, uword_to_pointer (sh, void *));
178 8 : BIO_set_init (b, 1);
179 8 : return b;
180 : }
181 :
182 : /*
183 : * fd.io coding-style-patch-verification: ON
184 : *
185 : * Local Variables:
186 : * eval: (c-set-style "gnu")
187 : * End:
188 : */
|