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_DTLS_H 24 : #define GNUTLS_LIB_DTLS_H 25 : 26 : #include <config.h> 27 : #include "gnutls_int.h" 28 : #include <buffers.h> 29 : #include <mbuffers.h> 30 : #include <constate.h> 31 : 32 : int _dtls_transmit(gnutls_session_t session); 33 : int _dtls_record_check(struct record_parameters_st *rp, uint64_t seq_num); 34 : void _dtls_reset_hsk_state(gnutls_session_t session); 35 : void _dtls_reset_window(struct record_parameters_st *rp); 36 : 37 : #define MAX_DTLS_TIMEOUT 60000 38 : 39 : 40 : #define RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, r) { \ 41 : struct timespec _now; \ 42 : unsigned int _diff; \ 43 : gnutls_gettime(&_now); \ 44 : \ 45 : _diff = timespec_sub_ms(&_now, &session->internals.handshake_start_time); \ 46 : if (_diff > session->internals.handshake_timeout_ms) \ 47 : { \ 48 : _gnutls_dtls_log("Session timeout: %u ms\n", _diff); \ 49 : return gnutls_assert_val(GNUTLS_E_TIMEDOUT); \ 50 : } \ 51 : else \ 52 : { \ 53 : int _rr; \ 54 : if (r != GNUTLS_E_INTERRUPTED) _rr = GNUTLS_E_AGAIN; \ 55 : else _rr = r; \ 56 : if (!(session->internals.flags & GNUTLS_NONBLOCK)) \ 57 : millisleep(50); \ 58 : return gnutls_assert_val(_rr); \ 59 : } \ 60 : } 61 : 62 : 63 : int _dtls_wait_and_retransmit(gnutls_session_t session); 64 : 65 : /* returns true or false depending on whether we need to 66 : * handle asynchronously handshake data. 67 : */ 68 520061 : inline static int _dtls_is_async(gnutls_session_t session) 69 : { 70 519474 : if ((session->security_parameters.entity == GNUTLS_SERVER 71 1030 : && session->internals.resumed == RESUME_FALSE) 72 519190 : || (session->security_parameters.entity == GNUTLS_CLIENT 73 519031 : && session->internals.resumed == RESUME_TRUE)) 74 : return 1; 75 : else 76 518659 : return 0; 77 : } 78 : 79 587 : inline static void _dtls_async_timer_init(gnutls_session_t session) 80 : { 81 587 : if (_dtls_is_async(session)) { 82 293 : _gnutls_dtls_log 83 : ("DTLS[%p]: Initializing timer for handshake state.\n", 84 : session); 85 586 : session->internals.dtls.async_term = 86 293 : gnutls_time(0) + MAX_DTLS_TIMEOUT / 1000; 87 : } else { 88 294 : _dtls_reset_hsk_state(session); 89 294 : _gnutls_handshake_io_buffer_clear(session); 90 294 : _gnutls_epoch_gc(session); 91 294 : session->internals.dtls.async_term = 0; 92 : } 93 587 : } 94 : 95 : void _dtls_async_timer_delete(gnutls_session_t session); 96 : 97 : /* Checks whether it is time to terminate the timer 98 : */ 99 3063740 : inline static void _dtls_async_timer_check(gnutls_session_t session) 100 : { 101 3063740 : if (!IS_DTLS(session)) 102 : return; 103 : 104 525362 : if (session->internals.dtls.async_term != 0) { 105 503 : time_t _now = time(0); 106 : 107 : /* check if we need to expire the queued handshake data */ 108 503 : if (_now > session->internals.dtls.async_term) { 109 0 : _dtls_async_timer_delete(session); 110 : } 111 : } 112 : } 113 : 114 : unsigned _gnutls_record_overhead(const version_entry_st *ver, 115 : const cipher_entry_st *cipher, 116 : const mac_entry_st *mac, 117 : unsigned max); 118 : 119 : /* Returns non-zero if the async timer is active */ 120 68 : inline static int _dtls_async_timer_active(gnutls_session_t session) 121 : { 122 68 : if (!IS_DTLS(session)) 123 : return 0; 124 : 125 68 : return session->internals.dtls.async_term; 126 : } 127 : 128 : /* This function is to be called from record layer once 129 : * a handshake replay is detected. It will make sure 130 : * it transmits only once per few seconds. Otherwise 131 : * it is the same as _dtls_transmit(). 132 : */ 133 309 : inline static int _dtls_retransmit(gnutls_session_t session) 134 : { 135 309 : return _dtls_transmit(session); 136 : } 137 : 138 : #endif /* GNUTLS_LIB_DTLS_H */