Line data Source code
1 : /* 2 : * Copyright (C) 2009-2012 Free Software Foundation, Inc. 3 : * 4 : * Author: Jonathan Bastien-Filiatrault 5 : * 6 : * This file is part of GNUTLS. 7 : * 8 : * The GNUTLS library is free software; you can redistribute it and/or 9 : * modify it under the terms of the GNU Lesser General Public License 10 : * as published by the Free Software Foundation; either version 2.1 of 11 : * the License, or (at your option) any later version. 12 : * 13 : * This library is distributed in the hope that it will be useful, but 14 : * WITHOUT ANY WARRANTY; without even the implied warranty of 15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 : * Lesser General Public License for more details. 17 : * 18 : * You should have received a copy of the GNU Lesser General Public License 19 : * along with this program. If not, see <https://www.gnu.org/licenses/> 20 : * 21 : */ 22 : 23 : #ifndef GNUTLS_LIB_MBUFFERS_H 24 : #define GNUTLS_LIB_MBUFFERS_H 25 : 26 : #include "gnutls_int.h" 27 : #include "errors.h" 28 : #include <assert.h> 29 : 30 : void _mbuffer_head_init(mbuffer_head_st * buf); 31 : void _mbuffer_head_clear(mbuffer_head_st * buf); 32 : void _mbuffer_enqueue(mbuffer_head_st * buf, mbuffer_st * bufel); 33 : mbuffer_st *_mbuffer_dequeue(mbuffer_head_st * buf, mbuffer_st * bufel); 34 : int _mbuffer_head_remove_bytes(mbuffer_head_st * buf, size_t bytes); 35 : mbuffer_st *_mbuffer_alloc(size_t maximum_size); 36 : int _mbuffer_linearize(mbuffer_head_st * buf); 37 : 38 : mbuffer_st *_mbuffer_head_get_first(mbuffer_head_st * buf, 39 : gnutls_datum_t * msg); 40 : mbuffer_st *_mbuffer_head_get_next(mbuffer_st * cur, gnutls_datum_t * msg); 41 : 42 : void _mbuffer_head_push_first(mbuffer_head_st * buf, mbuffer_st * bufel); 43 : 44 : mbuffer_st *_mbuffer_head_pop_first(mbuffer_head_st * buf); 45 : 46 : /* This is dangerous since it will replace bufel with a new 47 : * one. 48 : */ 49 : int _mbuffer_append_data(mbuffer_st * bufel, void *newdata, 50 : size_t newdata_size); 51 : 52 : 53 : /* For "user" use. One can have buffer data and header. 54 : */ 55 : 56 5127703 : inline static void *_mbuffer_get_uhead_ptr(mbuffer_st * bufel) 57 : { 58 5127703 : return bufel->msg.data + bufel->mark; 59 : } 60 : 61 12372612 : inline static void *_mbuffer_get_udata_ptr(mbuffer_st * bufel) 62 : { 63 11744076 : return bufel->msg.data + bufel->uhead_mark + bufel->mark; 64 : } 65 : 66 11531999 : inline static void _mbuffer_set_udata_size(mbuffer_st * bufel, size_t size) 67 : { 68 8289814 : bufel->msg.size = size + bufel->uhead_mark + bufel->mark; 69 3182980 : } 70 : 71 : inline static void 72 : _mbuffer_set_udata(mbuffer_st * bufel, void *data, size_t data_size) 73 : { 74 : memcpy(_mbuffer_get_udata_ptr(bufel), data, 75 : data_size); 76 : _mbuffer_set_udata_size(bufel, data_size); 77 : } 78 : 79 17750075 : inline static size_t _mbuffer_get_udata_size(mbuffer_st * bufel) 80 : { 81 14514130 : return bufel->msg.size - bufel->uhead_mark - bufel->mark; 82 : } 83 : 84 : /* discards size bytes from the begging of the buffer */ 85 : inline static void 86 6188 : _mbuffer_consume(mbuffer_head_st * buf, mbuffer_st * bufel, size_t size) 87 : { 88 6188 : bufel->uhead_mark = 0; 89 6188 : if (bufel->mark + size < bufel->msg.size) 90 2809 : bufel->mark += size; 91 : else 92 3379 : bufel->mark = bufel->msg.size; 93 : 94 6188 : buf->byte_length -= size; 95 : } 96 : 97 141158 : inline static size_t _mbuffer_get_uhead_size(mbuffer_st * bufel) 98 : { 99 121476 : return bufel->uhead_mark; 100 : } 101 : 102 5308297 : inline static void _mbuffer_set_uhead_size(mbuffer_st * bufel, size_t size) 103 : { 104 5308297 : bufel->uhead_mark = size; 105 14679 : } 106 : 107 57564 : inline static void _mbuffer_init(mbuffer_st *bufel, size_t max) 108 : { 109 57564 : memset(bufel, 0, sizeof(*bufel)); 110 57564 : bufel->maximum_size = max; 111 : 112 : /* payload points after the mbuffer_st structure */ 113 57564 : bufel->msg.data = (uint8_t *) bufel + sizeof(mbuffer_st); 114 : } 115 : 116 : /* Helper functions to utilize a gnutls_buffer_st in order 117 : * to generate a gnutls_mbuffer_st, without multiple allocations. 118 : */ 119 58514 : inline static int _gnutls_buffer_init_mbuffer(gnutls_buffer_st * buf, size_t header_size) 120 : { 121 58514 : int ret; 122 58514 : mbuffer_st *bufel; 123 : 124 58514 : _gnutls_buffer_init(buf); 125 : 126 58514 : ret = _gnutls_buffer_resize(buf, sizeof(mbuffer_st)+header_size); 127 58514 : if (ret < 0) 128 0 : return gnutls_assert_val(ret); 129 : 130 : /* we store the uhead size on the uninitialized bufel, only to read 131 : * it back on _gnutls_buffer_to_mbuffer(). */ 132 58514 : bufel = (void*)buf->data; 133 58514 : _mbuffer_set_uhead_size(bufel, header_size); 134 : 135 58514 : buf->length = sizeof(mbuffer_st)+header_size; 136 : 137 58514 : return 0; 138 : } 139 : 140 : #define _gnutls_buffer_init_handshake_mbuffer(b) _gnutls_buffer_init_mbuffer(b, HANDSHAKE_HEADER_SIZE(session)) 141 : 142 : 143 : /* Cannot fail */ 144 57564 : inline static mbuffer_st *_gnutls_buffer_to_mbuffer(gnutls_buffer_st * buf) 145 : { 146 57564 : mbuffer_st *bufel; 147 57564 : unsigned header_size; 148 : 149 57564 : bufel = (void*)buf->data; 150 : 151 57564 : header_size = _mbuffer_get_uhead_size(bufel); 152 57564 : assert(buf->length >= sizeof(mbuffer_st)+header_size); 153 : 154 57564 : _mbuffer_init(bufel, buf->length - sizeof(mbuffer_st)); 155 : 156 57564 : _mbuffer_set_udata_size(bufel, buf->length - sizeof(mbuffer_st)); 157 57564 : _mbuffer_set_uhead_size(bufel, header_size); 158 : 159 57564 : _gnutls_buffer_init(buf); /* avoid double frees */ 160 : 161 57564 : return bufel; 162 : } 163 : 164 40322 : inline static mbuffer_st *_gnutls_handshake_alloc(gnutls_session_t session, 165 : size_t maximum) 166 : { 167 40322 : mbuffer_st *bufel = 168 79145 : _mbuffer_alloc(HANDSHAKE_HEADER_SIZE(session) + maximum); 169 : 170 40322 : if (!bufel) 171 : return NULL; 172 : 173 40322 : _mbuffer_set_uhead_size(bufel, HANDSHAKE_HEADER_SIZE(session)); 174 40322 : _mbuffer_set_udata_size(bufel, maximum); 175 : 176 40322 : return bufel; 177 : } 178 : 179 : /* Free a segment, if the pointer is not NULL 180 : * 181 : * We take a ** to detect and fix double free bugs (the dangling 182 : * pointer case). It also makes sure the pointer has a known value 183 : * after freeing. 184 : */ 185 20291549 : inline static void _mbuffer_xfree(mbuffer_st ** bufel) 186 : { 187 20288804 : if (*bufel) 188 20291547 : gnutls_free(*bufel); 189 : 190 20287652 : *bufel = NULL; 191 1955 : } 192 : 193 : #ifdef ENABLE_ALIGN16 194 : mbuffer_st *_mbuffer_alloc_align16(size_t maximum_size, unsigned align_pos); 195 : int _mbuffer_linearize_align16(mbuffer_head_st * buf, unsigned align_pos); 196 : #else 197 : # define _mbuffer_alloc_align16(x,y) _mbuffer_alloc(x) 198 : # define _mbuffer_linearize_align16(x,y) _mbuffer_linearize(x) 199 : #endif 200 : 201 : #endif /* GNUTLS_LIB_MBUFFERS_H */