~ubuntu-branches/ubuntu/saucy/openvpn/saucy-proposed

« back to all changes in this revision

Viewing changes to mtu.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2013-05-24 17:42:45 UTC
  • mfrom: (1.1.19) (10.2.22 sid)
  • Revision ID: package-import@ubuntu.com-20130524174245-g9y6wlforycufqy5
Tags: 2.3.1-2ubuntu1
* Merge from Debian unstable. Remaining changes:
  - debian/openvpn.init.d:
    + Do not use start-stop-daemon and </dev/null to avoid blocking boot.
    + Show per-VPN result messages.
    + Add "--script-security 2" by default for backwards compatabliity.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
#include "syshead.h"
26
 
 
27
 
#include "common.h"
28
 
#include "buffer.h"
29
 
#include "error.h"
30
 
#include "integer.h"
31
 
#include "mtu.h"
32
 
 
33
 
#include "memdbg.h"
34
 
 
35
 
/* allocate a buffer for socket or tun layer */
36
 
void
37
 
alloc_buf_sock_tun (struct buffer *buf,
38
 
                    const struct frame *frame,
39
 
                    const bool tuntap_buffer,
40
 
                    const unsigned int align_mask)
41
 
{
42
 
  /* allocate buffer for overlapped I/O */
43
 
  *buf = alloc_buf (BUF_SIZE (frame));
44
 
  ASSERT (buf_init (buf, FRAME_HEADROOM_ADJ (frame, align_mask)));
45
 
  buf->len = tuntap_buffer ? MAX_RW_SIZE_TUN (frame) : MAX_RW_SIZE_LINK (frame);
46
 
  ASSERT (buf_safe (buf, 0));
47
 
}
48
 
 
49
 
void
50
 
frame_finalize (struct frame *frame,
51
 
                bool link_mtu_defined,
52
 
                int link_mtu,
53
 
                bool tun_mtu_defined,
54
 
                int tun_mtu)
55
 
{
56
 
  /* Set link_mtu based on command line options */
57
 
  if (tun_mtu_defined)
58
 
    {
59
 
      ASSERT (!link_mtu_defined);
60
 
      frame->link_mtu = tun_mtu + TUN_LINK_DELTA (frame);
61
 
    }
62
 
  else
63
 
    {
64
 
      ASSERT (link_mtu_defined);
65
 
      frame->link_mtu = link_mtu;
66
 
    }
67
 
 
68
 
  if (TUN_MTU_SIZE (frame) < TUN_MTU_MIN)
69
 
    {
70
 
      msg (M_WARN, "TUN MTU value (%d) must be at least %d", TUN_MTU_SIZE (frame), TUN_MTU_MIN);
71
 
      frame_print (frame, M_FATAL, "MTU is too small");
72
 
    }
73
 
 
74
 
  frame->link_mtu_dynamic = frame->link_mtu;
75
 
 
76
 
  frame->extra_buffer += PAYLOAD_ALIGN;
77
 
}
78
 
 
79
 
/*
80
 
 * Set the tun MTU dynamically.
81
 
 */
82
 
void
83
 
frame_set_mtu_dynamic (struct frame *frame, int mtu, unsigned int flags)
84
 
{
85
 
 
86
 
#ifdef ENABLE_DEBUG
87
 
  const int orig_mtu = mtu;
88
 
  const int orig_link_mtu_dynamic = frame->link_mtu_dynamic;
89
 
#endif
90
 
 
91
 
  ASSERT (mtu >= 0);
92
 
 
93
 
  if (flags & SET_MTU_TUN)
94
 
    mtu += TUN_LINK_DELTA (frame);
95
 
 
96
 
  if (!(flags & SET_MTU_UPPER_BOUND) || mtu < frame->link_mtu_dynamic)
97
 
    {
98
 
      frame->link_mtu_dynamic = constrain_int (
99
 
        mtu,
100
 
        EXPANDED_SIZE_MIN (frame),
101
 
        EXPANDED_SIZE (frame));
102
 
    }
103
 
 
104
 
  dmsg (D_MTU_DEBUG, "MTU DYNAMIC mtu=%d, flags=%u, %d -> %d",
105
 
       orig_mtu,
106
 
       flags,
107
 
       orig_link_mtu_dynamic,
108
 
       frame->link_mtu_dynamic);
109
 
}
110
 
 
111
 
