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

« back to all changes in this revision

Viewing changes to .pc/jjo-ipv6-support.patch/mroute.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
 
#if P2MP_SERVER
28
 
 
29
 
#include "mroute.h"
30
 
#include "proto.h"
31
 
#include "error.h"
32
 
#include "socket.h"
33
 
 
34
 
#include "memdbg.h"
35
 
 
36
 
void
37
 
mroute_addr_init (struct mroute_addr *addr)
38
 
{
39
 
  CLEAR (*addr);
40
 
}
41
 
 
42
 
/*
43
 
 * Ethernet multicast addresses.
44
 
 */
45
 
 
46
 
static inline bool
47
 
is_mac_mcast_addr (const uint8_t *mac)
48
 
{
49
 
  return (bool) mac[0] & 1;
50
 
}
51
 
 
52
 
static inline bool
53
 
is_mac_mcast_maddr (const struct mroute_addr *addr)
54
 
{
55
 
  return (addr->type & MR_ADDR_MASK) == MR_ADDR_ETHER && is_mac_mcast_addr (addr->addr); 
56
 
}
57
 
 
58
 
/*
59
 
 * Don't learn certain addresses.
60
 
 */
61
 
bool
62
 
mroute_learnable_address (const struct mroute_addr *addr)
63
 
{
64
 
  int i;
65
 
  bool not_all_zeros = false;
66
 
  bool not_all_ones = false;
67
 
 
68
 
  for (i = 0; i < addr->len; ++i)
69
 
    {
70
 
      int b = addr->addr[i];
71
 
      if (b != 0x00)
72
 
        not_all_zeros = true;
73
 
      if (b != 0xFF)
74
 
        not_all_ones = true;
75
 
    }
76
 
  return not_all_zeros && not_all_ones && !is_mac_mcast_maddr (addr);
77
 
}
78
 
 
79
 
static inline void
80
 
mroute_get_in_addr_t (struct mroute_addr *ma, const in_addr_t src, unsigned int mask)
81
 
{
82
 
  if (ma)
83
 
    {
84
 
      ma->type = MR_ADDR_IPV4 | mask;
85
 
      ma->netbits = 0;
86
 
      ma->len = 4;
87
 
      *(in_addr_t*)ma->addr = src;
88
 
    }
89
 
}
90
 
 
91
 
static inline bool
92
 
mroute_is_mcast (const in_addr_t addr)
93
 
{
94
 
  return ((addr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK));
95
 
}
96
 
 
97
 
#ifdef ENABLE_PF
98
 
 
99
 
static unsigned int
100
 
mroute_extract_addr_arp (struct mroute_addr *src,
101
 
                         struct mroute_addr *dest,
102
 
                         const struct buffer *buf)
103
 
{
104
 
  unsigned int ret = 0;
105
 
  if (BLEN (buf) >= (int) sizeof (struct openvpn_arp))
106
 
    {
107
 
      const struct openvpn_arp *arp = (const struct openvpn_arp *) BPTR (buf);
108
 
      if (arp->mac_addr_type == htons(0x0001)
109
 
          && arp->proto_addr_type == htons(0x0800)
110
 
          && arp->mac_addr_size == 0x06
111
 
          && arp->proto_addr_size == 0x04)
112
 
        {
113
 
          mroute_get_in_addr_t (src, arp->ip_src, MR_ARP);
114
 
          mroute_get_in_addr_t (dest, arp->ip_dest, MR_ARP);
115
 
 
116
 
          /* multicast packet? */
117
 
          if (mroute_is_mcast (arp->ip_dest))
118
 
            ret |= MROUTE_EXTRACT_MCAST;
119
 
 
120
 
          ret |= MROUTE_EXTRACT_SUCCEEDED;
121
 
        }
122
 
    }
123
 
  return ret;
124
 
}
125
 
 
126
 
#endif
127
 
 
128
 
unsigned int
129
 
mroute_extract_addr_ipv4 (struct mroute_addr *src,
130
 
                          struct mroute_addr *dest,
131
 
                          const struct buffer *buf)
