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-2010 OpenVPN Technologies, 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
20 *  along with this program (see the file COPYING included with this
21 *  distribution); if not, write to the Free Software Foundation, Inc.,
22 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25#ifndef MTU_H
26#define MTU_H
27
28#include "buffer.h"
29
30/*
31 *
32 * Packet maninipulation routes such as encrypt, decrypt, compress, decompress
33 * are passed a frame buffer that looks like this:
34 *
35 *    [extra_frame bytes] [mtu bytes] [extra_frame_bytes] [compression overflow bytes]
36 *                         ^
37 *                   Pointer passed to function points here so that routine
38 *                   can make use of extra_frame bytes before pointer
39 *                   to prepend headers, etc.
40 *
41 *    extra_frame bytes is large enough for all encryption related overhead.
42 *
43 *    mtu bytes will be the MTU size set in the ifconfig statement that configures
44 *      the TUN or TAP device such as:
45 *
46 *      ifconfig $1 10.1.0.2 pointopoint 10.1.0.1 mtu 1450
47 *
48 *    Compression overflow bytes is the worst-case size expansion that would be
49 *    expected if we tried to compress mtu + extra_frame bytes of uncompressible data.
50 */
51
52/*
53 * Standard ethernet MTU
54 */
55#define ETHERNET_MTU       1500
56
57/*
58 * It is a fatal error if mtu is less than
59 * this value for tun device.
60 */
61#define TUN_MTU_MIN        100
62
63/*
64 * Default MTU of network over which tunnel data will pass by TCP/UDP.
65 */
66#define LINK_MTU_DEFAULT   1500
67
68/*
69 * Default MTU of tunnel device.
70 */
71#define TUN_MTU_DEFAULT    1500
72
73/*
74 * MTU Defaults for TAP devices
75 */
76#define TAP_MTU_EXTRA_DEFAULT  32
77
78/*
79 * Default MSSFIX value, used for reducing TCP MTU size
80 */
81#define MSSFIX_DEFAULT     1450
82
83/*
84 * Alignment of payload data such as IP packet or
85 * ethernet frame.
86 */
87#define PAYLOAD_ALIGN 4
88
89
90/**************************************************************************/
91/**
92 * Packet geometry parameters.
93 */
94struct frame {
95  int link_mtu;                 /**< Maximum packet size to be sent over
96                                 *   the external network interface. */
97
98  int link_mtu_dynamic;         /**< Dynamic MTU value for the external
99                                 *   network interface. */
100
101  int extra_frame;              /**< Maximum number of bytes that all
102                                 *   processing steps together could add.
103                                 *   @code
104                                 *   frame.link_mtu = "socket MTU" - extra_frame;
105                                 *   @endcode
106                                 */
107
108  int extra_buffer;             /**< Maximum number of bytes that
109                                 *   processing steps could expand the
110                                 *   internal work buffer.
111                                 *
112                                 *   This is used by the \link compression
113                                 *   Data Channel Compression
114                                 *   module\endlink to give enough working
115                                 *   space for worst-case expansion of
116                                 *   incompressible content. */
117
118  int extra_tun;                /**< Maximum number of bytes in excess of
119                                 *   the tun/tap MTU that might be read
120                                 *   from or written to the virtual
121                                 *   tun/tap network interface. */
122
123  int extra_link;               /**< Maximum number of bytes in excess of
124                                 *   external network interface's MTU that
125                                 *   might be read from or written to it. */
126
127  /*
128   * Alignment control
129   */
130# define FRAME_HEADROOM_MARKER_DECRYPT     (1<<0)
131# define FRAME_HEADROOM_MARKER_FRAGMENT    (1<<1)
132# define FRAME_HEADROOM_MARKER_READ_LINK   (1<<2)
133# define FRAME_HEADROOM_MARKER_READ_STREAM (1<<3)
134  unsigned int align_flags;
135  int align_adjust;
136};
137
138/* Routines which read struct frame should use the macros below */
139
140/*
141 * Overhead added to packet payload due to encapsulation
142 */
143#define EXTRA_FRAME(f)           ((f)->extra_frame)
144
145/*
146 * Delta between tun payload size and final TCP/UDP datagram size
147 * (not including extra_link additions)
148 */
149#define TUN_LINK_DELTA(f)        ((f)->extra_frame + (f)->extra_tun)
150
151/*
152 * This is the size to "ifconfig" the tun or tap device.
153 */
154#define TUN_MTU_SIZE(f)          ((f)->link_mtu - TUN_LINK_DELTA(f))
155#define TUN_MTU_SIZE_DYNAMIC(f)  ((f)->link_mtu_dynamic - TUN_LINK_DELTA(f))
156
157/*
158 * This is the maximum packet size that we need to be able to
159 * read from or write to a tun or tap device.  For example,
160 * a tap device ifconfiged to an MTU of 1200 might actually want
161 * to return a packet size of 1214 on a read().
162 */
163#define PAYLOAD_SIZE(f)          ((f)->link_mtu - (f)->extra_frame)
164#define PAYLOAD_SIZE_DYNAMIC(f)  ((f)->link_mtu_dynamic - (f)->extra_frame)
165
166/*
167 * Max size of a payload packet after encryption, compression, etc.
168 * overhead is added.
169 */
170#define EXPANDED_SIZE(f)         ((f)->link_mtu)
171#define EXPANDED_SIZE_DYNAMIC(f) ((f)->link_mtu_dynamic)
172#define EXPANDED_SIZE_MIN(f)     (TUN_MTU_MIN + TUN_LINK_DELTA(f))
173
174/*
175 * These values are used as maximum size constraints
176 * on read() or write() from TUN/TAP device or TCP/UDP port.
177 */
178#define MAX_RW_SIZE_TUN(f)       (PAYLOAD_SIZE(f))
179#define MAX_RW_SIZE_LINK(f)      (EXPANDED_SIZE(f) + (f)->extra_link)
180
181/*
182 * Control buffer headroom allocations to allow for efficient prepending.
183 */
184#define FRAME_HEADROOM_BASE(f)     (TUN_LINK_DELTA(f) + (f)->extra_buffer + (f)->extra_link)
185#define FRAME_HEADROOM(f)          frame_headroom(f, 0)
186#define FRAME_HEADROOM_ADJ(f, fm)  frame_headroom(f, fm)
187
188/*
189 * Max size of a buffer used to build a packet for output to
190 * the TCP/UDP port.
191 */
192#define BUF_SIZE(f)              (TUN_MTU_SIZE(f) + FRAME_HEADROOM_BASE(f) * 2)
193
194/*
195 * Function prototypes.
196 */
197
198void frame_finalize (struct frame *frame,
199		     bool link_mtu_defined,
200		     int link_mtu,
201		     bool tun_mtu_defined,
202		     int tun_mtu);
203
204void frame_subtract_extra (struct frame *frame, const struct frame *src);
205
206void frame_print (const struct frame *frame,
207		  int level,
208		  const char *prefix);
209
210void set_mtu_discover_type (int sd, int mtu_type);
211int translate_mtu_discover_type_name (const char *name);
212
213/*
214 * frame_set_mtu_dynamic and flags
215 */
216
217#define SET_MTU_TUN         (1<<0) /* use tun/tap rather than link sizing */
218#define SET_MTU_UPPER_BOUND (1<<1) /* only decrease dynamic MTU */
219
220void frame_set_mtu_dynamic (struct frame *frame, int mtu, unsigned int flags);
221
222/*
223 * allocate a buffer for socket or tun layer
224 */
225void alloc_buf_sock_tun (struct buffer *buf,
226			 const struct frame *frame,
227			 const bool tuntap_buffer,
228			 const unsigned int align_mask);
229
230/*
231 * EXTENDED_SOCKET_ERROR_CAPABILITY functions -- print extra error info
232 * on socket errors, such as PMTU size.  As of 2003.05.11, only works
233 * on Linux 2.4+.
234 */
235
236#if EXTENDED_SOCKET_ERROR_CAPABILITY
237
238void set_sock_extended_error_passing (int sd);
239const char *format_extended_socket_error (int fd, int *mtu, struct gc_arena *gc);
240
241#endif
242
243/*
244 * Calculate a starting offset into a buffer object, dealing with
245 * headroom and alignment issues.
246 */
247static inline int
248frame_headroom (const struct frame *f, const unsigned int flag_mask)
249{
250  const int offset = FRAME_HEADROOM_BASE (f);
251  const int adjust = (flag_mask & f->align_flags) ? f->align_adjust : 0;
252  const int delta = ((PAYLOAD_ALIGN << 24) - (offset + adjust)) & (PAYLOAD_ALIGN - 1);
253  return offset + delta;
254}
255
256/*
257 * frame member adjustment functions
258 */
259
260static inline void
261frame_add_to_extra_frame (struct frame *frame, const int increment)
262{
263  frame->extra_frame += increment;
264}
265
266static inline void
267frame_add_to_extra_tun (struct frame *frame, const int increment)
268{
269  frame->extra_tun += increment;
270}
271
272static inline void
273frame_add_to_extra_link (struct frame *frame, const int increment)
274{
275  frame->extra_link += increment;
276}
277
278static inline void
279frame_add_to_extra_buffer (struct frame *frame, const int increment)
280{
281  frame->extra_buffer += increment;
282}
283
284static inline void
285frame_add_to_align_adjust (struct frame *frame, const int increment)
286{
287  frame->align_adjust += increment;
288}
289
290static inline void
291frame_align_to_extra_frame (struct frame *frame)
292{
293  frame->align_adjust = frame->extra_frame + frame->extra_link;
294}
295
296static inline void
297frame_or_align_flags (struct frame *frame, const unsigned int flag_mask)
298{
299  frame->align_flags |= flag_mask;
300}
301
302static inline bool
303frame_defined (const struct frame *frame)
304{
305  return frame->link_mtu > 0;
306}
307
308#endif
309