/*
112
 
 * Move extra_frame octets into extra_tun.  Used by fragmenting code
113
 
 * to adjust frame relative to its position in the buffer processing
114
 
 * queue.
115
 
 */
116
 
void
117
 
frame_subtract_extra (struct frame *frame, const struct frame *src)
118
 
{
119
 
  frame->extra_frame -= src->extra_frame;
120
 
  frame->extra_tun   += src->extra_frame;
121
 
}
122
 
 
123
 
void
124
 
frame_print (const struct frame *frame,
125
 
             int level,
126
 
             const char *prefix)
127
 
{
128
 
  struct gc_arena gc = gc_new ();
129
 
  struct buffer out = alloc_buf_gc (256, &gc);
130
 
  if (prefix)
131
 
    buf_printf (&out, "%s ", prefix);
132
 
  buf_printf (&out, "[");
133
 
  buf_printf (&out, " L:%d", frame->link_mtu);
134
 
  buf_printf (&out, " D:%d", frame->link_mtu_dynamic);
135
 
  buf_printf (&out, " EF:%d", frame->extra_frame);
136
 
  buf_printf (&out, " EB:%d", frame->extra_buffer);
137
 
  buf_printf (&out, " ET:%d", frame->extra_tun);
138
 
  buf_printf (&out, " EL:%d", frame->extra_link);
139
 
  if (frame->align_flags && frame->align_adjust)
140
 
    buf_printf (&out, " AF:%u/%d", frame->align_flags, frame->align_adjust);
141
 
  buf_printf (&out, " ]");
142
 
 
143
 
  msg (level, "%s", out.data);
144
 
  gc_free (&gc);
145
 
}
146
 
 
147
 
#define MTUDISC_NOT_SUPPORTED_MSG "--mtu-disc is not supported on this OS"
148
 
 
149
 
void
150
 
set_mtu_discover_type (int sd, int mtu_type)
151
 
{
152
 
  if (mtu_type >= 0)
153
 
    {
154
 
#if defined(HAVE_SETSOCKOPT) && defined(SOL_IP) && defined(IP_MTU_DISCOVER)
155
 
      if (setsockopt
156
 
          (sd, SOL_IP, IP_MTU_DISCOVER, &mtu_type, sizeof (mtu_type)))
157
 
        msg (M_ERR, "Error setting IP_MTU_DISCOVER type=%d on TCP/UDP socket",
158
 
             mtu_type);
159
 
#else
160
 
      msg (M_FATAL, MTUDISC_NOT_SUPPORTED_MSG);
161
 
#endif
162
 
    }
163
 
}
164
 
 
165
 
int
166
 
translate_mtu_discover_type_name (const char *name)
167
 
{
168
 
#if defined(IP_PMTUDISC_DONT) && defined(IP_PMTUDISC_WANT) && defined(IP_PMTUDISC_DO)
169
 
  if (!strcmp (name, "yes"))
170
 
    return IP_PMTUDISC_DO;
171
 
  if (!strcmp (name, "maybe"))
172
 
    return IP_PMTUDISC_WANT;
173
 
  if (!strcmp (name, "no"))
174
 
    return IP_PMTUDISC_DONT;
175
 
  msg (M_FATAL,
176
 
       "invalid --mtu-disc type: '%s' -- valid types are 'yes', 'maybe', or 'no'",
177
 
       name);
178
 
#else
179
 
  msg (M_FATAL, MTUDISC_NOT_SUPPORTED_MSG);
180
 
#endif
181
 
  return -1;                    /* NOTREACHED */
182
 
}
183
 
 
184
 
#if EXTENDED_SOCKET_ERROR_CAPABILITY
185
 
 
186
 
struct probehdr
187
 
