~ubuntu-branches/ubuntu/hardy/openvpn/hardy-security

« back to all changes in this revision

Viewing changes to mroute.c

  • Committer: Bazaar Package Importer
  • Author(s): Alberto Gonzalez Iniesta
  • Date: 2005-01-05 19:03:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050105190311-mvqzpuhmlvobg9nh
Tags: 1.99+2.rc6-1
* The 'Three Wise Men' release.
* New upstream release.
* Update README.Debian with comments on changed string remapping.
  Thanks ron@debian.org for noting this first. (Closes: #288669)

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-2004 James Yonan <jim@yonan.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 as published by
 
12
 *  the Free Software Foundation; either version 2 of the License, or
 
13
 *  (at your option) any later version.
 
14
 *
 
15
 *  This program is distributed in the hope that it will be useful,
 
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *  GNU General Public License for more details.
 
19
 *
 
20
 *  You should have received a copy of the GNU General Public License
 
21
 *  along with this program (see the file COPYING included with this
 
22
 *  distribution); if not, write to the Free Software Foundation, Inc.,
 
23
 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
24
 */
 
25
 
 
26
#ifdef WIN32
 
27
#include "config-win32.h"
 
28
#else
 
29
#include "config.h"
 
30
#endif
 
31
 
 
32
#include "syshead.h"
 
33
 
 
34
#if P2MP_SERVER
 
35
 
 
36
#include "mroute.h"
 
37
#include "proto.h"
 
38
#include "error.h"
 
39
#include "socket.h"
 
40
 
 
41
#include "memdbg.h"
 
42
 
 
43
void
 
44
mroute_addr_init (struct mroute_addr *addr)
 
45
{
 
46
  CLEAR (*addr);
 
47
}
 
48
 
 
49
/*
 
50
 * Ethernet multicast addresses.
 
51
 */
 
52
 
 
53
static inline bool
 
54
is_mac_mcast_addr (const uint8_t *mac)
 
55
{
 
56
  return (bool) mac[0] & 1;
 
57
}
 
58
 
 
59
static inline bool
 
60
is_mac_mcast_maddr (const struct mroute_addr *addr)
 
61
{
 
62
  return (addr->type & MR_ADDR_MASK) == MR_ADDR_ETHER && is_mac_mcast_addr (addr->addr); 
 
63
}
 
64
 
 
65
/*
 
66
 * Don't learn certain addresses.
 
67
 */
 
68
bool
 
69
mroute_learnable_address (const struct mroute_addr *addr)
 
70
{
 
71
  int i;
 
72
  bool not_all_zeros = false;
 
73
  bool not_all_ones = false;
 
74
 
 
75
  for (i = 0; i < addr->len; ++i)
 
76
    {
 
77
      int b = addr->addr[i];
 
78
      if (b != 0x00)
 
79
        not_all_zeros = true;
 
80
      if (b != 0xFF)
 
81
        not_all_ones = true;
 
82
    }
 
83
  return not_all_zeros && not_all_ones && !is_mac_mcast_maddr (addr);
 
84
}
 
85
 
 
86
/*
 
87
 * Given a raw packet in buf, return the src and dest
 
88
 * addresses of the packet.
 
89
 */
 
90
unsigned int
 
91
mroute_extract_addr_from_packet (struct mroute_addr *src,
 
92
                                 struct mroute_addr *dest,
 
93
                                 struct buffer *buf,
 
94
                                 int tunnel_type)
 
95
{
 
96
  unsigned int ret = 0;
 
97
  verify_align_4 (buf);
 
98
  if (tunnel_type == DEV_TYPE_TUN)
 
99
    {
 
100
      if (BLEN (buf) >= 1)
 
101
        {
 
102
          switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
 
103
            {
 
104
            case 4:
 
105
              if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
 
106
                {
 
107
                  const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);
 
108
                  if (src)
 
109
                    {
 
110
                      src->type = MR_ADDR_IPV4;
 
111
                      src->netbits = 0;
 
112
                      src->len = 4;
 
113
                      memcpy (src->addr, &ip->saddr, 4);
 
114
                    }
 
115
                  if (dest)
 
116
                    {
 
117
                      dest->type = MR_ADDR_IPV4;
 
118
                      dest->netbits = 0;
 
119
                      dest->len = 4;
 
120
                      memcpy (dest->addr, &ip->daddr, 4);
 
121
 
 
122
                      /* mcast address? */
 
123
                      if ((ip->daddr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK))
 
124
                        ret |= MROUTE_EXTRACT_MCAST;
 
125
 
 
126
                      /* IGMP message? */
 
127
                      if (ip->protocol == OPENVPN_IPPROTO_IGMP)
 
128
                        ret |= MROUTE_EXTRACT_IGMP;
 
129
                    }
 
130
                  ret |= MROUTE_EXTRACT_SUCCEEDED;
 
131
                }
 
132
              break;
 
133
            case 6:
 
134
              {
 
135
                msg (M_WARN, "Need IPv6 code in mroute_extract_addr_from_packet"); 
 
136
                break;
 
137
              }
 
138
            }
 
139
        }
 
140
    }
 
141
  else if (tunnel_type == DEV_TYPE_TAP)
 
142
    {
 
143
      if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr))
 