132
 
{
133
 
  unsigned int ret = 0;
134
 
  if (BLEN (buf) >= 1)
135
 
    {
136
 
      switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
137
 
        {
138
 
        case 4:
139
 
          if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
140
 
            {
141
 
              const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);
142
 
 
143
 
              mroute_get_in_addr_t (src, ip->saddr, 0);
144
 
              mroute_get_in_addr_t (dest, ip->daddr, 0);
145
 
 
146
 
              /* multicast packet? */
147
 
              if (mroute_is_mcast (ip->daddr))
148
 
                ret |= MROUTE_EXTRACT_MCAST;
149
 
 
150
 
              /* IGMP message? */
151
 
              if (ip->protocol == OPENVPN_IPPROTO_IGMP)
152
 
                ret |= MROUTE_EXTRACT_IGMP;
153
 
 
154
 
              ret |= MROUTE_EXTRACT_SUCCEEDED;
155
 
            }
156
 
          break;
157
 
        case 6:
158
 
          {
159
 
            msg (M_WARN, "Need IPv6 code in mroute_extract_addr_from_packet"); 
160
 
            break;
161
 
          }
162
 
        }
163
 
    }
164
 
  return ret;
165
 
}
166
 
 
167
 
unsigned int
168
 
mroute_extract_addr_ether (struct mroute_addr *src,
169
 
                           struct mroute_addr *dest,
170
 
                           struct mroute_addr *esrc,
171
 
                           struct mroute_addr *edest,
172
 
                           const struct buffer *buf)
173
 
{
174
 
  unsigned int ret = 0;
175
 
  if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr))
176
 
    {
177
 
      const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf);
178
 
      if (src)
179
 
        {
180
 
          src->type = MR_ADDR_ETHER;
181
 
          src->netbits = 0;
182
 
          src->len = 6;
183
 
          memcpy (src->addr, eth->source, 6);
184
 
        }
185
 
      if (dest)
186
 
        {
187
 
          dest->type = MR_ADDR_ETHER;
188
 
          dest->netbits = 0;
189
 
          dest->len = 6;
190
 
          memcpy (dest->addr, eth->dest, 6);
191
 
 
192
 
          /* ethernet broadcast/multicast packet? */
193
 
          if (is_mac_mcast_addr (eth->dest))
194
 
            ret |= MROUTE_EXTRACT_BCAST;
195
 
        }
196
 
          
197
 
      ret |= MROUTE_EXTRACT_SUCCEEDED;
198
 
 
199
 
#ifdef ENABLE_PF
200
 
      if (esrc || edest)
201
 
        {
202
 
          struct buffer b = *buf;
203
 
          if (buf_advance (&b, sizeof (struct openvpn_ethhdr)))
204
 
            {
205
 
              switch (ntohs (eth->proto))
206
 
                {
207
 
                case OPENVPN_ETH_P_IPV4:
208
 
                  ret |= (mroute_extract_addr_ipv4 (esrc, edest, &b) << MROUTE_SEC_SHIFT);
209
 
                  break;
210
 
                case OPENVPN_ETH_P_ARP:
211
 
                  ret |= (mroute_extract_addr_arp (esrc, edest, &b) << MROUTE_SEC_SHIFT);
212
 
                  break;
213
 
                }
214
 
            }
215
 
        }
216
 
#endif
217
 
    }
218
 
  return ret;
219
 
}
220
 
 
221
 
/*
222
 
 * Translate a struct openvpn_sockaddr (osaddr)
223
 
 * to a struct mroute_addr (addr).
224
 
 */
225
 
bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
226
 
                                      const struct openvpn_sockaddr *osaddr,
227
 
                                      bool use_port)
228
 
