summaryrefslogtreecommitdiff
path: root/src/openvpn/occ.h
blob: 067a65891ec185cecbb13985b125b6666269fa6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 *  OpenVPN -- An application to securely tunnel IP networks
 *             over a single TCP/UDP port, with support for SSL/TLS-based
 *             session authentication and key exchange,
 *             packet encryption, packet authentication, and
 *             packet compression.
 *
 *  Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2
 *  as published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef OCC_H
#define OCC_H

#include "forward.h"

/* OCC_STRING_SIZE must be set to sizeof (occ_magic) */
#define OCC_STRING_SIZE 16

/*
 * OCC (OpenVPN Configuration Control) protocol opcodes.
 */

#define OCC_REQUEST   0         /* request options string from peer */
#define OCC_REPLY     1         /* deliver options string to peer */

/*
 * Send an OCC_REQUEST once every OCC_INTERVAL
 * seconds until a reply is received.
 *
 * If we haven't received a reply after
 * OCC_N_TRIES, give up.
 */
#define OCC_INTERVAL_SECONDS 10
#define OCC_N_TRIES          12

/*
 * Other OCC protocol opcodes used to estimate the MTU empirically.
 */
#define OCC_MTU_LOAD_REQUEST   2        /* Ask peer to send a big packet to us */
#define OCC_MTU_LOAD           3        /* Send a big packet to peer */
#define OCC_MTU_REQUEST        4        /* Ask peer to tell us the largest
                                         * packet it has received from us so far */
#define OCC_MTU_REPLY          5        /* Send largest packet size to peer */

/*
 * Process one command from mtu_load_test_sequence
 * once every n seconds, if --mtu-test is specified.
 */
#define OCC_MTU_LOAD_INTERVAL_SECONDS 3

/*
 * Send an exit message to remote.
 */
#define OCC_EXIT               6

/*
 * Used to conduct a load test command sequence
 * of UDP connection for empirical MTU measurement.
 */
struct mtu_load_test
{
    int op;                     /* OCC opcode to send to peer */
    int delta;                  /* determine packet size to send by using
                                 * this delta against currently
                                 * configured MTU */
};

extern const uint8_t occ_magic[];

static inline bool
is_occ_msg(const struct buffer *buf)
{
    return buf_string_match_head(buf, occ_magic, OCC_STRING_SIZE);
}

void process_received_occ_msg(struct context *c);

void check_send_occ_req_dowork(struct context *c);

void check_send_occ_load_test_dowork(struct context *c);

void check_send_occ_msg_dowork(struct context *c);

/*
 * Inline functions
 */

static inline int
occ_reset_op(void)
{
    return -1;
}

/*
 * Should we send an OCC_REQUEST message?
 */
static inline void
check_send_occ_req(struct context *c)
{
    if (event_timeout_defined(&c->c2.occ_interval)
        && event_timeout_trigger(&c->c2.occ_interval,
                                 &c->c2.timeval,
                                 (!TO_LINK_DEF(c) && c->c2.occ_op < 0) ? ETT_DEFAULT : 0))
    {
        check_send_occ_req_dowork(c);
    }
}

/*
 * Should we send an MTU load test?
 */
static inline void
check_send_occ_load_test(struct context *c)
{
    if (event_timeout_defined(&c->c2.occ_mtu_load_test_interval)
        && event_timeout_trigger(&c->c2.occ_mtu_load_test_interval,
                                 &c->c2.timeval,
                                 (!TO_LINK_DEF(c) && c->c2.occ_op < 0) ? ETT_DEFAULT : 0))
    {
        check_send_occ_load_test_dowork(c);
    }
}

/*
 * Should we send an OCC message?
 */
static inline void
check_send_occ_msg(struct context *c)
{
    if (c->c2.occ_op >= 0)
    {
        if (!TO_LINK_DEF(c))
        {
            check_send_occ_msg_dowork(c);
        }
        else
        {
            tv_clear(&c->c2.timeval); /* ZERO-TIMEOUT */
        }
    }
}

#endif /* ifndef OCC_H */