144
        {
 
145
          const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf);
 
146
          if (src)
 
147
            {
 
148
              src->type = MR_ADDR_ETHER;
 
149
              src->netbits = 0;
 
150
              src->len = 6;
 
151
              memcpy (src->addr, eth->source, 6);
 
152
            }
 
153
          if (dest)
 
154
            {
 
155
              dest->type = MR_ADDR_ETHER;
 
156
              dest->netbits = 0;
 
157
              dest->len = 6;
 
158
              memcpy (dest->addr, eth->dest, 6);
 
159
 
 
160
              /* ethernet broadcast/multicast packet? */
 
161
              if (is_mac_mcast_addr (eth->dest))
 
162
                ret |= MROUTE_EXTRACT_BCAST;
 
163
            }
 
164
          
 
165
          ret |= MROUTE_EXTRACT_SUCCEEDED;
 
166
        }
 
167
    }
 
168
  return ret;
 
169
}
 
170
 
 
171
/*
 
172
 * Translate a struct sockaddr_in (saddr)
 
173
 * to a struct mroute_addr (addr).
 
174
 */
 
175
bool
 
176
mroute_extract_sockaddr_in (struct mroute_addr *addr, const struct sockaddr_in *saddr, bool use_port)
 
177
{
 
178
  if (saddr->sin_family == AF_INET)
 
179
    {
 
180
      if (use_port)
 
181
        {
 
182
          addr->type = MR_ADDR_IPV4 | MR_WITH_PORT;
 
183
          addr->netbits = 0;
 
184
          addr->len = 6;
 
185
          memcpy (addr->addr, &saddr->sin_addr.s_addr, 4);
 
186
          memcpy (addr->addr + 4, &saddr->sin_port, 2);
 
187
        }
 
188
      else
 
189
        {
 
190
          addr->type = MR_ADDR_IPV4;
 
191
          addr->netbits = 0;
 
192
          addr->len = 4;
 
193
          memcpy (addr->addr, &saddr->sin_addr.s_addr, 4);
 
194
        }
 
195
      return true;
 
196
    }
 
197
  return false;
 
198
}
 
199
 
 
200
/*
 
201
 * Zero off the host bits in an address, leaving
 
202
 * only the network bits, using the netbits member of
 
203
 * struct mroute_addr as the controlling parameter.
 
204
 */
 
205
void
 
206
mroute_addr_mask_host_bits (struct mroute_addr *ma)
 
207
{
 
208
  in_addr_t addr = ntohl(*(in_addr_t*)ma->addr);
 
209
  ASSERT ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4);
 
210
  addr &= netbits_to_netmask (ma->netbits);
 
211
  *(in_addr_t*)ma->addr = htonl (addr);
 
212
}
 
213
 
 
214
/*
 
215
 * The mroute_addr hash function takes into account the
 
216
 * address type, number of bits in the network address,
 
217
 * and the actual address.
 
218
 */
 
219
uint32_t
 
220
mroute_addr_hash_function (const void *key, uint32_t iv)
 
221
{
 
222
  return hash_func (mroute_addr_hash_ptr ((const struct mroute_addr *) key),
 
223
                    mroute_addr_hash_len ((const struct mroute_addr *) key),
 
224
                    iv);
 
225
}
 
226
 
 
227
bool
 
228
mroute_addr_compare_function (const void *key1, const void *key2)
 
229
{
 
230
  return mroute_addr_equal ((const struct mroute_addr *) key1,
 
231
                            (const struct mroute_addr *) key2);
 
232
}
 
233
 
 
234
const char *
 
235
mroute_addr_print (const struct mroute_addr *ma,
 
236
                   struct gc_arena *gc)
 