{
229
 
  if (osaddr->sa.sin_family == AF_INET)
230
 
    {
231
 
      if (use_port)
232
 
        {
233
 
          addr->type = MR_ADDR_IPV4 | MR_WITH_PORT;
234
 
          addr->netbits = 0;
235
 
          addr->len = 6;
236
 
          memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4);
237
 
          memcpy (addr->addr + 4, &osaddr->sa.sin_port, 2);
238
 
        }
239
 
      else
240
 
        {
241
 
          addr->type = MR_ADDR_IPV4;
242
 
          addr->netbits = 0;
243
 
          addr->len = 4;
244
 
          memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4);
245
 
        }
246
 
      return true;
247
 
    }
248
 
  return false;
249
 
}
250
 
 
251
 
/*
252
 
 * Zero off the host bits in an address, leaving
253
 
 * only the network bits, using the netbits member of
254
 
 * struct mroute_addr as the controlling parameter.
255
 
 */
256
 
void
257
 
mroute_addr_mask_host_bits (struct mroute_addr *ma)
258
 
{
259
 
  in_addr_t addr = ntohl(*(in_addr_t*)ma->addr);
260
 
  ASSERT ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4);
261
 
  addr &= netbits_to_netmask (ma->netbits);
262
 
  *(in_addr_t*)ma->addr = htonl (addr);
263
 
}
264
 
 
265
 
/*
266
 
 * The mroute_addr hash function takes into account the
267
 
 * address type, number of bits in the network address,
268
 
 * and the actual address.
269
 
 */
270
 
uint32_t
271
 
mroute_addr_hash_function (const void *key, uint32_t iv)
272
 
{
273
 
  return hash_func (mroute_addr_hash_ptr ((const struct mroute_addr *) key),
274
 
                    mroute_addr_hash_len ((const struct mroute_addr *) key),
275
 
                    iv);
276
 
}
277
 
 
278
 
bool
279
 
mroute_addr_compare_function (const void *key1, const void *key2)
280
 
{
281
 
  return mroute_addr_equal ((const struct mroute_addr *) key1,
282
 
                            (const struct mroute_addr *) key2);
283
 
}
284
 
 
285
 
const char *
286
 
mroute_addr_print (const struct mroute_addr *ma,
287
 
                   struct gc_arena *gc)
288
 
{
289
 
  return mroute_addr_print_ex (ma, MAPF_IA_EMPTY_IF_UNDEF, gc);
290
 
}
291
 
 
292
 
const char *
293
 
mroute_addr_print_ex (const struct mroute_addr *ma,
294
 
                      const unsigned int flags,
295
 
                      struct gc_arena *gc)
296
 
{
297
 
  struct buffer out = alloc_buf_gc (64, gc);
298
 
  if (ma)
299
 
    {
300
 
      struct mroute_addr maddr = *ma;
301
 
 
302
 
      switch (maddr.type & MR_ADDR_MASK)
303
 
        {
304
 
        case MR_ADDR_ETHER:
305
 
          buf_printf (&out, "%s", format_hex_ex (ma->addr, 6, 0, 1, ":", gc)); 
306
 
          break;
307
 
        case MR_ADDR_IPV4:
308
 
          {
309
 
            struct buffer buf;
310
 
            in_addr_t addr;
311
 
            int port;
312
 
            bool status;
313
 
            buf_set_read (&buf, maddr.addr, maddr.len);
314
 
            addr = buf_read_u32 (&buf, &status);
315
 
            if (status)
316
 
              {
317
 
                if ((flags & MAPF_SHOW_ARP) && (maddr.type & MR_ARP))
318
 
                  buf_printf (&out, "ARP/");
319
 
                buf_printf (&out, "%s", print_in_addr_t (addr, (flags & MAPF_IA_EMPTY_IF_UNDEF) ? IA_EMPTY_IF_UNDEF : 0, gc));
320
 
                if (maddr.type & MR_WITH_NETBITS)
321
 
                  {
322
 
                    if (flags & MAPF_SUBNET)
323
 
                      {
324
 
                        const in_addr_t netmask = netbits_to_netmask (maddr.netbits);
325
 
                        buf_printf (&out, "/%s", print_in_addr_t (netmask, 0, gc));
326
 
                      }
327
 
                    else
328
 
                      buf_printf (&out, "/%d", maddr.netbits);
329
 
                  }
330
 
              }
331
 
            if (maddr.type & MR_WITH_PORT)
332
 
              {
333
 
                port = buf_read_u16 (&buf);
334
 
                if (port >= 0)
335
 
                  buf_printf (&out, ":%d", port);
336
 
              }
337
 
          }
338
 
          break;
339
 
        case MR_ADDR_IPV6:
340
 
          buf_printf (&out, "IPV6"); 
341
 
          break;
342
 
        default:
343
 
          buf_printf (&out, "UNKNOWN"); 
344
 
          break;
345
 
        }
346
 
      return BSTR (&out);
347
 
    }
348
 
  else
349
 
    return "[NULL]";
350
 
}
351
 
 
352
 