{
188
 
  uint32_t ttl;
189
 
  struct timeval tv;
190
 
};
191
 
 
192
 
const char *
193
 
format_extended_socket_error (int fd, int *mtu, struct gc_arena *gc)
194
 
{
195
 
  int res;
196
 
  struct probehdr rcvbuf;
197
 
  struct iovec iov;
198
 
  struct msghdr msg;
199
 
  struct cmsghdr *cmsg;
200
 
  struct sock_extended_err *e;
201
 
  struct sockaddr_in addr;
202
 
  struct buffer out = alloc_buf_gc (256, gc);
203
 
  char *cbuf = (char *) gc_malloc (256, false, gc);
204
 
 
205
 
  *mtu = 0;
206
 
 
207
 
  while (true)
208
 
    {
209
 
      memset (&rcvbuf, -1, sizeof (rcvbuf));
210
 
      iov.iov_base = &rcvbuf;
211
 
      iov.iov_len = sizeof (rcvbuf);
212
 
      msg.msg_name = (uint8_t *) &addr;
213
 
      msg.msg_namelen = sizeof (addr);
214
 
      msg.msg_iov = &iov;
215
 
      msg.msg_iovlen = 1;
216
 
      msg.msg_flags = 0;
217
 
      msg.msg_control = cbuf;
218
 
      msg.msg_controllen = 256; /* size of cbuf */
219
 
 
220
 
      res = recvmsg (fd, &msg, MSG_ERRQUEUE);
221
 
      if (res < 0)
222
 
        goto exit;
223
 
 
224
 
      e = NULL;
225
 
 
226
 
      for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
227
 
        {
228
 
          if (cmsg->cmsg_level == SOL_IP)
229
 
            {
230
 
              if (cmsg->cmsg_type == IP_RECVERR)
231
 
                {
232
 
                  e = (struct sock_extended_err *) CMSG_DATA (cmsg);
233
 
                }
234
 
              else
235
 
                {
236
 
                  buf_printf (&out ,"CMSG=%d|", cmsg->cmsg_type);
237
 
                }
238
 
            }
239
 
        }
240
 
      if (e == NULL)
241
 
        {
242
 
          buf_printf (&out, "NO-INFO|");
243
 
          goto exit;
244
 
        }
245
 
 
246
 
      switch (e->ee_errno)
247
 
        {
248
 
        case ETIMEDOUT:
249
 
          buf_printf (&out, "ETIMEDOUT|");
250
 
          break;
251
 
        case EMSGSIZE:
252
 
          buf_printf (&out, "EMSGSIZE Path-MTU=%d|", e->ee_info);
253
 
          *mtu = e->ee_info;
254
 
          break;
255
 
        case ECONNREFUSED:
256
 
          buf_printf (&out, "ECONNREFUSED|");
257
 
          break;
258
 
        case EPROTO:
259
 
          buf_printf (&out, "EPROTO|");
260
 
          break;
261
 
        case EHOSTUNREACH:
262
 
          buf_printf (&out, "EHOSTUNREACH|");
263
 
          break;
264
 
        case ENETUNREACH:
265
 
          buf_printf (&out, "ENETUNREACH|");
266
 
          break;
267
 
        case EACCES:
268
 
          buf_printf (&out, "EACCES|");
269
 
          break;
270
 
        default:
271
 
          buf_printf (&out, "UNKNOWN|");
272
 
          break;
273
 
        }
274
 
    }
275
 
 
276
 
 exit:
277
 
  buf_rmtail (&out, '|');
278
 
  return BSTR (&out);
279
 
}
280
 
 
281
 
void
282
 
set_sock_extended_error_passing (int sd)
283
 
{
284
 
  int on = 1;
285
 
  if (setsockopt (sd, SOL_IP, IP_RECVERR, &on, sizeof (on)))
286
 
    msg (M_WARN | M_ERRNO,
287
 
         "Note: enable extended error passing on TCP/UDP socket failed (IP_RECVERR)");
288
 
}
289
 
 
290
 
#endif