237
{
 
238
  struct buffer out = alloc_buf_gc (64, gc);
 
239
  if (ma)
 
240
    {
 
241
      struct mroute_addr maddr = *ma;
 
242
 
 
243
      switch (maddr.type & MR_ADDR_MASK)
 
244
        {
 
245
        case MR_ADDR_ETHER:
 
246
          buf_printf (&out, "%s", format_hex_ex (ma->addr, 6, 0, 1, ":", gc)); 
 
247
          break;
 
248
        case MR_ADDR_IPV4:
 
249
          {
 
250
            struct buffer buf;
 
251
            in_addr_t addr;
 
252
            int port;
 
253
            bool status;
 
254
            buf_set_read (&buf, maddr.addr, maddr.len);
 
255
            addr = buf_read_u32 (&buf, &status);
 
256
            if (status)
 
257
              {
 
258
                buf_printf (&out, "%s", print_in_addr_t (addr, IA_EMPTY_IF_UNDEF, gc));
 
259
                if (maddr.type & MR_WITH_NETBITS)
 
260
                  buf_printf (&out, "/%d", maddr.netbits);
 
261
              }
 
262
            if (maddr.type & MR_WITH_PORT)
 
263
              {
 
264
                port = buf_read_u16 (&buf);
 
265
                if (port >= 0)
 
266
                  buf_printf (&out, ":%d", port);
 
267
              }
 
268
          }
 
269
          break;
 
270
        case MR_ADDR_IPV6:
 
271
          buf_printf (&out, "IPV6"); 
 
272
          break;
 
273
        default:
 
274
          buf_printf (&out, "UNKNOWN"); 
 
275
          break;
 
276
        }
 
277
      return BSTR (&out);
 
278
    }
 
279
  else
 
280
    return "[NULL]";
 
281
}
 
282
 
 
283
/*
 
284
 * mroute_helper's main job is keeping track of
 
285
 * currently used CIDR netlengths, so we don't
 
286
 * have to cycle through all 33.
 
287
 */
 
288
 
 
289
struct mroute_helper *
 
290
mroute_helper_init (int ageable_ttl_secs)
 
291
{
 
292
  struct mroute_helper *mh;
 
293
  ALLOC_OBJ_CLEAR (mh, struct mroute_helper);
 
294
  //mutex_init (&mh->mutex);
 
295
  mh->ageable_ttl_secs = ageable_ttl_secs;
 
296
  return mh;
 
297
}
 
298
 
 
299
static void
 
300
mroute_helper_regenerate (struct mroute_helper *mh)
 
301
{
 
302
  int i, j = 0;
 
303
  for (i = MR_HELPER_NET_LEN - 1; i >= 0; --i)
 
304
    {
 
305
      if (mh->net_len_refcount[i] > 0)
 
306
        mh->net_len[j++] = (uint8_t) i;
 
307
    }
 
308
  mh->n_net_len = j;
 
309
 
 
310
#ifdef ENABLE_DEBUG
 
311
  if (check_debug_level (D_MULTI_DEBUG))
 
312
    {
 
313
      struct gc_arena gc = gc_new ();
 
314
      struct buffer out = alloc_buf_gc (256, &gc);
 
315
      buf_printf (&out, "MROUTE CIDR netlen:");
 
316
      for (i = 0; i < mh->n_net_len; ++i)
 
317
        {
 
318
          buf_printf (&out, " /%d", mh->net_len[i]);
 
319
        }
 
320
      dmsg (D_MULTI_DEBUG, "%s", BSTR (&out));
 
321
      gc_free (&gc);
 
322
    }
 
323
#endif
 
324
}
 
325
 
 
326
void
 
327
mroute_helper_add_iroute (struct mroute_helper *mh, const struct iroute *ir)
 
328
{
 
329
  if (ir->netbits >= 0)
 
330
    {
 
331
      ASSERT (ir->netbits < MR_HELPER_NET_LEN);
 
332
      mroute_helper_lock (mh);
 
333
      ++mh->cache_generation;
 
334
      ++mh->net_len_refcount[ir->netbits];
 
335
      if (mh->net_len_refcount[ir->netbits] == 1)
 
336
        mroute_helper_regenerate (mh);
 
337
      mroute_helper_unlock (mh);
 
338
    }
 
339
}
 
340
 
 
341
void
 
342
mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir)
 
343
{
 
344
  if (ir->netbits >= 0)
 
345
    {
 
346
      ASSERT (ir->netbits < MR_HELPER_NET_LEN);
 
347
      mroute_helper_lock (mh);
 
348
      ++mh->cache_generation;
 
349
      --mh->net_len_refcount[ir->netbits];
 
350
      ASSERT (mh->net_len_refcount[ir->netbits] >= 0);
 
351
      if (!mh->net_len_refcount[ir->netbits])
 
352
        mroute_helper_regenerate (mh);
 
353
      mroute_helper_unlock (mh);
 
354
    }
 
355
}
 
356
 
 
357
void
 
358
mroute_helper_free (struct mroute_helper *mh)
 
359
{
 
360
  //mutex_destroy (&mh->mutex);
 
361
  free (mh);
 
362
}
 
363
 
 
364
#else
 
365
static void dummy(void) {}
 
366
#endif /* P2MP_SERVER */