/*
353
 
 * mroute_helper's main job is keeping track of
354
 
 * currently used CIDR netlengths, so we don't
355
 
 * have to cycle through all 33.
356
 
 */
357
 
 
358
 
struct mroute_helper *
359
 
mroute_helper_init (int ageable_ttl_secs)
360
 
{
361
 
  struct mroute_helper *mh;
362
 
  ALLOC_OBJ_CLEAR (mh, struct mroute_helper);
363
 
  mh->ageable_ttl_secs = ageable_ttl_secs;
364
 
  return mh;
365
 
}
366
 
 
367
 
static void
368
 
mroute_helper_regenerate (struct mroute_helper *mh)
369
 
{
370
 
  int i, j = 0;
371
 
  for (i = MR_HELPER_NET_LEN - 1; i >= 0; --i)
372
 
    {
373
 
      if (mh->net_len_refcount[i] > 0)
374
 
        mh->net_len[j++] = (uint8_t) i;
375
 
    }
376
 
  mh->n_net_len = j;
377
 
 
378
 
#ifdef ENABLE_DEBUG
379
 
  if (check_debug_level (D_MULTI_DEBUG))
380
 
    {
381
 
      struct gc_arena gc = gc_new ();
382
 
      struct buffer out = alloc_buf_gc (256, &gc);
383
 
      buf_printf (&out, "MROUTE CIDR netlen:");
384
 
      for (i = 0; i < mh->n_net_len; ++i)
385
 
        {
386
 
          buf_printf (&out, " /%d", mh->net_len[i]);
387
 
        }
388
 
      dmsg (D_MULTI_DEBUG, "%s", BSTR (&out));
389
 
      gc_free (&gc);
390
 
    }
391
 
#endif
392
 
}
393
 
 
394
 
void
395
 
mroute_helper_add_iroute (struct mroute_helper *mh, const struct iroute *ir)
396
 
{
397
 
  if (ir->netbits >= 0)
398
 
    {
399
 
      ASSERT (ir->netbits < MR_HELPER_NET_LEN);
400
 
      ++mh->cache_generation;
401
 
      ++mh->net_len_refcount[ir->netbits];
402
 
      if (mh->net_len_refcount[ir->netbits] == 1)
403
 
        mroute_helper_regenerate (mh);
404
 
    }
405
 
}
406
 
 
407
 
void
408
 
mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir)
409
 
{
410
 
  if (ir->netbits >= 0)
411
 
    {
412
 
      ASSERT (ir->netbits < MR_HELPER_NET_LEN);
413
 
      ++mh->cache_generation;
414
 
      --mh->net_len_refcount[ir->netbits];
415
 
      ASSERT (mh->net_len_refcount[ir->netbits] >= 0);
416
 
      if (!mh->net_len_refcount[ir->netbits])
417
 
        mroute_helper_regenerate (mh);
418
 
    }
419
 
}
420
 
 
421
 
void
422
 
mroute_helper_free (struct mroute_helper *mh)
423
 
{
424
 
  free (mh);
425
 
}
426
 
 
427
 
#else
428
 
static void dummy(void) {}
429
 
#endif /* P2MP_SERVER */