LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/ext - heartbeat.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 138 217 63.6 %
Date: 2020-10-30 04:50:48 Functions: 9 12 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2012,2013 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2013 Nikos Mavrogiannopoulos
       4             :  *
       5             :  * Author: Nikos Mavrogiannopoulos
       6             :  *
       7             :  * This file is part of GnuTLS.
       8             :  *
       9             :  * The GnuTLS is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public License
      11             :  * as published by the Free Software Foundation; either version 2.1 of
      12             :  * the License, or (at your option) any later version.
      13             :  *
      14             :  * This library is distributed in the hope that it will be useful, but
      15             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public License
      20             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      21             :  *
      22             :  */
      23             : 
      24             : /* This file implements the TLS heartbeat extension.
      25             :  */
      26             : 
      27             : #include "errors.h"
      28             : #include "gnutls_int.h"
      29             : #include <dtls.h>
      30             : #include <record.h>
      31             : #include <ext/heartbeat.h>
      32             : #include <hello_ext.h>
      33             : #include <random.h>
      34             : 
      35             : #ifdef ENABLE_HEARTBEAT
      36             : /**
      37             :   * gnutls_heartbeat_enable:
      38             :   * @session: is a #gnutls_session_t type.
      39             :   * @type: one of the GNUTLS_HB_* flags
      40             :   *
      41             :   * If this function is called with the %GNUTLS_HB_PEER_ALLOWED_TO_SEND
      42             :   * @type, GnuTLS will allow heartbeat messages to be received. Moreover it also
      43             :   * request the peer to accept heartbeat messages. This function
      44             :   * must be called prior to TLS handshake.
      45             :   *
      46             :   * If the @type used is %GNUTLS_HB_LOCAL_ALLOWED_TO_SEND, then the peer
      47             :   * will be asked to accept heartbeat messages but not send ones.
      48             :   *
      49             :   * The function gnutls_heartbeat_allowed() can be used to test Whether
      50             :   * locally generated heartbeat messages can be accepted by the peer.
      51             :   *
      52             :   * Since: 3.1.2
      53             :   **/
      54          18 : void gnutls_heartbeat_enable(gnutls_session_t session, unsigned int type)
      55             : {
      56          18 :         gnutls_ext_priv_data_t epriv;
      57             : 
      58          18 :         epriv = (void*)(intptr_t)type;
      59          18 :         _gnutls_hello_ext_set_priv(session, GNUTLS_EXTENSION_HEARTBEAT,
      60             :                                      epriv);
      61          18 : }
      62             : 
      63             : /**
      64             :   * gnutls_heartbeat_allowed:
      65             :   * @session: is a #gnutls_session_t type.
      66             :   * @type: one of %GNUTLS_HB_LOCAL_ALLOWED_TO_SEND and %GNUTLS_HB_PEER_ALLOWED_TO_SEND
      67             :   *
      68             :   * This function will check whether heartbeats are allowed
      69             :   * to be sent or received in this session. 
      70             :   *
      71             :   * Returns: Non zero if heartbeats are allowed.
      72             :   *
      73             :   * Since: 3.1.2
      74             :   **/
      75         630 : unsigned gnutls_heartbeat_allowed(gnutls_session_t session, unsigned int type)
      76             : {
      77         630 :         gnutls_ext_priv_data_t epriv;
      78             : 
      79         630 :         if (session->internals.handshake_in_progress != 0)
      80             :                 return 0; /* not allowed */
      81             : 
      82         459 :         if (_gnutls_hello_ext_get_priv
      83             :             (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0)
      84             :                 return 0;       /* Not enabled */
      85             : 
      86          13 :         if (type == GNUTLS_HB_LOCAL_ALLOWED_TO_SEND) {
      87           8 :                 if (((intptr_t)epriv) & LOCAL_ALLOWED_TO_SEND)
      88           3 :                         return 1;
      89           5 :         } else if (((intptr_t)epriv) & GNUTLS_HB_PEER_ALLOWED_TO_SEND)
      90           5 :                 return 1;
      91             : 
      92             :         return 0;
      93             : }
      94             : 
      95             : #define DEFAULT_PADDING_SIZE 16
      96             : 
      97             : /*
      98             :  * Sends heartbeat data.
      99             :  */
     100             : static int
     101           5 : heartbeat_send_data(gnutls_session_t session, const void *data,
     102             :                     size_t data_size, uint8_t type)
     103             : {
     104           5 :         int ret, pos;
     105           5 :         uint8_t *response;
     106             : 
     107           5 :         response = gnutls_malloc(1 + 2 + data_size + DEFAULT_PADDING_SIZE);
     108           5 :         if (response == NULL)
     109           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     110             : 
     111           5 :         pos = 0;
     112           5 :         response[pos++] = type;
     113             : 
     114           5 :         _gnutls_write_uint16(data_size, &response[pos]);
     115           5 :         pos += 2;
     116             : 
     117           5 :         memcpy(&response[pos], data, data_size);
     118           5 :         pos += data_size;
     119             : 
     120           5 :         ret =
     121           5 :             gnutls_rnd(GNUTLS_RND_NONCE, &response[pos],
     122             :                        DEFAULT_PADDING_SIZE);
     123           5 :         if (ret < 0) {
     124           0 :                 gnutls_assert();
     125           0 :                 goto cleanup;
     126             :         }
     127           5 :         pos += DEFAULT_PADDING_SIZE;
     128             : 
     129          10 :         ret =
     130           5 :             _gnutls_send_int(session, GNUTLS_HEARTBEAT, -1,
     131             :                              EPOCH_WRITE_CURRENT, response, pos,
     132             :                              MBUFFER_FLUSH);
     133             : 
     134           5 :       cleanup:
     135           5 :         gnutls_free(response);
     136           5 :         return ret;
     137             : }
     138             : 
     139             : /**
     140             :  * gnutls_heartbeat_ping:
     141             :  * @session: is a #gnutls_session_t type.
     142             :  * @data_size: is the length of the ping payload.
     143             :  * @max_tries: if flags is %GNUTLS_HEARTBEAT_WAIT then this sets the number of retransmissions. Use zero for indefinite (until timeout).
     144             :  * @flags: if %GNUTLS_HEARTBEAT_WAIT then wait for pong or timeout instead of returning immediately.
     145             :  *
     146             :  * This function sends a ping to the peer. If the @flags is set
     147             :  * to %GNUTLS_HEARTBEAT_WAIT then it waits for a reply from the peer.
     148             :  * 
     149             :  * Note that it is highly recommended to use this function with the
     150             :  * flag %GNUTLS_HEARTBEAT_WAIT, or you need to handle retransmissions
     151             :  * and timeouts manually.
     152             :  *
     153             :  * The total TLS data transmitted as part of the ping message are given by
     154             :  * the following formula: MAX(16, @data_size)+gnutls_record_overhead_size()+3.
     155             :  *
     156             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     157             :  *
     158             :  * Since: 3.1.2
     159             :  **/
     160             : int
     161           3 : gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size,
     162             :                       unsigned int max_tries, unsigned int flags)
     163             : {
     164           3 :         int ret;
     165           3 :         unsigned int retries = 1, diff;
     166           3 :         struct timespec now;
     167             : 
     168           3 :         if (data_size > MAX_HEARTBEAT_LENGTH)
     169           0 :                 return
     170           0 :                     gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
     171             : 
     172           3 :         if (gnutls_heartbeat_allowed
     173             :             (session, GNUTLS_HB_LOCAL_ALLOWED_TO_SEND) == 0)
     174           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     175             : 
     176             :         /* resume previous call if interrupted */
     177           3 :         if (session->internals.record_send_buffer.byte_length > 0 &&
     178           0 :             session->internals.record_send_buffer.head != NULL &&
     179           0 :             session->internals.record_send_buffer.head->type ==
     180             :             GNUTLS_HEARTBEAT)
     181           0 :                 return _gnutls_io_write_flush(session);
     182             : 
     183           3 :         switch (session->internals.hb_state) {
     184           3 :         case SHB_SEND1:
     185           3 :                 if (data_size > DEFAULT_PADDING_SIZE)
     186           3 :                         data_size -= DEFAULT_PADDING_SIZE;
     187             :                 else
     188             :                         data_size = 0;
     189             : 
     190           3 :                 _gnutls_buffer_reset(&session->internals.hb_local_data);
     191             : 
     192           3 :                 ret =
     193           3 :                     _gnutls_buffer_resize(&session->internals.
     194             :                                           hb_local_data, data_size);
     195           3 :                 if (ret < 0)
     196           0 :                         return gnutls_assert_val(ret);
     197             : 
     198           3 :                 ret =
     199           6 :                     gnutls_rnd(GNUTLS_RND_NONCE,
     200           3 :                                 session->internals.hb_local_data.data,
     201             :                                 data_size);
     202           3 :                 if (ret < 0)
     203           0 :                         return gnutls_assert_val(ret);
     204             : 
     205           3 :                 gnutls_gettime(&session->internals.hb_ping_start);
     206           3 :                 session->internals.hb_local_data.length = data_size;
     207           3 :                 session->internals.hb_state = SHB_SEND2;
     208             : 
     209           3 :                 FALLTHROUGH;
     210           3 :         case SHB_SEND2:
     211           3 :                 session->internals.hb_actual_retrans_timeout_ms =
     212           3 :                     session->internals.hb_retrans_timeout_ms;
     213           3 :               retry:
     214           3 :                 ret =
     215           6 :                     heartbeat_send_data(session,
     216           3 :                                         session->internals.hb_local_data.
     217             :                                         data,
     218             :                                         session->internals.hb_local_data.
     219             :                                         length, HEARTBEAT_REQUEST);
     220           3 :                 if (ret < 0)
     221           0 :                         return gnutls_assert_val(ret);
     222             : 
     223           3 :                 gnutls_gettime(&session->internals.hb_ping_sent);
     224             : 
     225           3 :                 if (!(flags & GNUTLS_HEARTBEAT_WAIT)) {
     226           0 :                         session->internals.hb_state = SHB_SEND1;
     227           0 :                         break;
     228             :                 }
     229             : 
     230           3 :                 session->internals.hb_state = SHB_RECV;
     231           3 :                 FALLTHROUGH;
     232             : 
     233           3 :         case SHB_RECV:
     234           6 :                 ret =
     235           3 :                     _gnutls_recv_int(session, GNUTLS_HEARTBEAT,
     236             :                                      NULL, 0, NULL,
     237             :                                      session->internals.
     238             :                                      hb_actual_retrans_timeout_ms);
     239           3 :                 if (ret == GNUTLS_E_HEARTBEAT_PONG_RECEIVED) {
     240           3 :                         session->internals.hb_state = SHB_SEND1;
     241           3 :                         break;
     242           0 :                 } else if (ret == GNUTLS_E_TIMEDOUT) {
     243           0 :                         retries++;
     244           0 :                         if (max_tries > 0 && retries > max_tries) {
     245           0 :                                 session->internals.hb_state = SHB_SEND1;
     246           0 :                                 return gnutls_assert_val(ret);
     247             :                         }
     248             : 
     249           0 :                         gnutls_gettime(&now);
     250           0 :                         diff =
     251           0 :                             timespec_sub_ms(&now,
     252             :                                             &session->internals.
     253             :                                             hb_ping_start);
     254           0 :                         if (diff > session->internals.hb_total_timeout_ms) {
     255           0 :                                 session->internals.hb_state = SHB_SEND1;
     256           0 :                                 return
     257           0 :                                     gnutls_assert_val(GNUTLS_E_TIMEDOUT);
     258             :                         }
     259             : 
     260           0 :                         session->internals.hb_actual_retrans_timeout_ms *=
     261             :                             2;
     262           0 :                         session->internals.hb_actual_retrans_timeout_ms %=
     263             :                             MAX_DTLS_TIMEOUT;
     264             : 
     265           0 :                         session->internals.hb_state = SHB_SEND2;
     266           0 :                         goto retry;
     267           0 :                 } else if (ret < 0) {
     268           0 :                         session->internals.hb_state = SHB_SEND1;
     269           0 :                         return gnutls_assert_val(ret);
     270             :                 }
     271             :         }
     272             : 
     273             :         return 0;
     274             : }
     275             : 
     276             : /**
     277             :  * gnutls_heartbeat_pong:
     278             :  * @session: is a #gnutls_session_t type.
     279             :  * @flags: should be zero
     280             :  *
     281             :  * This function replies to a ping by sending a pong to the peer.
     282             :  *
     283             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     284             :  *
     285             :  * Since: 3.1.2
     286             :  **/
     287           2 : int gnutls_heartbeat_pong(gnutls_session_t session, unsigned int flags)
     288             : {
     289           2 :         int ret;
     290             : 
     291           2 :         if (session->internals.record_send_buffer.byte_length > 0 &&
     292           0 :             session->internals.record_send_buffer.head != NULL &&
     293           0 :             session->internals.record_send_buffer.head->type ==
     294             :             GNUTLS_HEARTBEAT)
     295           0 :                 return _gnutls_io_write_flush(session);
     296             : 
     297           2 :         if (session->internals.hb_remote_data.length == 0)
     298           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     299             : 
     300           2 :         ret =
     301           4 :             heartbeat_send_data(session,
     302           2 :                                 session->internals.hb_remote_data.data,
     303             :                                 session->internals.hb_remote_data.length,
     304             :                                 HEARTBEAT_RESPONSE);
     305             : 
     306           2 :         _gnutls_buffer_reset(&session->internals.hb_remote_data);
     307             : 
     308           2 :         if (ret < 0)
     309           0 :                 return gnutls_assert_val(ret);
     310             : 
     311             :         return 0;
     312             : }
     313             : 
     314             : /*
     315             :  * Processes a heartbeat message. 
     316             :  */
     317          18 : int _gnutls_heartbeat_handle(gnutls_session_t session, mbuffer_st * bufel)
     318             : {
     319          18 :         int ret;
     320          18 :         unsigned type;
     321          18 :         unsigned pos;
     322          18 :         uint8_t *msg = _mbuffer_get_udata_ptr(bufel);
     323          18 :         size_t hb_len, len = _mbuffer_get_udata_size(bufel);
     324             : 
     325          18 :         if (gnutls_heartbeat_allowed
     326             :             (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND) == 0)
     327          20 :                 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
     328             : 
     329           5 :         if (len < 3 + DEFAULT_PADDING_SIZE)
     330           0 :                 return
     331           0 :                     gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
     332             : 
     333           5 :         pos = 0;
     334           5 :         type = msg[pos++];
     335             : 
     336           5 :         hb_len = _gnutls_read_uint16(&msg[pos]);
     337           5 :         if (hb_len > len - 3 - DEFAULT_PADDING_SIZE)
     338           0 :                 return
     339           0 :                     gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
     340             : 
     341           5 :         pos += 2;
     342             : 
     343           5 :         switch (type) {
     344           2 :         case HEARTBEAT_REQUEST:
     345           2 :                 _gnutls_buffer_reset(&session->internals.hb_remote_data);
     346             : 
     347           2 :                 ret =
     348           2 :                     _gnutls_buffer_resize(&session->internals.
     349             :                                           hb_remote_data, hb_len);
     350           2 :                 if (ret < 0)
     351           0 :                         return gnutls_assert_val(ret);
     352             : 
     353           2 :                 if (hb_len > 0)
     354           2 :                         memcpy(session->internals.hb_remote_data.data,
     355           2 :                                &msg[pos], hb_len);
     356           2 :                 session->internals.hb_remote_data.length = hb_len;
     357             : 
     358           2 :                 return gnutls_assert_val(GNUTLS_E_HEARTBEAT_PING_RECEIVED);
     359             : 
     360           3 :         case HEARTBEAT_RESPONSE:
     361             : 
     362           3 :                 if (hb_len != session->internals.hb_local_data.length)
     363           0 :                         return
     364           0 :                             gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
     365             : 
     366           3 :                 if (hb_len > 0 &&
     367           3 :                     memcmp(&msg[pos],
     368           3 :                            session->internals.hb_local_data.data,
     369             :                            hb_len) != 0) {
     370           0 :                         if (IS_DTLS(session))
     371           0 :                                 return gnutls_assert_val(GNUTLS_E_AGAIN);       /* ignore it */
     372             :                         else
     373           0 :                                 return
     374           0 :                                     gnutls_assert_val
     375             :                                     (GNUTLS_E_UNEXPECTED_PACKET);
     376             :                 }
     377             : 
     378           3 :                 _gnutls_buffer_reset(&session->internals.hb_local_data);
     379             : 
     380           3 :                 return gnutls_assert_val(GNUTLS_E_HEARTBEAT_PONG_RECEIVED);
     381           0 :         default:
     382           0 :                 _gnutls_record_log
     383             :                     ("REC[%p]: HB: received unknown type %u\n", session,
     384             :                      type);
     385           0 :                 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
     386             :         }
     387             : }
     388             : 
     389             : /**
     390             :  * gnutls_heartbeat_get_timeout:
     391             :  * @session: is a #gnutls_session_t type.
     392             :  *
     393             :  * This function will return the milliseconds remaining
     394             :  * for a retransmission of the previously sent ping
     395             :  * message. This function is useful when ping is used in
     396             :  * non-blocking mode, to estimate when to call gnutls_heartbeat_ping()
     397             :  * if no packets have been received.
     398             :  *
     399             :  * Returns: the remaining time in milliseconds.
     400             :  *
     401             :  * Since: 3.1.2
     402             :  **/
     403           0 : unsigned int gnutls_heartbeat_get_timeout(gnutls_session_t session)
     404             : {
     405           0 :         struct timespec now;
     406           0 :         unsigned int diff;
     407             : 
     408           0 :         gnutls_gettime(&now);
     409           0 :         diff = timespec_sub_ms(&now, &session->internals.hb_ping_sent);
     410           0 :         if (diff >= session->internals.hb_actual_retrans_timeout_ms)
     411             :                 return 0;
     412             :         else
     413           0 :                 return session->internals.hb_actual_retrans_timeout_ms -
     414             :                     diff;
     415             : }
     416             : 
     417             : /**
     418             :  * gnutls_heartbeat_set_timeouts:
     419             :  * @session: is a #gnutls_session_t type.
     420             :  * @retrans_timeout: The time at which a retransmission will occur in milliseconds
     421             :  * @total_timeout: The time at which the connection will be aborted, in milliseconds.
     422             :  *
     423             :  * This function will override the timeouts for the DTLS heartbeat
     424             :  * protocol. The retransmission timeout is the time after which a
     425             :  * message from the peer is not received, the previous request will
     426             :  * be retransmitted. The total timeout is the time after which the
     427             :  * handshake will be aborted with %GNUTLS_E_TIMEDOUT.
     428             :  *
     429             :  * Since: 3.1.2
     430             :  **/
     431           0 : void gnutls_heartbeat_set_timeouts(gnutls_session_t session,
     432             :                                    unsigned int retrans_timeout,
     433             :                                    unsigned int total_timeout)
     434             : {
     435           0 :         session->internals.hb_retrans_timeout_ms = retrans_timeout;
     436           0 :         session->internals.hb_total_timeout_ms = total_timeout;
     437           0 : }
     438             : 
     439             : 
     440             : static int
     441          56 : _gnutls_heartbeat_recv_params(gnutls_session_t session,
     442             :                               const uint8_t * data, size_t _data_size)
     443             : {
     444          56 :         unsigned policy;
     445          56 :         gnutls_ext_priv_data_t epriv;
     446             : 
     447          56 :         if (_gnutls_hello_ext_get_priv
     448             :             (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0) {
     449          44 :                 if (session->security_parameters.entity == GNUTLS_CLIENT)
     450           0 :                         return
     451           0 :                             gnutls_assert_val
     452             :                             (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
     453             :                 return 0;       /* Not enabled */
     454             :         }
     455             : 
     456          12 :         if (_data_size == 0)
     457             :                 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
     458             : 
     459          12 :         policy = (intptr_t)epriv;
     460             : 
     461          12 :         if (data[0] == 1)
     462          12 :                 policy |= LOCAL_ALLOWED_TO_SEND;
     463           0 :         else if (data[0] == 2)
     464           0 :                 policy |= LOCAL_NOT_ALLOWED_TO_SEND;
     465             :         else
     466           0 :                 return
     467           0 :                     gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
     468             : 
     469          12 :         epriv = (void*)(intptr_t)policy;
     470          12 :         _gnutls_hello_ext_set_priv(session, GNUTLS_EXTENSION_HEARTBEAT,
     471             :                                      epriv);
     472             : 
     473          12 :         return 0;
     474             : }
     475             : 
     476             : static int
     477        3818 : _gnutls_heartbeat_send_params(gnutls_session_t session,
     478             :                               gnutls_buffer_st * extdata)
     479             : {
     480        3818 :         gnutls_ext_priv_data_t epriv;
     481        3818 :         uint8_t p;
     482             : 
     483        3818 :         if (_gnutls_hello_ext_get_priv
     484             :             (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0)
     485             :                 return 0;       /* nothing to send - not enabled */
     486             : 
     487          18 :         if (((intptr_t)epriv) & GNUTLS_HB_PEER_ALLOWED_TO_SEND)
     488          18 :                 p = 1;
     489             :         else                    /*if (epriv.num & GNUTLS_HB_PEER_NOT_ALLOWED_TO_SEND) */
     490           0 :                 p = 2;
     491             : 
     492          18 :         if (_gnutls_buffer_append_data(extdata, &p, 1) < 0)
     493           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     494             : 
     495             :         return 1;
     496             : }
     497             : 
     498             : static int
     499          17 : _gnutls_heartbeat_pack(gnutls_ext_priv_data_t epriv, gnutls_buffer_st * ps)
     500             : {
     501          17 :         int ret;
     502             : 
     503          17 :         BUFFER_APPEND_NUM(ps, (intptr_t)epriv);
     504             : 
     505             :         return 0;
     506             : 
     507             : }
     508             : 
     509             : static int
     510           0 : _gnutls_heartbeat_unpack(gnutls_buffer_st * ps,
     511             :                          gnutls_ext_priv_data_t * _priv)
     512             : {
     513           0 :         gnutls_ext_priv_data_t epriv;
     514           0 :         int ret;
     515             : 
     516           0 :         BUFFER_POP_CAST_NUM(ps, epriv);
     517             : 
     518           0 :         *_priv = epriv;
     519             : 
     520           0 :         ret = 0;
     521           0 :       error:
     522           0 :         return ret;
     523             : }
     524             : 
     525             : const hello_ext_entry_st ext_mod_heartbeat = {
     526             :         .name = "Heartbeat",
     527             :         .tls_id = 15,
     528             :         .gid = GNUTLS_EXTENSION_HEARTBEAT,
     529             :         .client_parse_point = GNUTLS_EXT_TLS,
     530             :         .server_parse_point = GNUTLS_EXT_TLS,
     531             :         .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
     532             :                     GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
     533             :         .recv_func = _gnutls_heartbeat_recv_params,
     534             :         .send_func = _gnutls_heartbeat_send_params,
     535             :         .pack_func = _gnutls_heartbeat_pack,
     536             :         .unpack_func = _gnutls_heartbeat_unpack,
     537             :         .deinit_func = NULL,
     538             :         .cannot_be_overriden = 1
     539             : };
     540             : 
     541             : #else
     542             : void gnutls_heartbeat_enable(gnutls_session_t session, unsigned int type)
     543             : {
     544             : }
     545             : 
     546             : unsigned gnutls_heartbeat_allowed(gnutls_session_t session, unsigned int type)
     547             : {
     548             :         return 0;
     549             : }
     550             : 
     551             : int
     552             : gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size,
     553             :                       unsigned int max_tries, unsigned int flags)
     554             : {
     555             :         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     556             : }
     557             : 
     558             : int gnutls_heartbeat_pong(gnutls_session_t session, unsigned int flags)
     559             : {
     560             :         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     561             : }
     562             : 
     563             : unsigned int gnutls_heartbeat_get_timeout(gnutls_session_t session)
     564             : {
     565             :         return 0;
     566             : }
     567             : 
     568             : void gnutls_heartbeat_set_timeouts(gnutls_session_t session,
     569             :                                    unsigned int retrans_timeout,
     570             :                                    unsigned int total_timeout)
     571             : {
     572             :         return;
     573             : }
     574             : #endif

Generated by: LCOV version 1.14