OpenVPN
mtu.c
Go to the documentation of this file.
1 /*
2  * OpenVPN -- An application to securely tunnel IP networks
3  * over a single TCP/UDP port, with support for SSL/TLS-based
4  * session authentication and key exchange,
5  * packet encryption, packet authentication, and
6  * packet compression.
7  *
8  * Copyright (C) 2002-2022 OpenVPN Inc <sales@openvpn.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2
12  * as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 
30 #include "syshead.h"
31 
32 #include "common.h"
33 #include "buffer.h"
34 #include "error.h"
35 #include "integer.h"
36 #include "mtu.h"
37 #include "options.h"
38 #include "crypto.h"
39 
40 #include "memdbg.h"
41 
42 /* allocate a buffer for socket or tun layer */
43 void
45  const struct frame *frame,
46  const bool tuntap_buffer)
47 {
48  /* allocate buffer for overlapped I/O */
49  *buf = alloc_buf(BUF_SIZE(frame));
51  buf->len = frame->buf.payload_size;
52  ASSERT(buf_safe(buf, 0));
53 }
54 
55 unsigned int
56 calc_packet_id_size_dc(const struct options *options, const struct key_type *kt)
57 {
58  /* Unless no-replay is enabled, we have a packet id, no matter if
59  * encryption is used or not */
60  if (!options->replay)
61  {
62  return 0;
63  }
64 
65  bool tlsmode = options->tls_server || options->tls_client;
66 
67  bool packet_id_long_form = !tlsmode || cipher_kt_mode_ofb_cfb(kt->cipher);
68 
69  return packet_id_size(packet_id_long_form);
70 }
71 
72 size_t
74  const struct options *options,
75  bool occ)
76 {
77  /* Sum of all the overhead that reduces the usable packet size */
78  size_t header_size = 0;
79 
80  bool tlsmode = options->tls_server || options->tls_client;
81 
82  /* A socks proxy adds 10 byte of extra header to each packet
83  * (we only support Socks with IPv4, this value is different for IPv6) */
85  {
86  header_size += 10;
87  }
88 
89  /* TCP stream based packets have a 16 bit length field */
91  {
92  header_size += 2;
93  }
94 
95  /* Add the opcode and peerid */
96  if (tlsmode)
97  {
98  header_size += options->use_peer_id ? 4 : 1;
99  }
100 
101  unsigned int pkt_id_size = calc_packet_id_size_dc(options, kt);
102 
103  /* For figuring out the crypto overhead, we need the size of the payload
104  * including all headers that also get encrypted as part of the payload */
105  header_size += calculate_crypto_overhead(kt, pkt_id_size, occ);
106  return header_size;
107 }
108 
109 
110 size_t
112  const struct options *options,
113  const struct key_type *kt,
114  bool extra_tun)
115 {
116  size_t overhead = 0;
117 
118  /* This is the overhead of tap device that is not included in the MTU itself
119  * i.e. Ethernet header that we still need to transmit as part of the
120  * payload */
121  if (extra_tun)
122  {
123  overhead += frame->extra_tun;
124  }
125 
126 #if defined(USE_COMP)
127  /* v1 Compression schemes add 1 byte header. V2 only adds a header when it
128  * does not increase the packet length. We ignore the unlikely escaping
129  * for tap here */
130  if (options->comp.alg == COMP_ALG_LZ4 || options->comp.alg == COMP_ALG_STUB
131  || options->comp.alg == COMP_ALG_LZO)
132  {
133  overhead += 1;
134  }
135 #endif
136 #if defined(ENABLE_FRAGMENT)
137  /* Add the size of the fragment header (uint32_t) */
138  if (options->ce.fragment)
139  {
140  overhead += 4;
141  }
142 #endif
143 
144  if (cipher_kt_mode_cbc(kt->cipher))
145  {
146  /* The packet id is part of the plain text payload instead of the
147  * cleartext protocol header and needs to be included in the payload
148  * overhead instead of the protocol header */
149  overhead += calc_packet_id_size_dc(options, kt);
150  }
151 
152  return overhead;
153 }
154 
155 size_t
157  const struct options *options,
158  const struct key_type *kt)
159 {
160  size_t payload_size = options->ce.tun_mtu;
161  payload_size += frame_calculate_payload_overhead(frame, options, kt, true);
162  return payload_size;
163 }
164 
165 size_t
166 calc_options_string_link_mtu(const struct options *o, const struct frame *frame)
167 {
168  struct key_type occ_kt;
169 
170  /* neither --secret nor TLS mode */
171  if (!o->tls_client && !o->tls_server && !o->shared_secret_file)
172  {
173  init_key_type(&occ_kt, "none", "none", false, false);
174  return frame_calculate_payload_size(frame, o, &occ_kt);
175  }
176 
177  /* o->ciphername might be BF-CBC even though the underlying SSL library
178  * does not support it. For this reason we workaround this corner case
179  * by pretending to have no encryption enabled and by manually adding
180  * the required packet overhead to the MTU computation.
181  */
182  const char *ciphername = o->ciphername;
183 
184  unsigned int overhead = 0;
185 
186  if (strcmp(o->ciphername, "BF-CBC") == 0)
187  {
188  /* none has no overhead, so use this to later add only --auth
189  * overhead */
190 
191  /* overhead of BF-CBC: 64 bit block size, 64 bit IV size */
192  overhead += 64/8 + 64/8;
193  /* set ciphername to none, so its size does get added in the
194  * fake_kt and the cipher is not tried to be resolved */
195  ciphername = "none";
196  }
197 
198  /* We pass tlsmode always true here since as we do not need to check if
199  * the ciphers are actually valid for non tls in occ calucation */
200  init_key_type(&occ_kt, ciphername, o->authname, true, false);
201 
202  unsigned int payload = frame_calculate_payload_size(frame, o, &occ_kt);
203  overhead += frame_calculate_protocol_header_size(&occ_kt, o, true);
204 
205  return payload + overhead;
206 }
207 
208 void
209 frame_print(const struct frame *frame,
210  int level,
211  const char *prefix)
212 {
213  struct gc_arena gc = gc_new();
214  struct buffer out = alloc_buf_gc(256, &gc);
215  if (prefix)
216  {
217  buf_printf(&out, "%s ", prefix);
218  }
219  buf_printf(&out, "[");
220  buf_printf(&out, " mss_fix:%d", frame->mss_fix);
221 #ifdef ENABLE_FRAGMENT
222  buf_printf(&out, " max_frag:%d", frame->max_fragment_size);
223 #endif
224  buf_printf(&out, " tun_mtu:%d", frame->tun_mtu);
225  buf_printf(&out, " tun_max_mtu:%d", frame->tun_max_mtu);
226  buf_printf(&out, " headroom:%d", frame->buf.headroom);
227  buf_printf(&out, " payload:%d", frame->buf.payload_size);
228  buf_printf(&out, " tailroom:%d", frame->buf.tailroom);
229  buf_printf(&out, " ET:%d", frame->extra_tun);
230  buf_printf(&out, " ]");
231 
232  msg(level, "%s", out.data);
233  gc_free(&gc);
234 }
235 
236 #define MTUDISC_NOT_SUPPORTED_MSG "--mtu-disc is not supported on this OS"
237 
238 void
240 {
241  if (mtu_type >= 0)
242  {
243  switch (proto_af)
244  {
245 #if defined(IP_MTU_DISCOVER)
246  case AF_INET:
247  if (setsockopt(sd, IPPROTO_IP, IP_MTU_DISCOVER,
248  (void *) &mtu_type, sizeof(mtu_type)))
249  {
250  msg(M_ERR, "Error setting IP_MTU_DISCOVER type=%d on TCP/UDP socket",
251  mtu_type);
252  }
253  break;
254 
255 #endif
256 #if defined(IPV6_MTU_DISCOVER)
257  case AF_INET6:
258  if (setsockopt(sd, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
259  (void *) &mtu_type, sizeof(mtu_type)))
260  {
261  msg(M_ERR, "Error setting IPV6_MTU_DISCOVER type=%d on TCP6/UDP6 socket",
262  mtu_type);
263  }
264  break;
265 
266 #endif
267  default:
269  break;
270  }
271  }
272 }
273 
274 int
276 {
277 #if defined(IP_PMTUDISC_DONT) && defined(IP_PMTUDISC_WANT) && defined(IP_PMTUDISC_DO)
278  if (!strcmp(name, "yes"))
279  {
280  return IP_PMTUDISC_DO;
281  }
282  if (!strcmp(name, "maybe"))
283  {
284  return IP_PMTUDISC_WANT;
285  }
286  if (!strcmp(name, "no"))
287  {
288  return IP_PMTUDISC_DONT;
289  }
290  msg(M_FATAL,
291  "invalid --mtu-disc type: '%s' -- valid types are 'yes', 'maybe', or 'no'",
292  name);
293 #else /* if defined(IP_PMTUDISC_DONT) && defined(IP_PMTUDISC_WANT) && defined(IP_PMTUDISC_DO) */
295 #endif
296  return -1; /* NOTREACHED */
297 }
298 
299 #if EXTENDED_SOCKET_ERROR_CAPABILITY
300 
301 struct probehdr
302 {
303  uint32_t ttl;
304  struct timeval tv;
305 };
306 
307 const char *
308 format_extended_socket_error(int fd, int *mtu, struct gc_arena *gc)
309 {
310  int res;
311  struct probehdr rcvbuf;
312  struct iovec iov;
313  struct msghdr msg;
314  struct cmsghdr *cmsg;
315  struct sock_extended_err *e;
316  struct sockaddr_storage addr;
317  struct buffer out = alloc_buf_gc(256, gc);
318  char *cbuf = (char *) gc_malloc(256, false, gc);
319 
320  *mtu = 0;
321 
322  while (true)
323  {
324  memset(&rcvbuf, -1, sizeof(rcvbuf));
325  iov.iov_base = &rcvbuf;
326  iov.iov_len = sizeof(rcvbuf);
327  msg.msg_name = (uint8_t *) &addr;
328  msg.msg_namelen = sizeof(addr);
329  msg.msg_iov = &iov;
330  msg.msg_iovlen = 1;
331  msg.msg_flags = 0;
332  msg.msg_control = cbuf;
333  msg.msg_controllen = 256; /* size of cbuf */
334 
335  res = recvmsg(fd, &msg, MSG_ERRQUEUE);
336  if (res < 0)
337  {
338  goto exit;
339  }
340 
341  e = NULL;
342 
343  for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
344  {
345  if (cmsg->cmsg_level == SOL_IP)
346  {
347  if (cmsg->cmsg_type == IP_RECVERR)
348  {
349  e = (struct sock_extended_err *) CMSG_DATA(cmsg);
350  }
351  else
352  {
353  buf_printf(&out, "CMSG=%d|", cmsg->cmsg_type);
354  }
355  }
356  else if (cmsg->cmsg_level == IPPROTO_IPV6)
357  {
358  if (cmsg->cmsg_type == IPV6_RECVERR)
359  {
360  e = (struct sock_extended_err *) CMSG_DATA(cmsg);
361  }
362  else
363  {
364  buf_printf(&out, "CMSG=%d|", cmsg->cmsg_type);
365  }
366  }
367  }
368  if (e == NULL)
369  {
370  buf_printf(&out, "NO-INFO|");
371  goto exit;
372  }
373 
374  switch (e->ee_errno)
375  {
376  case ETIMEDOUT:
377  buf_printf(&out, "ETIMEDOUT|");
378  break;
379 
380  case EMSGSIZE:
381  buf_printf(&out, "EMSGSIZE Path-MTU=%d|", e->ee_info);
382  *mtu = e->ee_info;
383  break;
384 
385  case ECONNREFUSED:
386  buf_printf(&out, "ECONNREFUSED|");
387  break;
388 
389  case EPROTO:
390  buf_printf(&out, "EPROTO|");
391  break;
392 
393  case EHOSTUNREACH:
394  buf_printf(&out, "EHOSTUNREACH|");
395  break;
396 
397  case ENETUNREACH:
398  buf_printf(&out, "ENETUNREACH|");
399  break;
400 
401  case EACCES:
402  buf_printf(&out, "EACCES|");
403  break;
404 
405  default:
406  buf_printf(&out, "UNKNOWN|");
407  break;
408  }
409  }
410 
411 exit:
412  buf_rmtail(&out, '|');
413  return BSTR(&out);
414 }
415 
416 void
417 set_sock_extended_error_passing(int sd, sa_family_t proto_af)
418 {
419  int on = 1;
420  /* see "man 7 ip" (on Linux)
421  * this works on IPv4 and IPv6(-dual-stack) sockets (v4-mapped)
422  */
423  if (setsockopt(sd, SOL_IP, IP_RECVERR, (void *) &on, sizeof(on)) != 0)
424  {
425  msg(M_WARN | M_ERRNO,
426  "Note: enable extended error passing on TCP/UDP socket failed (IP_RECVERR)");
427  }
428  /* see "man 7 ipv6" (on Linux)
429  * this only works on IPv6 sockets
430  */
431  if (proto_af == AF_INET6
432  && setsockopt(sd, IPPROTO_IPV6, IPV6_RECVERR, (void *) &on, sizeof(on)) != 0)
433  {
434  msg(M_WARN | M_ERRNO,
435  "Note: enable extended error passing on TCP/UDP socket failed (IPV6_RECVERR)");
436  }
437 }
438 
439 #endif /* if EXTENDED_SOCKET_ERROR_CAPABILITY */
buf_safe
static bool buf_safe(const struct buffer *buf, size_t len)
Definition: buffer.h:525
frame::mss_fix
unsigned int mss_fix
The actual MSS value that should be written to the payload packets.
Definition: mtu.h:118
buf_rmtail
void buf_rmtail(struct buffer *buf, uint8_t remove)
Definition: buffer.c:531
options::use_peer_id
bool use_peer_id
Definition: options.h:678
error.h
gc_new
static struct gc_arena gc_new(void)
Definition: buffer.h:998
M_ERRNO
#define M_ERRNO
Definition: error.h:100
buffer::len
int len
Length in bytes of the actual content within the allocated memory.
Definition: buffer.h:66
frame_print
void frame_print(const struct frame *frame, int level, const char *prefix)
Definition: mtu.c:209
connection_entry::socks_proxy_server
const char * socks_proxy_server
Definition: options.h:116
M_FATAL
#define M_FATAL
Definition: error.h:95
frame_calculate_payload_size
size_t frame_calculate_payload_size(const struct frame *frame, const struct options *options, const struct key_type *kt)
Calculates the size of the payload according to tun-mtu and tap overhead.
Definition: mtu.c:156
buf_init
#define buf_init(buf, offset)
Definition: buffer.h:196
BSTR
#define BSTR(buf)
Definition: buffer.h:129
options::authname
const char * authname
Definition: options.h:555
options::tls_client
bool tls_client
Definition: options.h:570
options::shared_secret_file
const char * shared_secret_file
Definition: options.h:548
alloc_buf_gc
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:90
config-msvc.h
frame::tailroom
int tailroom
the tailroom in the buffer.
Definition: mtu.h:112
frame::buf
struct frame::@5 buf
options::ce
struct connection_entry ce
Definition: options.h:275
frame_calculate_protocol_header_size
size_t frame_calculate_protocol_header_size(const struct key_type *kt, const struct options *options, bool occ)
Calculates the size of the OpenVPN protocol header.
Definition: mtu.c:73
options.h
frame
Packet geometry parameters.
Definition: mtu.h:98
options::tls_server
bool tls_server
Definition: options.h:569
translate_mtu_discover_type_name
int translate_mtu_discover_type_name(const char *name)
Definition: mtu.c:275
sa_family_t
unsigned short sa_family_t
Definition: syshead.h:402
mtu.h
ASSERT
#define ASSERT(x)
Definition: error.h:201
frame::extra_tun
int extra_tun
Maximum number of bytes in excess of the tun/tap MTU that might be read from or written to the virtua...
Definition: mtu.h:145
frame::payload_size
int payload_size
the maximum size that a payload that our buffers can hold from either tun device or network link.
Definition: mtu.h:102
calc_options_string_link_mtu
size_t calc_options_string_link_mtu(const struct options *o, const struct frame *frame)
Calculate the link-mtu to advertise to our peer.
Definition: mtu.c:166
M_WARN
#define M_WARN
Definition: error.h:97
options
Definition: options.h:236
crypto.h
M_ERR
#define M_ERR
Definition: error.h:111
buffer
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
proto_is_udp
static bool proto_is_udp(int proto)
Returns if the protocol being used is UDP.
Definition: socket.h:573
MTUDISC_NOT_SUPPORTED_MSG
#define MTUDISC_NOT_SUPPORTED_MSG
Definition: mtu.c:236
key_type
Definition: crypto.h:139
frame::max_fragment_size
int max_fragment_size
The maximum size of a fragment.
Definition: mtu.h:124
buffer.h
syshead.h
cipher_kt_mode_ofb_cfb
bool cipher_kt_mode_ofb_cfb(const char *ciphername)
Check if the supplied cipher is a supported OFB or CFB mode cipher.
Definition: crypto_openssl.c:768
gc_arena
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
alloc_buf_sock_tun
void alloc_buf_sock_tun(struct buffer *buf, const struct frame *frame, const bool tuntap_buffer)
Definition: mtu.c:44
key_type::cipher
const char * cipher
const name of the cipher
Definition: crypto.h:141
options::replay
bool replay
Definition: options.h:558
socket_descriptor_t
SOCKET socket_descriptor_t
Definition: syshead.h:445
common.h
gc_malloc
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition: buffer.c:382
set_mtu_discover_type
void set_mtu_discover_type(socket_descriptor_t sd, int mtu_type, sa_family_t proto_af)
Definition: mtu.c:239
packet_id_size
static int packet_id_size(bool long_form)
Definition: packet_id.h:310
gc_free
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1006
BUF_SIZE
#define BUF_SIZE(f)
Definition: mtu.h:172
frame::tun_max_mtu
int tun_max_mtu
the maximum tun-mtu size the buffers are are sized for.
Definition: mtu.h:141
calc_packet_id_size_dc
unsigned int calc_packet_id_size_dc(const struct options *options, const struct key_type *kt)
Return the size of the packet ID size that is currently in use by cipher and options for the data cha...
Definition: mtu.c:56
cipher_kt_mode_cbc
bool cipher_kt_mode_cbc(const char *ciphername)
Check if the supplied cipher is a supported CBC mode cipher.
Definition: crypto_openssl.c:753
proto_is_tcp
static bool proto_is_tcp(int proto)
returns if the proto is a TCP variant (tcp-server, tcp-client or tcp)
Definition: socket.h:593
SOL_IP
#define SOL_IP
Definition: syshead.h:395
config.h
connection_entry::fragment
int fragment
Definition: options.h:134
frame_calculate_payload_overhead
size_t frame_calculate_payload_overhead(const struct frame *frame, const struct options *options, const struct key_type *kt, bool extra_tun)
Calculates the size of the payload overhead according to tun-mtu and tap overhead.
Definition: mtu.c:111
calculate_crypto_overhead
unsigned int calculate_crypto_overhead(const struct key_type *kt, unsigned int pkt_id_size, bool occ)
Calculate the maximum overhead that our encryption has on a packet.
Definition: crypto.c:671
connection_entry::proto
int proto
Definition: options.h:101
init_key_type
void init_key_type(struct key_type *kt, const char *ciphername, const char *authname, bool tls_mode, bool warn)
Initialize a key_type structure with.
Definition: crypto.c:745
alloc_buf
struct buffer alloc_buf(size_t size)
Definition: buffer.c:64
connection_entry::tun_mtu
int tun_mtu
Definition: options.h:120
memdbg.h
options::ciphername
const char * ciphername
Definition: options.h:551
msg
#define msg(flags,...)
Definition: error.h:150
frame::tun_mtu
int tun_mtu
the (user) configured tun-mtu.
Definition: mtu.h:131
integer.h
buf_printf
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:242
frame::headroom
int headroom
the headroom in the buffer, this is choosen to allow all potential header to be added before the pack...
Definition: mtu.h:108
buffer::data
uint8_t * data
Pointer to the allocated memory.
Definition: buffer.h:68