~smoser/ubuntu/oneiric/openvpn/lp-794916

« back to all changes in this revision

Viewing changes to .pc/clean_netlist.patch/route.c

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2010-10-23 01:59:28 UTC
  • mfrom: (10.2.9 sid)
  • Revision ID: james.westby@ubuntu.com-20101023015928-5kjk27ysk77ju6k9
Tags: 2.1.3-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.
  +  debian/control: Add lsb-base >= 3.2-14 to allow status_of_proc()

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
/*
 
26
 * Support routines for adding/deleting network routes.
 
27
 */
 
28
 
 
29
#include "syshead.h"
 
30
 
 
31
#include "common.h"
 
32
#include "error.h"
 
33
#include "route.h"
 
34
#include "misc.h"
 
35
#include "socket.h"
 
36
#include "manage.h"
 
37
#include "win32.h"
 
38
 
 
39
#include "memdbg.h"
 
40
 
 
41
static void delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
 
42
static void get_bypass_addresses (struct route_bypass *rb, const unsigned int flags);
 
43
 
 
44
#ifdef ENABLE_DEBUG
 
45
 
 
46
static void
 
47
print_bypass_addresses (const struct route_bypass *rb)
 
48
{
 
49
  struct gc_arena gc = gc_new ();
 
50
  int i;
 
51
  for (i = 0; i < rb->n_bypass; ++i)
 
52
    {
 
53
      msg (D_ROUTE, "ROUTE: bypass_host_route[%d]=%s",
 
54
           i,
 
55
           print_in_addr_t (rb->bypass[i], 0, &gc));
 
56
    }
 
57
  gc_free (&gc);
 
58
}
 
59
 
 
60
#endif
 
61
 
 
62
static bool
 
63
add_bypass_address (struct route_bypass *rb, const in_addr_t a)
 
64
{
 
65
  int i;
 
66
  for (i = 0; i < rb->n_bypass; ++i)
 
67
    {
 
68
      if (a == rb->bypass[i]) /* avoid duplicates */
 
69
        return true;
 
70
    }
 
71
  if (rb->n_bypass < N_ROUTE_BYPASS)
 
72
    {
 
73
      rb->bypass[rb->n_bypass++] = a;
 
74
      return true;
 
75
    }
 
76
  else
 
77
    {
 
78
      return false;
 
79
    }
 
80
}
 
81
 
 
82
struct route_option_list *
 
83
new_route_option_list (const int max_routes, struct gc_arena *a)
 
84
{
 
85
  struct route_option_list *ret;
 
86
  ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_option_list, struct route_option, max_routes, a);
 
87
  ret->capacity = max_routes;
 
88
  return ret;
 
89
}
 
90
 
 
91
struct route_option_list *
 
92
clone_route_option_list (const struct route_option_list *src, struct gc_arena *a)
 
93
{
 
94
  const size_t rl_size = array_mult_safe (sizeof(struct route_option), src->capacity, sizeof(struct route_option_list));
 
95
  struct route_option_list *ret = gc_malloc (rl_size, false, a);
 
96
  memcpy (ret, src, rl_size);
 
97
  return ret;
 
98
}
 
99
 
 
100
void
 
101
copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src)
 
102
{
 
103
  const size_t src_size = array_mult_safe (sizeof(struct route_option), src->capacity, sizeof(struct route_option_list));
 
104
  if (src->n > dest->capacity)
 
105
    msg (M_FATAL, PACKAGE_NAME " ROUTE: (copy) number of route options in src (%d) is greater than route list capacity in dest (%d)", src->n, dest->capacity);
 
106
  memcpy (dest, src, src_size);
 
107
}
 
108
 
 
109
struct route_list *
 
110
new_route_list (const int max_routes, struct gc_arena *a)
 
111
{
 
112
  struct route_list *ret;
 
113
  ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_list, struct route, max_routes, a);
 
114
  ret->capacity = max_routes;
 
115
  return ret;
 
116
}
 
117
 
 
118
static const char *
 
119
route_string (const struct route *r, struct gc_arena *gc)
 
120
{
 
121
  struct buffer out = alloc_buf_gc (256, gc);
 
122
  buf_printf (&out, "ROUTE network %s netmask %s gateway %s",
 
123
              print_in_addr_t (r->network, 0, gc),
 
124
              print_in_addr_t (r->netmask, 0, gc),
 
125
              print_in_addr_t (r->gateway, 0, gc)
 
126
              );
 
127
  if (r->metric_defined)
 
128
    buf_printf (&out, " metric %d", r->metric);
 
129
  return BSTR (&out);
 
130
}
 
131
 
 
132
static bool
 
133
is_route_parm_defined (const char *parm)
 
134
{
 
135
  if (!parm)
 
136
    return false;
 
137
  if (!strcmp (parm, "default"))
 
138
    return false;
 
139
  return true;
 
140
}
 
141
 
 
142
static void
 
143
setenv_route_addr (struct env_set *es, const char *key, const in_addr_t addr, int i)
 
144
{
 
145
  struct gc_arena gc = gc_new ();
 
146
  struct buffer name = alloc_buf_gc (256, &gc);
 
147
  if (i >= 0)
 
148
    buf_printf (&name, "route_%s_%d", key, i);
 
149
  else
 
150
    buf_printf (&name, "route_%s", key);
 
151
  setenv_str (es, BSTR (&name), print_in_addr_t (addr, 0, &gc));
 
152
  gc_free (&gc);
 
153
}
 
154
 
 
155
static bool
 
156
get_special_addr (const struct route_special_addr *spec,
 
157
                  const char *string,
 
158
                  in_addr_t *out,
 
159
                  bool *status)
 
160
{
 
161
  if (status)
 
162
    *status = true;
 
163
  if (!strcmp (string, "vpn_gateway"))
 
164
    {
 
165
      if (spec)
 
166
        {
 
167
          if (spec->remote_endpoint_defined)
 
168
            *out = spec->remote_endpoint;
 
169
          else
 
170
            {
 
171
              msg (M_INFO, PACKAGE_NAME " ROUTE: vpn_gateway undefined");
 
172
              if (status)
 
173
                *status = false;
 
174
            }
 
175
        }
 
176
      return true;
 
177
    }
 
178
  else if (!strcmp (string, "net_gateway"))
 
179
    {
 
180
      if (spec)
 
181
        {
 
182
          if (spec->net_gateway_defined)
 
183
            *out = spec->net_gateway;
 
184
          else
 
185
            {
 
186
              msg (M_INFO, PACKAGE_NAME " ROUTE: net_gateway undefined -- unable to get default gateway from system");
 
187
              if (status)
 
188
                *status = false;
 
189
            }
 
190
        }
 
191
      return true;
 
192
    }
 
193
  else if (!strcmp (string, "remote_host"))
 
194
    {
 
195
      if (spec)
 
196
        {
 
197
          if (spec->remote_host_defined)
 
198
            *out = spec->remote_host;
 
199
          else
 
200
            {
 
201
              msg (M_INFO, PACKAGE_NAME " ROUTE: remote_host undefined");
 
202
              if (status)
 
203
                *status = false;
 
204
            }
 
205
        }
 
206
      return true;
 
207
    }
 
208
  return false;
 
209
}
 
210
 
 
211
bool
 
212
is_special_addr (const char *addr_str)
 
213
{
 
214
  if (addr_str)
 
215
    return get_special_addr (NULL, addr_str, NULL, NULL);
 
216
  else
 
217
    return false;
 
218
}
 
219
 
 
220
static bool
 
221
init_route (struct route *r,
 
222
            struct resolve_list *network_list,
 
223
            const struct route_option *ro,
 
224
            const struct route_special_addr *spec)
 
225
{
 
226
  const in_addr_t default_netmask = ~0;
 
227
  bool status;
 
228
 
 
229
  r->option = ro;
 
230
  r->defined = false;
 
231
 
 
232
  /* network */
 
233
 
 
234
  if (!is_route_parm_defined (ro->network))
 
235
    {
 
236
      goto fail;
 
237
    }
 
238
  
 
239
  if (!get_special_addr (spec, ro->network, &r->network, &status))
 
240
    {
 
241
      r->network = getaddr_multi (
 
242
                                  GETADDR_RESOLVE
 
243
                                  | GETADDR_HOST_ORDER
 
244
                                  | GETADDR_WARN_ON_SIGNAL,
 
245
                                  ro->network,
 
246
                                  0,
 
247
                                  &status,
 
248
                                  NULL,
 
249
                                  network_list);
 
250
    }
 
251
 
 
252
  if (!status)
 
253
    goto fail;
 
254
 
 
255
  /* netmask */
 
256
 
 
257
  if (is_route_parm_defined (ro->netmask))
 
258
    {
 
259
      r->netmask = getaddr (
 
260
                            GETADDR_HOST_ORDER
 
261
                            | GETADDR_WARN_ON_SIGNAL,
 
262
                            ro->netmask,
 
263
                            0,
 
264
                            &status,
 
265
                            NULL);
 
266
      if (!status)
 
267
        goto fail;
 
268
    }
 
269
  else
 
270
    r->netmask = default_netmask;
 
271
 
 
272
  /* gateway */
 
273
 
 
274
  if (is_route_parm_defined (ro->gateway))
 
275
    {
 
276
      if (!get_special_addr (spec, ro->gateway, &r->gateway, &status))
 
277
        {
 
278
          r->gateway = getaddr (
 
279
                                GETADDR_RESOLVE
 
280
                                | GETADDR_HOST_ORDER
 
281
                                | GETADDR_WARN_ON_SIGNAL,
 
282
                                ro->gateway,
 
283
                                0,
 
284
                                &status,
 
285
                                NULL);
 
286
        }
 
287
      if (!status)
 
288
        goto fail;
 
289
    }
 
290
  else
 
291
    {
 
292
      if (spec->remote_endpoint_defined)
 
293
        r->gateway = spec->remote_endpoint;
 
294
      else
 
295
        {
 
296
          msg (M_WARN, PACKAGE_NAME " ROUTE: " PACKAGE_NAME " needs a gateway parameter for a --route option and no default was specified by either --route-gateway or --ifconfig options");
 
297
          goto fail;
 
298
        }
 
299
    }
 
300
 
 
301
  /* metric */
 
302
 
 
303
  r->metric_defined = false;
 
304
  r->metric = 0;
 
305
  if (is_route_parm_defined (ro->metric))
 
306
    {
 
307
      r->metric = atoi (ro->metric);
 
308
      if (r->metric < 0)
 
309
        {
 
310
          msg (M_WARN, PACKAGE_NAME " ROUTE: route metric for network %s (%s) must be >= 0",
 
311
               ro->network,
 
312
               ro->metric);
 
313
          goto fail;
 
314
        }
 
315
      r->metric_defined = true;
 
316
    }
 
317
  else if (spec->default_metric_defined)
 
318
    {
 
319
      r->metric = spec->default_metric;
 
320
      r->metric_defined = true;
 
321
    }
 
322
 
 
323
  r->defined = true;
 
324
 
 
325
  return true;
 
326
 
 
327
 fail:
 
328
  msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve route for host/network: %s",
 
329
       ro->network);
 
330
  r->defined = false;
 
331
  return false;
 
332
}
 
333
 
 
334
void
 
335
add_route_to_option_list (struct route_option_list *l,
 
336
                          const char *network,
 
337
                          const char *netmask,
 
338
                          const char *gateway,
 
339
                          const char *metric)
 
340
{
 
341
  struct route_option *ro;
 
342
  if (l->n >= l->capacity)
 
343
    msg (M_FATAL, PACKAGE_NAME " ROUTE: cannot add more than %d routes -- please increase the max-routes option in the client configuration file",
 
344
         l->capacity);
 
345
  ro = &l->routes[l->n];
 
346
  ro->network = network;
 
347
  ro->netmask = netmask;
 
348
  ro->gateway = gateway;
 
349
  ro->metric = metric;
 
350
  ++l->n;
 
351
}
 
352
 
 
353
void
 
354
clear_route_list (struct route_list *rl)
 
355
{
 
356
  const int capacity = rl->capacity;
 
357
  const size_t rl_size = array_mult_safe (sizeof(struct route), capacity, sizeof(struct route_list));
 
358
  memset(rl, 0, rl_size);
 
359
  rl->capacity = capacity;
 
360
}
 
361
 
 
362
void
 
363
route_list_add_default_gateway (struct route_list *rl,
 
364
                                struct env_set *es,
 
365
                                const in_addr_t addr)
 
366
{
 
367
  rl->spec.remote_endpoint = addr;
 
368
  rl->spec.remote_endpoint_defined = true;
 
369
  setenv_route_addr (es, "vpn_gateway", rl->spec.remote_endpoint, -1);
 
370
}
 
371
 
 
372
bool
 
373
init_route_list (struct route_list *rl,
 
374
                 const struct route_option_list *opt,
 
375
                 const char *remote_endpoint,
 
376
                 int default_metric,
 
377
                 in_addr_t remote_host,
 
378
                 struct env_set *es)
 
379
{
 
380
  struct gc_arena gc = gc_new ();
 
381
  bool ret = true;
 
382
 
 
383
  clear_route_list (rl);
 
384
 
 
385
  rl->flags = opt->flags;
 
386
 
 
387
  if (remote_host)
 
388
    {
 
389
      rl->spec.remote_host = remote_host;
 
390
      rl->spec.remote_host_defined = true;
 
391
    }
 
392
 
 
393
  if (default_metric)
 
394
    {
 
395
      rl->spec.default_metric = default_metric;
 
396
      rl->spec.default_metric_defined = true;
 
397
    }
 
398
 
 
399
  rl->spec.net_gateway_defined = get_default_gateway (&rl->spec.net_gateway, NULL);
 
400
  if (rl->spec.net_gateway_defined)
 
401
    {
 
402
      setenv_route_addr (es, "net_gateway", rl->spec.net_gateway, -1);
 
403
      dmsg (D_ROUTE, "ROUTE default_gateway=%s", print_in_addr_t (rl->spec.net_gateway, 0, &gc));
 
404
    }
 
405
  else
 
406
    {
 
407
      dmsg (D_ROUTE, "ROUTE: default_gateway=UNDEF");
 
408
    }
 
409
 
 
410
  if (rl->flags & RG_ENABLE)
 
411
    {
 
412
      get_bypass_addresses (&rl->spec.bypass, rl->flags);
 
413
#ifdef ENABLE_DEBUG
 
414
      print_bypass_addresses (&rl->spec.bypass);
 
415
#endif
 
416
    }
 
417
 
 
418
  if (is_route_parm_defined (remote_endpoint))
 
419
    {
 
420
      rl->spec.remote_endpoint = getaddr (
 
421
                                     GETADDR_RESOLVE
 
422
                                     | GETADDR_HOST_ORDER
 
423
                                     | GETADDR_WARN_ON_SIGNAL,
 
424
                                     remote_endpoint,
 
425
                                     0,
 
426
                                     &rl->spec.remote_endpoint_defined,
 
427
                                     NULL);
 
428
 
 
429
      if (rl->spec.remote_endpoint_defined)
 
430
        {
 
431
          setenv_route_addr (es, "vpn_gateway", rl->spec.remote_endpoint, -1);
 
432
        }
 
433
      else
 
434
        {
 
435
          msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve default gateway: %s",
 
436
               remote_endpoint);
 
437
          ret = false;
 
438
        }
 
439
    }
 
440
  else
 
441
    rl->spec.remote_endpoint_defined = false;
 
442
 
 
443
  /* parse the routes from opt to rl */
 
444
  {
 
445
    int i, j = 0;
 
446
    bool warned = false;
 
447
    for (i = 0; i < opt->n; ++i)
 
448
      {
 
449
        struct resolve_list netlist;
 
450
        struct route r;
 
451
        int k;
 
452
 
 
453
        if (!init_route (&r,
 
454
                         &netlist,
 
455
                         &opt->routes[i],
 
456
                         &rl->spec))
 
457
          ret = false;
 
458
        else
 
459
          {
 
460
            if (!netlist.len)
 
461
              {
 
462
                netlist.data[0] = r.network;
 
463
                netlist.len = 1;
 
464
              }
 
465
            for (k = 0; k < netlist.len; ++k)
 
466
              {
 
467
                if (j < rl->capacity)
 
468
                  {
 
469
                    r.network = netlist.data[k];
 
470
                    rl->routes[j++] = r;
 
471
                  }
 
472
                else
 
473
                  {
 
474
                    if (!warned)
 
475
                      {
 
476
                        msg (M_WARN, PACKAGE_NAME " ROUTE: routes dropped because number of expanded routes is greater than route list capacity (%d)", rl->capacity);
 
477
                        warned = true;
 
478
                      }
 
479
                  }
 
480
              }
 
481
          }
 
482
      }
 
483
    rl->n = j;
 
484
  }
 
485
 
 
486
  gc_free (&gc);
 
487
  return ret;
 
488
}
 
489
 
 
490
static void
 
491
add_route3 (in_addr_t network,
 
492
            in_addr_t netmask,
 
493
            in_addr_t gateway,
 
494
            const struct tuntap *tt,
 
495
            unsigned int flags,
 
496
            const struct env_set *es)
 
497
{
 
498
  struct route r;
 
499
  CLEAR (r);
 
500
  r.defined = true;
 
501
  r.network = network;
 
502
  r.netmask = netmask;
 
503
  r.gateway = gateway;
 
504
  add_route (&r, tt, flags, es);
 
505
}
 
506
 
 
507
static void
 
508
del_route3 (in_addr_t network,
 
509
            in_addr_t netmask,
 
510
            in_addr_t gateway,
 
511
            const struct tuntap *tt,
 
512
            unsigned int flags,
 
513
            const struct env_set *es)
 
514
{
 
515
  struct route r;
 
516
  CLEAR (r);
 
517
  r.defined = true;
 
518
  r.network = network;
 
519
  r.netmask = netmask;
 
520
  r.gateway = gateway;
 
521
  delete_route (&r, tt, flags, es);
 
522
}
 
523
 
 
524
static void
 
525
add_bypass_routes (struct route_bypass *rb,
 
526
                   in_addr_t gateway,
 
527
                   const struct tuntap *tt,
 
528
                   unsigned int flags,
 
529
                   const struct env_set *es)
 
530
{
 
531
  int i;
 
532
  for (i = 0; i < rb->n_bypass; ++i)
 
533
    {
 
534
      if (rb->bypass[i] != gateway)
 
535
        add_route3 (rb->bypass[i],
 
536
                    ~0,
 
537
                    gateway,
 
538
                    tt,
 
539
                    flags,
 
540
                    es);
 
541
    }
 
542
}
 
543
 
 
544
static void
 
545
del_bypass_routes (struct route_bypass *rb,
 
546
                   in_addr_t gateway,
 
547
                   const struct tuntap *tt,
 
548
                   unsigned int flags,
 
549
                   const struct env_set *es)
 
550
{
 
551
  int i;
 
552
  for (i = 0; i < rb->n_bypass; ++i)
 
553
    {
 
554
      if (rb->bypass[i] != gateway)
 
555
        del_route3 (rb->bypass[i],
 
556
                    ~0,
 
557
                    gateway,
 
558
                    tt,
 
559
                    flags,
 
560
                    es);
 
561
    }
 
562
}
 
563
 
 
564
static void
 
565
redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
 
566
{
 
567
  const char err[] = "NOTE: unable to redirect default gateway --";
 
568
 
 
569
  if (rl->flags & RG_ENABLE)
 
570
    {
 
571
      if (!rl->spec.remote_endpoint_defined)
 
572
        {
 
573
          msg (M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
 
574
        }
 
575
      else if (!rl->spec.net_gateway_defined)
 
576
        {
 
577
          msg (M_WARN, "%s Cannot read current default gateway from system", err);
 
578
        }
 
579
      else if (!rl->spec.remote_host_defined)
 
580
        {
 
581
          msg (M_WARN, "%s Cannot obtain current remote host address", err);
 
582
        }
 
583
      else
 
584
        {
 
585
          bool local = BOOL_CAST(rl->flags & RG_LOCAL);
 
586
          if (rl->flags & RG_AUTO_LOCAL) {
 
587
            const int tla = test_local_addr (rl->spec.remote_host);
 
588
            if (tla == TLA_NONLOCAL)
 
589
              {
 
590
                dmsg (D_ROUTE, "ROUTE remote_host is NOT LOCAL");
 
591
                local = false;
 
592
              }
 
593
            else if (tla == TLA_LOCAL)
 
594
              {
 
595
                dmsg (D_ROUTE, "ROUTE remote_host is LOCAL");
 
596
                local = true;
 
597
              }
 
598
          }
 
599
          if (!local)
 
600
            {
 
601
              /* route remote host to original default gateway */
 
602
#ifdef USE_PF_INET6
 
603
              /* if remote_host is not ipv4 (ie: ipv6), just skip
 
604
               * adding this special /32 route */
 
605
              if (rl->spec.remote_host != IPV4_INVALID_ADDR) {
 
606
#endif
 
607
                add_route3 (rl->spec.remote_host,
 
608
                            ~0,
 
609
                            rl->spec.net_gateway,
 
610
                            tt,
 
611
                            flags,
 
612
                            es);
 
613
                rl->did_local = true;
 
614
#ifdef USE_PF_INET6
 
615
              } else {
 
616
                dmsg (D_ROUTE, "ROUTE remote_host protocol differs from tunneled");
 
617
              }
 
618
#endif
 
619
            }
 
620
 
 
621
          /* route DHCP/DNS server traffic through original default gateway */
 
622
          add_bypass_routes (&rl->spec.bypass, rl->spec.net_gateway, tt, flags, es);
 
623
 
 
624
          if (rl->flags & RG_REROUTE_GW)
 
625
            {
 
626
              if (rl->flags & RG_DEF1)
 
627
                {
 
628
                  /* add new default route (1st component) */
 
629
                  add_route3 (0x00000000,
 
630
                              0x80000000,
 
631
                              rl->spec.remote_endpoint,
 
632
                              tt,
 
633
                              flags,
 
634
                              es);
 
635
 
 
636
                  /* add new default route (2nd component) */
 
637
                  add_route3 (0x80000000,
 
638
                              0x80000000,
 
639
                              rl->spec.remote_endpoint,
 
640
                              tt,
 
641
                              flags,
 
642
                              es);
 
643
                }
 
644
              else
 
645
                {
 
646
                  /* delete default route */
 
647
                  del_route3 (0,
 
648
                              0,
 
649
                              rl->spec.net_gateway,
 
650
                              tt,
 
651
                              flags,
 
652
                              es);
 
653
 
 
654
                  /* add new default route */
 
655
                  add_route3 (0,
 
656
                              0,
 
657
                              rl->spec.remote_endpoint,
 
658
                              tt,
 
659
                              flags,
 
660
                              es);
 
661
                }
 
662
            }
 
663
 
 
664
          /* set a flag so we can undo later */
 
665
          rl->did_redirect_default_gateway = true;
 
666
        }
 
667
    }
 
668
}
 
669
 
 
670
static void
 
671
undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
 
672
{
 
673
  if (rl->did_redirect_default_gateway)
 
674
    {
 
675
      /* delete remote host route */
 
676
      if (rl->did_local)
 
677
        {
 
678
          del_route3 (rl->spec.remote_host,
 
679
                      ~0,
 
680
                      rl->spec.net_gateway,
 
681
                      tt,
 
682
                      flags,
 
683
                      es);
 
684
          rl->did_local = false;
 
685
        }
 
686
 
 
687
      /* delete special DHCP/DNS bypass route */
 
688
      del_bypass_routes (&rl->spec.bypass, rl->spec.net_gateway, tt, flags, es);
 
689
 
 
690
      if (rl->flags & RG_REROUTE_GW)
 
691
        {
 
692
          if (rl->flags & RG_DEF1)
 
693
            {
 
694
              /* delete default route (1st component) */
 
695
              del_route3 (0x00000000,
 
696
                          0x80000000,
 
697
                          rl->spec.remote_endpoint,
 
698
                          tt,
 
699
                          flags,
 
700
                          es);
 
701
 
 
702
              /* delete default route (2nd component) */
 
703
              del_route3 (0x80000000,
 
704
                          0x80000000,
 
705
                          rl->spec.remote_endpoint,
 
706
                          tt,
 
707
                          flags,
 
708
                          es);
 
709
            }
 
710
          else
 
711
            {
 
712
              /* delete default route */
 
713
              del_route3 (0,
 
714
                          0,
 
715
                          rl->spec.remote_endpoint,
 
716
                          tt,
 
717
                          flags,
 
718
                          es);
 
719
 
 
720
              /* restore original default route */
 
721
              add_route3 (0,
 
722
                          0,
 
723
                          rl->spec.net_gateway,
 
724
                          tt,
 
725
                          flags,
 
726
                          es);
 
727
            }
 
728
        }
 
729
 
 
730
      rl->did_redirect_default_gateway = false;
 
731
    }
 
732
}
 
733
 
 
734
void
 
735
add_routes (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
 
736
{
 
737
  redirect_default_route_to_vpn (rl, tt, flags, es);
 
738
  if (!rl->routes_added)
 
739
    {
 
740
      int i;
 
741
 
 
742
#ifdef ENABLE_MANAGEMENT
 
743
      if (management && rl->n)
 
744
        {
 
745
          management_set_state (management,
 
746
                                OPENVPN_STATE_ADD_ROUTES,
 
747
                                NULL,
 
748
                                0,
 
749
                                0);
 
750
        }
 
751
#endif
 
752
      
 
753
      for (i = 0; i < rl->n; ++i)
 
754
        {
 
755
          struct route *r = &rl->routes[i];
 
756
          check_subnet_conflict (r->network, r->netmask, "route");
 
757
          if (flags & ROUTE_DELETE_FIRST)
 
758
            delete_route (r, tt, flags, es);
 
759
          add_route (r, tt, flags, es);
 
760
        }
 
761
      rl->routes_added = true;
 
762
    }
 
763
}
 
764
 
 
765
void
 
766
delete_routes (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
 
767
{
 
768
  if (rl->routes_added)
 
769
    {
 
770
      int i;
 
771
      for (i = rl->n - 1; i >= 0; --i)
 
772
        {
 
773
          const struct route *r = &rl->routes[i];
 
774
          delete_route (r, tt, flags, es);
 
775
        }
 
776
      rl->routes_added = false;
 
777
    }
 
778
  undo_redirect_default_route_to_vpn (rl, tt, flags, es);
 
779
 
 
780
  clear_route_list (rl);
 
781
}
 
782
 
 
783
#ifdef ENABLE_DEBUG
 
784
 
 
785
static const char *
 
786
show_opt (const char *option)
 
787
{
 
788
  if (!option)
 
789
    return "nil";
 
790
  else
 
791
    return option;
 
792
}
 
793
 
 
794
static void
 
795
print_route_option (const struct route_option *ro, int level)
 
796
{
 
797
  msg (level, "  route %s/%s/%s/%s",
 
798
       show_opt (ro->network),
 
799
       show_opt (ro->netmask),
 
800
       show_opt (ro->gateway),
 
801
       show_opt (ro->metric));
 
802
}
 
803
 
 
804
void
 
805
print_route_options (const struct route_option_list *rol,
 
806
                     int level)
 
807
{
 
808
  int i;
 
809
  if (rol->flags & RG_ENABLE)
 
810
    msg (level, "  [redirect_default_gateway local=%d]",
 
811
         (rol->flags & RG_LOCAL) != 0);
 
812
  for (i = 0; i < rol->n; ++i)
 
813
    print_route_option (&rol->routes[i], level);
 
814
}
 
815
 
 
816
#endif
 
817
 
 
818
static void
 
819
print_route (const struct route *r, int level)
 
820
{
 
821
  struct gc_arena gc = gc_new ();
 
822
  if (r->defined)
 
823
    msg (level, "%s", route_string (r, &gc));
 
824
  gc_free (&gc);
 
825
}
 
826
 
 
827
void
 
828
print_routes (const struct route_list *rl, int level)
 
829
{
 
830
  int i;
 
831
  for (i = 0; i < rl->n; ++i)
 
832
    print_route (&rl->routes[i], level);
 
833
}
 
834
 
 
835
static void
 
836
setenv_route (struct env_set *es, const struct route *r, int i)
 
837
{
 
838
  struct gc_arena gc = gc_new ();
 
839
  if (r->defined)
 
840
    {
 
841
      setenv_route_addr (es, "network", r->network, i);
 
842
      setenv_route_addr (es, "netmask", r->netmask, i);
 
843
      setenv_route_addr (es, "gateway", r->gateway, i);
 
844
 
 
845
      if (r->metric_defined)
 
846
        {
 
847
          struct buffer name = alloc_buf_gc (256, &gc);
 
848
          buf_printf (&name, "route_metric_%d", i);
 
849
          setenv_int (es, BSTR (&name), r->metric);
 
850
        }
 
851
    }
 
852
  gc_free (&gc);
 
853
}
 
854
 
 
855
void
 
856
setenv_routes (struct env_set *es, const struct route_list *rl)
 
857
{
 
858
  int i;
 
859
  for (i = 0; i < rl->n; ++i)
 
860
    setenv_route (es, &rl->routes[i], i + 1);
 
861
}
 
862
 
 
863
void
 
864
add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
 
865
{
 
866
  struct gc_arena gc;
 
867
  struct argv argv;
 
868
  const char *network;
 
869
  const char *netmask;
 
870
  const char *gateway;
 
871
  bool status = false;
 
872
 
 
873
  if (!r->defined)
 
874
    return;
 
875
 
 
876
  gc_init (&gc);
 
877
  argv_init (&argv);
 
878
 
 
879
  network = print_in_addr_t (r->network, 0, &gc);
 
880
  netmask = print_in_addr_t (r->netmask, 0, &gc);
 
881
  gateway = print_in_addr_t (r->gateway, 0, &gc);
 
882
 
 
883
  /*
 
884
   * Filter out routes which are essentially no-ops
 
885
   */
 
886
  if (r->network == r->gateway && r->netmask == 0xFFFFFFFF)
 
887
    {
 
888
      msg (M_INFO, PACKAGE_NAME " ROUTE: omitted no-op route: %s/%s -> %s",
 
889
           network, netmask, gateway);
 
890
      goto done;
 
891
    }
 
892
 
 
893
#if defined(TARGET_LINUX)
 
894
#ifdef CONFIG_FEATURE_IPROUTE
 
895
  argv_printf (&argv, "%s route add %s/%d via %s",
 
896
              iproute_path,
 
897
              network,
 
898
              count_netmask_bits(netmask),
 
899
              gateway);
 
900
  if (r->metric_defined)
 
901
    argv_printf_cat (&argv, "metric %d", r->metric);
 
902
 
 
903
#else
 
904
  argv_printf (&argv, "%s add -net %s netmask %s gw %s",
 
905
                ROUTE_PATH,
 
906
              network,
 
907
              netmask,
 
908
              gateway);
 
909
  if (r->metric_defined)
 
910
    argv_printf_cat (&argv, "metric %d", r->metric);
 
911
#endif  /*CONFIG_FEATURE_IPROUTE*/
 
912
  argv_msg (D_ROUTE, &argv);
 
913
  status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route add command failed");
 
914
 
 
915
#elif defined (WIN32)
 
916
 
 
917
  argv_printf (&argv, "%s%sc ADD %s MASK %s %s",
 
918
               get_win_sys_path(),
 
919
               WIN_ROUTE_PATH_SUFFIX,
 
920
               network,
 
921
               netmask,
 
922
               gateway);
 
923
  if (r->metric_defined)
 
924
    argv_printf_cat (&argv, "METRIC %d", r->metric);
 
925
 
 
926
  argv_msg (D_ROUTE, &argv);
 
927
 
 
928
  if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_IPAPI)
 
929
    {
 
930
      status = add_route_ipapi (r, tt);
 
931
      msg (D_ROUTE, "Route addition via IPAPI %s", status ? "succeeded" : "failed");
 
932
    }
 
933
  else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_EXE)
 
934
    {
 
935
      netcmd_semaphore_lock ();
 
936
      status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add command failed");
 
937
      netcmd_semaphore_release ();
 
938
    }
 
939
  else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_ADAPTIVE)
 
940
    {
 
941
      status = add_route_ipapi (r, tt);
 
942
      msg (D_ROUTE, "Route addition via IPAPI %s [adaptive]", status ? "succeeded" : "failed");
 
943
      if (!status)
 
944
        {
 
945
          msg (D_ROUTE, "Route addition fallback to route.exe");
 
946
          netcmd_semaphore_lock ();
 
947
          status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add command failed [adaptive]");
 
948
          netcmd_semaphore_release ();
 
949
        }
 
950
    }
 
951
  else
 
952
    {
 
953
      ASSERT (0);
 
954
    }
 
955
 
 
956
#elif defined (TARGET_SOLARIS)
 
957
 
 
958
  /* example: route add 192.0.2.32 -netmask 255.255.255.224 somegateway */
 
959
 
 
960
  argv_printf (&argv, "%s add",
 
961
                ROUTE_PATH);
 
962
 
 
963
#if 0
 
964
  if (r->metric_defined)
 
965
    argv_printf_cat (&argv, "-rtt %d", r->metric);
 
966
#endif
 
967
 
 
968
  argv_printf_cat (&argv, "%s -netmask %s %s",
 
969
              network,
 
970
              netmask,
 
971
              gateway);
 
972
 
 
973
  argv_msg (D_ROUTE, &argv);
 
974
  status = openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route add command failed");
 
975
 
 
976
#elif defined(TARGET_FREEBSD)
 
977
 
 
978
  argv_printf (&argv, "%s add",
 
979
                ROUTE_PATH);
 
980
 
 
981
#if 0
 
982
  if (r->metric_defined)
 
983
    argv_printf_cat (&argv, "-rtt %d", r->metric);
 
984
#endif
 
985
 
 
986
  argv_printf_cat (&argv, "-net %s %s %s",
 
987
              network,
 
988
              gateway,
 
989
              netmask);
 
990
 
 
991
  argv_msg (D_ROUTE, &argv);
 
992
  status = openvpn_execve_check (&argv, es, 0, "ERROR: FreeBSD route add command failed");
 
993
 
 
994
#elif defined(TARGET_DRAGONFLY)
 
995
 
 
996
  argv_printf (&argv, "%s add",
 
997
                ROUTE_PATH);
 
998
 
 
999
#if 0
 
1000
  if (r->metric_defined)
 
1001
    argv_printf_cat (&argv, "-rtt %d", r->metric);
 
1002
#endif
 
1003
 
 
1004
  argv_printf_cat (&argv, "-net %s %s %s",
 
1005
              network,
 
1006
              gateway,
 
1007
              netmask);
 
1008
 
 
1009
  argv_msg (D_ROUTE, &argv);
 
1010
  status = openvpn_execve_check (&argv, es, 0, "ERROR: DragonFly route add command failed");
 
1011
 
 
1012
#elif defined(TARGET_DARWIN)
 
1013
 
 
1014
  argv_printf (&argv, "%s add",
 
1015
                ROUTE_PATH);
 
1016
 
 
1017
#if 0
 
1018
  if (r->metric_defined)
 
1019
    argv_printf_cat (&argv, "-rtt %d", r->metric);
 
1020
#endif
 
1021
 
 
1022
  argv_printf_cat (&argv, "-net %s %s %s",
 
1023
              network,
 
1024
              gateway,
 
1025
              netmask);
 
1026
 
 
1027
  argv_msg (D_ROUTE, &argv);
 
1028
  status = openvpn_execve_check (&argv, es, 0, "ERROR: OS X route add command failed");
 
1029
 
 
1030
#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
 
1031
 
 
1032
  argv_printf (&argv, "%s add",
 
1033
                ROUTE_PATH);
 
1034
 
 
1035
#if 0
 
1036
  if (r->metric_defined)
 
1037
    argv_printf_cat (&argv, "-rtt %d", r->metric);
 
1038
#endif
 
1039
 
 
1040
  argv_printf_cat (&argv, "-net %s %s -netmask %s",
 
1041
              network,
 
1042
              gateway,
 
1043
              netmask);
 
1044
 
 
1045
  argv_msg (D_ROUTE, &argv);
 
1046
  status = openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route add command failed");
 
1047
 
 
1048
#else
 
1049
  msg (M_FATAL, "Sorry, but I don't know how to do 'route' commands on this operating system.  Try putting your routes in a --route-up script");
 
1050
#endif
 
1051
 
 
1052
 done:
 
1053
  r->defined = status;
 
1054
  argv_reset (&argv);
 
1055
  gc_free (&gc);
 
1056
}
 
1057
 
 
1058
static void
 
1059
delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
 
1060
{
 
1061
  struct gc_arena gc;
 
1062
  struct argv argv;
 
1063
  const char *network;
 
1064
  const char *netmask;
 
1065
  const char *gateway;
 
1066
 
 
1067
  if (!r->defined)
 
1068
    return;
 
1069
 
 
1070
  gc_init (&gc);
 
1071
  argv_init (&argv);
 
1072
 
 
1073
  network = print_in_addr_t (r->network, 0, &gc);
 
1074
  netmask = print_in_addr_t (r->netmask, 0, &gc);
 
1075
  gateway = print_in_addr_t (r->gateway, 0, &gc);
 
1076
 
 
1077
#if defined(TARGET_LINUX)
 
1078
#ifdef CONFIG_FEATURE_IPROUTE
 
1079
  argv_printf (&argv, "%s route del %s/%d",
 
1080
              iproute_path,
 
1081
              network,
 
1082
              count_netmask_bits(netmask));
 
1083
#else
 
1084
 
 
1085
  argv_printf (&argv, "%s del -net %s netmask %s",
 
1086
                ROUTE_PATH,
 
1087
              network,
 
1088
              netmask);
 
1089
#endif /*CONFIG_FEATURE_IPROUTE*/
 
1090
  if (r->metric_defined)
 
1091
    argv_printf_cat (&argv, "metric %d", r->metric);
 
1092
  argv_msg (D_ROUTE, &argv);
 
1093
  openvpn_execve_check (&argv, es, 0, "ERROR: Linux route delete command failed");
 
1094
 
 
1095
#elif defined (WIN32)
 
1096
  
 
1097
  argv_printf (&argv, "%s%sc DELETE %s MASK %s %s",
 
1098
               get_win_sys_path(),
 
1099
               WIN_ROUTE_PATH_SUFFIX,
 
1100
               network,
 
1101
               netmask,
 
1102
               gateway);
 
1103
 
 
1104
  argv_msg (D_ROUTE, &argv);
 
1105
 
 
1106
  if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_IPAPI)
 
1107
    {
 
1108
      const bool status = del_route_ipapi (r, tt);
 
1109
      msg (D_ROUTE, "Route deletion via IPAPI %s", status ? "succeeded" : "failed");
 
1110
    }
 
1111
  else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_EXE)
 
1112
    {
 
1113
      netcmd_semaphore_lock ();
 
1114
      openvpn_execve_check (&argv, es, 0, "ERROR: Windows route delete command failed");
 
1115
      netcmd_semaphore_release ();
 
1116
    }
 
1117
  else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_ADAPTIVE)
 
1118
    {
 
1119
      const bool status = del_route_ipapi (r, tt);
 
1120
      msg (D_ROUTE, "Route deletion via IPAPI %s [adaptive]", status ? "succeeded" : "failed");
 
1121
      if (!status)
 
1122
        {
 
1123
          msg (D_ROUTE, "Route deletion fallback to route.exe");
 
1124
          netcmd_semaphore_lock ();
 
1125
          openvpn_execve_check (&argv, es, 0, "ERROR: Windows route delete command failed [adaptive]");
 
1126
          netcmd_semaphore_release ();
 
1127
        }
 
1128
    }
 
1129
  else
 
1130
    {
 
1131
      ASSERT (0);
 
1132
    }
 
1133
 
 
1134
#elif defined (TARGET_SOLARIS)
 
1135
 
 
1136
  argv_printf (&argv, "%s delete %s -netmask %s %s",
 
1137
                ROUTE_PATH,
 
1138
              network,
 
1139
              netmask,
 
1140
              gateway);
 
1141
 
 
1142
  argv_msg (D_ROUTE, &argv);
 
1143
  openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route delete command failed");
 
1144
 
 
1145
#elif defined(TARGET_FREEBSD)
 
1146
 
 
1147
  argv_printf (&argv, "%s delete -net %s %s %s",
 
1148
                ROUTE_PATH,
 
1149
              network,
 
1150
              gateway,
 
1151
              netmask);
 
1152
 
 
1153
  argv_msg (D_ROUTE, &argv);
 
1154
  openvpn_execve_check (&argv, es, 0, "ERROR: FreeBSD route delete command failed");
 
1155
 
 
1156
#elif defined(TARGET_DRAGONFLY)
 
1157
 
 
1158
  argv_printf (&argv, "%s delete -net %s %s %s",
 
1159
                ROUTE_PATH,
 
1160
              network,
 
1161
              gateway,
 
1162
              netmask);
 
1163
 
 
1164
  argv_msg (D_ROUTE, &argv);
 
1165
  openvpn_execve_check (&argv, es, 0, "ERROR: DragonFly route delete command failed");
 
1166
 
 
1167
#elif defined(TARGET_DARWIN)
 
1168
 
 
1169
  argv_printf (&argv, "%s delete -net %s %s %s",
 
1170
                ROUTE_PATH,
 
1171
              network,
 
1172
              gateway,
 
1173
              netmask);
 
1174
 
 
1175
  argv_msg (D_ROUTE, &argv);
 
1176
  openvpn_execve_check (&argv, es, 0, "ERROR: OS X route delete command failed");
 
1177
 
 
1178
#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
 
1179
 
 
1180
  argv_printf (&argv, "%s delete -net %s %s -netmask %s",
 
1181
                ROUTE_PATH,
 
1182
              network,
 
1183
              gateway,
 
1184
              netmask);
 
1185
 
 
1186
  argv_msg (D_ROUTE, &argv);
 
1187
  openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route delete command failed");
 
1188
 
 
1189
#else
 
1190
  msg (M_FATAL, "Sorry, but I don't know how to do 'route' commands on this operating system.  Try putting your routes in a --route-up script");
 
1191
#endif
 
1192
 
 
1193
  argv_reset (&argv);
 
1194
  gc_free (&gc);
 
1195
}
 
1196
 
 
1197
/*
 
1198
 * The --redirect-gateway option requires OS-specific code below
 
1199
 * to get the current default gateway.
 
1200
 */
 
1201
 
 
1202
#if defined(WIN32)
 
1203
 
 
1204
static const MIB_IPFORWARDTABLE *
 
1205
get_windows_routing_table (struct gc_arena *gc)
 
1206
{
 
1207
  ULONG size = 0;
 
1208
  PMIB_IPFORWARDTABLE rt = NULL;
 
1209
  DWORD status;
 
1210
 
 
1211
  status = GetIpForwardTable (NULL, &size, TRUE);
 
1212
  if (status == ERROR_INSUFFICIENT_BUFFER)
 
1213
    {
 
1214
      rt = (PMIB_IPFORWARDTABLE) gc_malloc (size, false, gc);
 
1215
      status = GetIpForwardTable (rt, &size, TRUE);
 
1216
      if (status != NO_ERROR)
 
1217
        {
 
1218
          msg (D_ROUTE, "NOTE: GetIpForwardTable returned error: %s (code=%u)",
 
1219
               strerror_win32 (status, gc),
 
1220
               (unsigned int)status);
 
1221
          rt = NULL;
 
1222
        }
 
1223
    }
 
1224
  return rt;
 
1225
}
 
1226
 
 
1227
static int
 
1228
test_route (const IP_ADAPTER_INFO *adapters,
 
1229
            const in_addr_t gateway,
 
1230
            DWORD *index)
 
1231
{
 
1232
  int count = 0;
 
1233
  DWORD i = adapter_index_of_ip (adapters, gateway, &count, NULL);
 
1234
  if (index)
 
1235
    *index = i;
 
1236
  return count;
 
1237
}
 
1238
 
 
1239
static void
 
1240
test_route_helper (bool *ret,
 
1241
                   int *count,
 
1242
                   int *good,
 
1243
                   int *ambig,
 
1244
                   const IP_ADAPTER_INFO *adapters,
 
1245
                   const in_addr_t gateway)
 
1246
{
 
1247
  int c;
 
1248
 
 
1249
  ++*count;
 
1250
  c = test_route (adapters, gateway, NULL);
 
1251
  if (c == 0)
 
1252
    *ret = false;
 
1253
  else
 
1254
    ++*good;
 
1255
  if (c > 1)
 
1256
    ++*ambig;
 
1257
}
 
1258
 
 
1259
/*
 
1260
 * If we tried to add routes now, would we succeed?
 
1261
 */
 
1262
bool
 
1263
test_routes (const struct route_list *rl, const struct tuntap *tt)
 
1264
{
 
1265
  struct gc_arena gc = gc_new ();
 
1266
  const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
 
1267
  bool ret = false;
 
1268
  int count = 0;
 
1269
  int good = 0;
 
1270
  int ambig = 0;
 
1271
  bool adapter_up = false;
 
1272
 
 
1273
  if (is_adapter_up (tt, adapters))
 
1274
    {
 
1275
      ret = true;
 
1276
      adapter_up = true;
 
1277
 
 
1278
      if (rl)
 
1279
        {
 
1280
          int i;
 
1281
          for (i = 0; i < rl->n; ++i)
 
1282
            test_route_helper (&ret, &count, &good, &ambig, adapters, rl->routes[i].gateway);
 
1283
 
 
1284
          if ((rl->flags & RG_ENABLE) && rl->spec.remote_endpoint_defined)
 
1285
            test_route_helper (&ret, &count, &good, &ambig, adapters, rl->spec.remote_endpoint);
 
1286
        }
 
1287
    }
 
1288
 
 
1289
  msg (D_ROUTE, "TEST ROUTES: %d/%d succeeded len=%d ret=%d a=%d u/d=%s",
 
1290
       good,
 
1291
       count,
 
1292
       rl ? rl->n : -1,
 
1293
       (int)ret,
 
1294
       ambig,
 
1295
       adapter_up ? "up" : "down");
 
1296
 
 
1297
  gc_free (&gc);
 
1298
  return ret;
 
1299
}
 
1300
 
 
1301
static const MIB_IPFORWARDROW *
 
1302
get_default_gateway_row (const MIB_IPFORWARDTABLE *routes)
 
1303
{
 
1304
  struct gc_arena gc = gc_new ();
 
1305
  DWORD lowest_metric = ~0;
 
1306
  const MIB_IPFORWARDROW *ret = NULL;
 
1307
  int i;
 
1308
  int best = -1;
 
1309
 
 
1310
  if (routes)
 
1311
    {
 
1312
      for (i = 0; i < routes->dwNumEntries; ++i)
 
1313
        {
 
1314
          const MIB_IPFORWARDROW *row = &routes->table[i];
 
1315
          const in_addr_t net = ntohl (row->dwForwardDest);
 
1316
          const in_addr_t mask = ntohl (row->dwForwardMask);
 
1317
          const DWORD index = row->dwForwardIfIndex;
 
1318
          const DWORD metric = row->dwForwardMetric1;
 
1319
 
 
1320
          dmsg (D_ROUTE_DEBUG, "GDGR: route[%d] %s/%s i=%d m=%d",
 
1321
                i,
 
1322
                print_in_addr_t ((in_addr_t) net, 0, &gc),
 
1323
                print_in_addr_t ((in_addr_t) mask, 0, &gc),
 
1324
                (int)index,
 
1325
                (int)metric);
 
1326
 
 
1327
          if (!net && !mask && metric < lowest_metric)
 
1328
            {
 
1329
              ret = row;
 
1330
              lowest_metric = metric;
 
1331
              best = i;
 
1332
            }
 
1333
        }
 
1334
    }
 
1335
 
 
1336
  dmsg (D_ROUTE_DEBUG, "GDGR: best=%d lm=%u", best, (unsigned int)lowest_metric);
 
1337
 
 
1338
  gc_free (&gc);
 
1339
  return ret;
 
1340
}
 
1341
 
 
1342
bool
 
1343
get_default_gateway (in_addr_t *gw, in_addr_t *netmask)
 
1344
{
 
1345
  struct gc_arena gc = gc_new ();
 
1346
  bool ret_bool = false;
 
1347
 
 
1348
  const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
 
1349
  const MIB_IPFORWARDTABLE *routes = get_windows_routing_table (&gc);
 
1350
  const MIB_IPFORWARDROW *row = get_default_gateway_row (routes);
 
1351
 
 
1352
  if (row)
 
1353
    {
 
1354
      *gw = ntohl (row->dwForwardNextHop);
 
1355
      if (netmask)
 
1356
        {
 
1357
          if (adapter_index_of_ip (adapters, *gw, NULL, netmask) == ~0)
 
1358
            *netmask = ~0;
 
1359
        }
 
1360
      ret_bool = true;
 
1361
    }
 
1362
 
 
1363
  gc_free (&gc);
 
1364
  return ret_bool;
 
1365
}
 
1366
 
 
1367
static DWORD
 
1368
windows_route_find_if_index (const struct route *r, const struct tuntap *tt)
 
1369
{
 
1370
  struct gc_arena gc = gc_new ();
 
1371
  DWORD ret = ~0;
 
1372
  int count = 0;
 
1373
  const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
 
1374
  const IP_ADAPTER_INFO *tun_adapter = get_tun_adapter (tt, adapters);
 
1375
  bool on_tun = false;
 
1376
 
 
1377
  /* first test on tun interface */
 
1378
  if (is_ip_in_adapter_subnet (tun_adapter, r->gateway, NULL))
 
1379
    {
 
1380
      ret = tun_adapter->Index;
 
1381
      count = 1;
 
1382
      on_tun = true;
 
1383
    }
 
1384
  else /* test on other interfaces */
 
1385
    {
 
1386
      count = test_route (adapters, r->gateway, &ret);
 
1387
    }
 
1388
 
 
1389
  if (count == 0)
 
1390
    {
 
1391
      msg (M_WARN, "Warning: route gateway is not reachable on any active network adapters: %s",
 
1392
           print_in_addr_t (r->gateway, 0, &gc));
 
1393
      ret = ~0;
 
1394
    }
 
1395
  else if (count > 1)
 
1396
    {
 
1397
      msg (M_WARN, "Warning: route gateway is ambiguous: %s (%d matches)",
 
1398
           print_in_addr_t (r->gateway, 0, &gc),
 
1399
           count);
 
1400
      ret = ~0;
 
1401
    }
 
1402
 
 
1403
  dmsg (D_ROUTE_DEBUG, "DEBUG: route find if: on_tun=%d count=%d index=%d",
 
1404
       on_tun,
 
1405
       count,
 
1406
       (int)ret);
 
1407
 
 
1408
  gc_free (&gc);
 
1409
  return ret;
 
1410
}
 
1411
 
 
1412
bool
 
1413
add_route_ipapi (const struct route *r, const struct tuntap *tt)
 
1414
{
 
1415
  struct gc_arena gc = gc_new ();
 
1416
  bool ret = false;
 
1417
  DWORD status;
 
1418
  const DWORD if_index = windows_route_find_if_index (r, tt);  
 
1419
 
 
1420
  if (if_index != ~0)
 
1421
    {
 
1422
      MIB_IPFORWARDROW fr;
 
1423
      CLEAR (fr);
 
1424
      fr.dwForwardDest = htonl (r->network);
 
1425
      fr.dwForwardMask = htonl (r->netmask);
 
1426
      fr.dwForwardPolicy = 0;
 
1427
      fr.dwForwardNextHop = htonl (r->gateway);
 
1428
      fr.dwForwardIfIndex = if_index;
 
1429
      fr.dwForwardType = 4;  /* the next hop is not the final dest */
 
1430
      fr.dwForwardProto = 3; /* PROTO_IP_NETMGMT */
 
1431
      fr.dwForwardAge = 0;
 
1432
      fr.dwForwardNextHopAS = 0;
 
1433
      fr.dwForwardMetric1 = r->metric_defined ? r->metric : 1;
 
1434
      fr.dwForwardMetric2 = ~0;
 
1435
      fr.dwForwardMetric3 = ~0;
 
1436
      fr.dwForwardMetric4 = ~0;
 
1437
      fr.dwForwardMetric5 = ~0;
 
1438
 
 
1439
      if ((r->network & r->netmask) != r->network)
 
1440
        msg (M_WARN, "Warning: address %s is not a network address in relation to netmask %s",
 
1441
             print_in_addr_t (r->network, 0, &gc),
 
1442
             print_in_addr_t (r->netmask, 0, &gc));
 
1443
 
 
1444
      status = CreateIpForwardEntry (&fr);
 
1445
 
 
1446
      if (status == NO_ERROR)
 
1447
        ret = true;
 
1448
      else
 
1449
        {
 
1450
          /* failed, try increasing the metric to work around Vista issue */
 
1451
          const unsigned int forward_metric_limit = 2048; /* iteratively retry higher metrics up to this limit */
 
1452
 
 
1453
          for ( ; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
 
1454
            {
 
1455
              /* try a different forward type=3 ("the next hop is the final dest") in addition to 4.
 
1456
                 --redirect-gateway over RRAS seems to need this. */
 
1457
              for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
 
1458
                {
 
1459
                  status = CreateIpForwardEntry (&fr);
 
1460
                  if (status == NO_ERROR)
 
1461
                    {
 
1462
                      msg (D_ROUTE, "ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%u and dwForwardType=%u",
 
1463
                           (unsigned int)fr.dwForwardMetric1,
 
1464
                           (unsigned int)fr.dwForwardType);
 
1465
                      ret = true;
 
1466
                      goto doublebreak;
 
1467
                    }
 
1468
                  else if (status != ERROR_BAD_ARGUMENTS)
 
1469
                    goto doublebreak;
 
1470
                }
 
1471
            }
 
1472
 
 
1473
        doublebreak:
 
1474
          if (status != NO_ERROR)
 
1475
            msg (M_WARN, "ROUTE: route addition failed using CreateIpForwardEntry: %s [status=%u if_index=%u]",
 
1476
                 strerror_win32 (status, &gc),
 
1477
                 (unsigned int)status,
 
1478
                 (unsigned int)if_index);
 
1479
        }
 
1480
    }
 
1481
 
 
1482
  gc_free (&gc);
 
1483
  return ret;
 
1484
}
 
1485
 
 
1486
bool
 
1487
del_route_ipapi (const struct route *r, const struct tuntap *tt)
 
1488
{
 
1489
  struct gc_arena gc = gc_new ();
 
1490
  bool ret = false;
 
1491
  DWORD status;
 
1492
  const DWORD if_index = windows_route_find_if_index (r, tt);
 
1493
 
 
1494
  if (if_index != ~0)
 
1495
    {
 
1496
      MIB_IPFORWARDROW fr;
 
1497
      CLEAR (fr);
 
1498
 
 
1499
      fr.dwForwardDest = htonl (r->network);
 
1500
      fr.dwForwardMask = htonl (r->netmask);
 
1501
      fr.dwForwardPolicy = 0;
 
1502
      fr.dwForwardNextHop = htonl (r->gateway);
 
1503
      fr.dwForwardIfIndex = if_index;
 
1504
 
 
1505
      status = DeleteIpForwardEntry (&fr);
 
1506
 
 
1507
      if (status == NO_ERROR)
 
1508
        ret = true;
 
1509
      else
 
1510
        msg (M_WARN, "ROUTE: route deletion failed using DeleteIpForwardEntry: %s",
 
1511
             strerror_win32 (status, &gc));
 
1512
    }
 
1513
 
 
1514
  gc_free (&gc);
 
1515
  return ret;
 
1516
}
 
1517
 
 
1518
static const char *
 
1519
format_route_entry (const MIB_IPFORWARDROW *r, struct gc_arena *gc)
 
1520
{
 
1521
  struct buffer out = alloc_buf_gc (256, gc);
 
1522
  buf_printf (&out, "%s %s %s p=%d i=%d t=%d pr=%d a=%d h=%d m=%d/%d/%d/%d/%d", 
 
1523
              print_in_addr_t (r->dwForwardDest, IA_NET_ORDER, gc),
 
1524
              print_in_addr_t (r->dwForwardMask, IA_NET_ORDER, gc),
 
1525
              print_in_addr_t (r->dwForwardNextHop, IA_NET_ORDER, gc),
 
1526
              (int)r->dwForwardPolicy,
 
1527
              (int)r->dwForwardIfIndex,
 
1528
              (int)r->dwForwardType,
 
1529
              (int)r->dwForwardProto,
 
1530
              (int)r->dwForwardAge,
 
1531
              (int)r->dwForwardNextHopAS,
 
1532
              (int)r->dwForwardMetric1,
 
1533
              (int)r->dwForwardMetric2,
 
1534
              (int)r->dwForwardMetric3,
 
1535
              (int)r->dwForwardMetric4,
 
1536
              (int)r->dwForwardMetric5);
 
1537
  return BSTR (&out);
 
1538
}
 
1539
 
 
1540
/*
 
1541
 * Show current routing table
 
1542
 */
 
1543
void
 
1544
show_routes (int msglev)
 
1545
{
 
1546
  struct gc_arena gc = gc_new ();
 
1547
  int i;
 
1548
 
 
1549
  const MIB_IPFORWARDTABLE *rt = get_windows_routing_table (&gc);
 
1550
 
 
1551
  msg (msglev, "SYSTEM ROUTING TABLE");
 
1552
  if (rt)
 
1553
    {
 
1554
      for (i = 0; i < rt->dwNumEntries; ++i)
 
1555
        {
 
1556
          msg (msglev, "%s", format_route_entry (&rt->table[i], &gc));
 
1557
        }
 
1558
    }
 
1559
  gc_free (&gc);
 
1560
}
 
1561
 
 
1562
#elif defined(TARGET_LINUX)
 
1563
 
 
1564
bool
 
1565
get_default_gateway (in_addr_t *gateway, in_addr_t *netmask)
 
1566
{
 
1567
  struct gc_arena gc = gc_new ();
 
1568
  bool ret = false;
 
1569
  FILE *fp = fopen ("/proc/net/route", "r");
 
1570
  if (fp)
 
1571
    {
 
1572
      char line[256];
 
1573
      int count = 0;
 
1574
      int best_count = 0;
 
1575
      unsigned int lowest_metric = ~0;
 
1576
      in_addr_t best_gw = 0;
 
1577
      while (fgets (line, sizeof (line), fp) != NULL)
 
1578
        {
 
1579
          if (count)
 
1580
            {
 
1581
              unsigned int net_x = 0;
 
1582
              unsigned int mask_x = 0;
 
1583
              unsigned int gw_x = 0;
 
1584
              unsigned int metric = 0;
 
1585
              const int np = sscanf (line, "%*s\t%x\t%x\t%*s\t%*s\t%*s\t%d\t%x",
 
1586
                                     &net_x,
 
1587
                                     &gw_x,
 
1588
                                     &metric,
 
1589
                                     &mask_x);
 
1590
              if (np == 4)
 
1591
                {
 
1592
                  const in_addr_t net = ntohl (net_x);
 
1593
                  const in_addr_t mask = ntohl (mask_x);
 
1594
                  const in_addr_t gw = ntohl (gw_x);
 
1595
 
 
1596
                  dmsg (D_ROUTE_DEBUG, "GDG: route[%d] %s/%s/%s m=%u",
 
1597
                        count,
 
1598
                        print_in_addr_t ((in_addr_t) net, 0, &gc),
 
1599
                        print_in_addr_t ((in_addr_t) mask, 0, &gc),
 
1600
                        print_in_addr_t ((in_addr_t) gw, 0, &gc),
 
1601
                        metric);
 
1602
 
 
1603
                  if (!net && !mask && metric < lowest_metric)
 
1604
                    {
 
1605
                      best_gw = gw;
 
1606
                      lowest_metric = metric;
 
1607
                      best_count = count;
 
1608
                    }
 
1609
                }
 
1610
            }
 
1611
          ++count;
 
1612
        }
 
1613
      fclose (fp);
 
1614
 
 
1615
      if (best_gw)
 
1616
        {
 
1617
          *gateway = best_gw;
 
1618
          if (netmask)
 
1619
            {
 
1620
              *netmask = 0xFFFFFF00; /* FIXME -- get the real netmask of the adapter containing the default gateway */
 
1621
            }
 
1622
          ret = true;
 
1623
        }
 
1624
 
 
1625
      dmsg (D_ROUTE_DEBUG, "GDG: best=%s[%d] lm=%u",
 
1626
            print_in_addr_t ((in_addr_t) best_gw, 0, &gc),
 
1627
            best_count,
 
1628
            (unsigned int)lowest_metric);
 
1629
    }
 
1630
 
 
1631
  gc_free (&gc);
 
1632
  return ret;
 
1633
}
 
1634
 
 
1635
#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
 
1636
 
 
1637
#include <sys/types.h>
 
1638
#include <sys/socket.h>
 
1639
#include <netinet/in.h>
 
1640
 
 
1641
/* all of this is taken from <net/route.h> in FreeBSD */
 
1642
#define RTA_DST     0x1
 
1643
#define RTA_GATEWAY 0x2
 
1644
#define RTA_NETMASK 0x4
 
1645
 
 
1646
#define RTM_GET     0x4
 
1647
#define RTM_VERSION 5
 
1648
 
 
1649
#define RTF_UP      0x1
 
1650
#define RTF_GATEWAY 0x2
 
1651
 
 
1652
/*
 
1653
 * These numbers are used by reliable protocols for determining
 
1654
 * retransmission behavior and are included in the routing structure.
 
1655
 */
 
1656
struct rt_metrics {
 
1657
        u_long  rmx_locks;      /* Kernel must leave these values alone */
 
1658
        u_long  rmx_mtu;        /* MTU for this path */
 
1659
        u_long  rmx_hopcount;   /* max hops expected */
 
1660
        u_long  rmx_expire;     /* lifetime for route, e.g. redirect */
 
1661
        u_long  rmx_recvpipe;   /* inbound delay-bandwidth product */
 
1662
        u_long  rmx_sendpipe;   /* outbound delay-bandwidth product */
 
1663
        u_long  rmx_ssthresh;   /* outbound gateway buffer limit */
 
1664
        u_long  rmx_rtt;        /* estimated round trip time */
 
1665
        u_long  rmx_rttvar;     /* estimated rtt variance */
 
1666
        u_long  rmx_pksent;     /* packets sent using this route */
 
1667
        u_long  rmx_filler[4];  /* will be used for T/TCP later */
 
1668
};
 
1669
 
 
1670
/*
 
1671
 * Structures for routing messages.
 
1672
 */
 
1673
struct rt_msghdr {
 
1674
        u_short rtm_msglen;     /* to skip over non-understood messages */
 
1675
        u_char  rtm_version;    /* future binary compatibility */
 
1676
        u_char  rtm_type;       /* message type */
 
1677
        u_short rtm_index;      /* index for associated ifp */
 
1678
        int     rtm_flags;      /* flags, incl. kern & message, e.g. DONE */
 
1679
        int     rtm_addrs;      /* bitmask identifying sockaddrs in msg */
 
1680
        pid_t   rtm_pid;        /* identify sender */
 
1681
        int     rtm_seq;        /* for sender to identify action */
 
1682
        int     rtm_errno;      /* why failed */
 
1683
        int     rtm_use;        /* from rtentry */
 
1684
        u_long  rtm_inits;      /* which metrics we are initializing */
 
1685
        struct  rt_metrics rtm_rmx; /* metrics themselves */
 
1686
};
 
1687
 
 
1688
struct {
 
1689
  struct rt_msghdr m_rtm;
 
1690
  char       m_space[512];
 
1691
} m_rtmsg;
 
1692
 
 
1693
#define ROUNDUP(a) \
 
1694
        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
 
1695
 
 
1696
bool
 
1697
get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
 
1698
{
 
1699
  struct gc_arena gc = gc_new ();
 
1700
  int s, seq, l, pid, rtm_addrs, i;
 
1701
  struct sockaddr so_dst, so_mask;
 
1702
  char *cp = m_rtmsg.m_space; 
 
1703
  struct sockaddr *gate = NULL, *sa;
 
1704
  struct  rt_msghdr *rtm_aux;
 
1705
 
 
1706
#define NEXTADDR(w, u) \
 
1707
        if (rtm_addrs & (w)) {\
 
1708
            l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
 
1709
        }
 
1710
 
 
1711
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
 
1712
 
 
1713
#define rtm m_rtmsg.m_rtm
 
1714
 
 
1715
  pid = getpid();
 
1716
  seq = 0;
 
1717
  rtm_addrs = RTA_DST | RTA_NETMASK;
 
1718
 
 
1719
  bzero(&so_dst, sizeof(so_dst));
 
1720
  bzero(&so_mask, sizeof(so_mask));
 
1721
  bzero(&rtm, sizeof(struct rt_msghdr));
 
1722
 
 
1723
  rtm.rtm_type = RTM_GET;
 
1724
  rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
 
1725
  rtm.rtm_version = RTM_VERSION;
 
1726
  rtm.rtm_seq = ++seq;
 
1727
  rtm.rtm_addrs = rtm_addrs; 
 
1728
 
 
1729
  so_dst.sa_family = AF_INET;
 
1730
  so_dst.sa_len = sizeof(struct sockaddr_in);
 
1731
  so_mask.sa_family = AF_INET;
 
1732
  so_mask.sa_len = sizeof(struct sockaddr_in);
 
1733
 
 
1734
  NEXTADDR(RTA_DST, so_dst);
 
1735
  NEXTADDR(RTA_NETMASK, so_mask);
 
1736
 
 
1737
  rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
 
1738
 
 
1739
  s = socket(PF_ROUTE, SOCK_RAW, 0);
 
1740
 
 
1741
  if (write(s, (char *)&m_rtmsg, l) < 0)
 
1742
    {
 
1743
      warn("writing to routing socket");
 
1744
      gc_free (&gc);
 
1745
      close(s);
 
1746
      return false;
 
1747
    }
 
1748
 
 
1749
  do {
 
1750
    l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
 
1751
  } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
 
1752
                        
 
1753
  close(s);
 
1754
 
 
1755
  rtm_aux = &rtm;
 
1756
 
 
1757
  cp = ((char *)(rtm_aux + 1));
 
1758
  if (rtm_aux->rtm_addrs) {
 
1759
    for (i = 1; i; i <<= 1)
 
1760
      if (i & rtm_aux->rtm_addrs) {
 
1761
        sa = (struct sockaddr *)cp;
 
1762
        if (i == RTA_GATEWAY )
 
1763
          gate = sa;
 
1764
        ADVANCE(cp, sa);
 
1765
      }
 
1766
  }
 
1767
  else
 
1768
    {
 
1769
      gc_free (&gc);
 
1770
      return false;
 
1771
    }
 
1772
 
 
1773
 
 
1774
  if (gate != NULL )
 
1775
    {
 
1776
      *ret = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
 
1777
#if 0
 
1778
      msg (M_INFO, "gw %s",
 
1779
           print_in_addr_t ((in_addr_t) *ret, 0, &gc));
 
1780
#endif
 
1781
 
 
1782
      if (netmask)
 
1783
        {
 
1784
          *netmask = 0xFFFFFF00; // FIXME -- get the real netmask of the adapter containing the default gateway
 
1785
        }
 
1786
 
 
1787
      gc_free (&gc);
 
1788
      return true;
 
1789
    }
 
1790
  else
 
1791
    {
 
1792
      gc_free (&gc);
 
1793
      return false;
 
1794
    }
 
1795
}
 
1796
 
 
1797
#elif defined(TARGET_DARWIN)
 
1798
 
 
1799
#include <sys/types.h>
 
1800
#include <sys/socket.h>
 
1801
#include <netinet/in.h>
 
1802
 
 
1803
/* all of this is taken from <net/route.h> in Darwin */
 
1804
#define RTA_DST     0x1
 
1805
#define RTA_GATEWAY 0x2
 
1806
#define RTA_NETMASK 0x4
 
1807
 
 
1808
#define RTM_GET     0x4
 
1809
#define RTM_VERSION 5
 
1810
 
 
1811
#define RTF_UP      0x1
 
1812
#define RTF_GATEWAY 0x2
 
1813
 
 
1814
/*
 
1815
 * These numbers are used by reliable protocols for determining
 
1816
 * retransmission behavior and are included in the routing structure.
 
1817
 */
 
1818
struct rt_metrics {
 
1819
        u_long  rmx_locks;      /* Kernel must leave these values alone */
 
1820
        u_long  rmx_mtu;        /* MTU for this path */
 
1821
        u_long  rmx_hopcount;   /* max hops expected */
 
1822
        u_long  rmx_expire;     /* lifetime for route, e.g. redirect */
 
1823
        u_long  rmx_recvpipe;   /* inbound delay-bandwidth product */
 
1824
        u_long  rmx_sendpipe;   /* outbound delay-bandwidth product */
 
1825
        u_long  rmx_ssthresh;   /* outbound gateway buffer limit */
 
1826
        u_long  rmx_rtt;        /* estimated round trip time */
 
1827
        u_long  rmx_rttvar;     /* estimated rtt variance */
 
1828
        u_long  rmx_pksent;     /* packets sent using this route */
 
1829
        u_long  rmx_filler[4];  /* will be used for T/TCP later */
 
1830
};
 
1831
 
 
1832
/*
 
1833
 * Structures for routing messages.
 
1834
 */
 
1835
struct rt_msghdr {
 
1836
        u_short rtm_msglen;     /* to skip over non-understood messages */
 
1837
        u_char  rtm_version;    /* future binary compatibility */
 
1838
        u_char  rtm_type;       /* message type */
 
1839
        u_short rtm_index;      /* index for associated ifp */
 
1840
        int     rtm_flags;      /* flags, incl. kern & message, e.g. DONE */
 
1841
        int     rtm_addrs;      /* bitmask identifying sockaddrs in msg */
 
1842
        pid_t   rtm_pid;        /* identify sender */
 
1843
        int     rtm_seq;        /* for sender to identify action */
 
1844
        int     rtm_errno;      /* why failed */
 
1845
        int     rtm_use;        /* from rtentry */
 
1846
        u_long  rtm_inits;      /* which metrics we are initializing */
 
1847
        struct  rt_metrics rtm_rmx; /* metrics themselves */
 
1848
};
 
1849
 
 
1850
struct {
 
1851
  struct rt_msghdr m_rtm;
 
1852
  char       m_space[512];
 
1853
} m_rtmsg;
 
1854
 
 
1855
#define ROUNDUP(a) \
 
1856
        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
 
1857
 
 
1858
bool
 
1859
get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
 
1860
{
 
1861
  struct gc_arena gc = gc_new ();
 
1862
  int s, seq, l, pid, rtm_addrs, i;
 
1863
  struct sockaddr so_dst, so_mask;
 
1864
  char *cp = m_rtmsg.m_space; 
 
1865
  struct sockaddr *gate = NULL, *sa;
 
1866
  struct  rt_msghdr *rtm_aux;
 
1867
 
 
1868
#define NEXTADDR(w, u) \
 
1869
        if (rtm_addrs & (w)) {\
 
1870
            l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
 
1871
        }
 
1872
 
 
1873
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
 
1874
 
 
1875
#define rtm m_rtmsg.m_rtm
 
1876
 
 
1877
  pid = getpid();
 
1878
  seq = 0;
 
1879
  rtm_addrs = RTA_DST | RTA_NETMASK;
 
1880
 
 
1881
  bzero(&so_dst, sizeof(so_dst));
 
1882
  bzero(&so_mask, sizeof(so_mask));
 
1883
  bzero(&rtm, sizeof(struct rt_msghdr));
 
1884
 
 
1885
  rtm.rtm_type = RTM_GET;
 
1886
  rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
 
1887
  rtm.rtm_version = RTM_VERSION;
 
1888
  rtm.rtm_seq = ++seq;
 
1889
  rtm.rtm_addrs = rtm_addrs; 
 
1890
 
 
1891
  so_dst.sa_family = AF_INET;
 
1892
  so_dst.sa_len = sizeof(struct sockaddr_in);
 
1893
  so_mask.sa_family = AF_INET;
 
1894
  so_mask.sa_len = sizeof(struct sockaddr_in);
 
1895
 
 
1896
  NEXTADDR(RTA_DST, so_dst);
 
1897
  NEXTADDR(RTA_NETMASK, so_mask);
 
1898
 
 
1899
  rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
 
1900
 
 
1901
  s = socket(PF_ROUTE, SOCK_RAW, 0);
 
1902
 
 
1903
  if (write(s, (char *)&m_rtmsg, l) < 0)
 
1904
    {
 
1905
      msg (M_WARN, "ROUTE: problem writing to routing socket");
 
1906
      gc_free (&gc);
 
1907
      close(s);
 
1908
      return false;
 
1909
    }
 
1910
 
 
1911
  do {
 
1912
    l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
 
1913
  } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
 
1914
                        
 
1915
  close(s);
 
1916
 
 
1917
  rtm_aux = &rtm;
 
1918
 
 
1919
  cp = ((char *)(rtm_aux + 1));
 
1920
  if (rtm_aux->rtm_addrs) {
 
1921
    for (i = 1; i; i <<= 1)
 
1922
      if (i & rtm_aux->rtm_addrs) {
 
1923
        sa = (struct sockaddr *)cp;
 
1924
        if (i == RTA_GATEWAY )
 
1925
          gate = sa;
 
1926
        ADVANCE(cp, sa);
 
1927
      }
 
1928
  }
 
1929
  else
 
1930
    {
 
1931
      gc_free (&gc);
 
1932
      return false;
 
1933
    }
 
1934
 
 
1935
 
 
1936
  if (gate != NULL )
 
1937
    {
 
1938
      *ret = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
 
1939
#if 0
 
1940
      msg (M_INFO, "gw %s",
 
1941
           print_in_addr_t ((in_addr_t) *ret, 0, &gc));
 
1942
#endif
 
1943
 
 
1944
      if (netmask)
 
1945
        {
 
1946
          *netmask = 0xFFFFFF00; // FIXME -- get the real netmask of the adapter containing the default gateway
 
1947
        }
 
1948
 
 
1949
      gc_free (&gc);
 
1950
      return true;
 
1951
    }
 
1952
  else
 
1953
    {
 
1954
      gc_free (&gc);
 
1955
      return false;
 
1956
    }
 
1957
}
 
1958
 
 
1959
#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
 
1960
 
 
1961
#include <sys/types.h>
 
1962
#include <sys/socket.h>
 
1963
#include <netinet/in.h>
 
1964
 
 
1965
/* all of this is taken from <net/route.h> in OpenBSD 3.6 */
 
1966
#define RTA_DST         0x1     /* destination sockaddr present */
 
1967
#define RTA_GATEWAY     0x2     /* gateway sockaddr present */
 
1968
#define RTA_NETMASK     0x4     /* netmask sockaddr present */
 
1969
 
 
1970
#define RTM_GET         0x4     /* Report Metrics */
 
1971
 
 
1972
#define RTM_VERSION     3       /* Up the ante and ignore older versions */
 
1973
 
 
1974
#define RTF_UP          0x1             /* route usable */
 
1975
#define RTF_GATEWAY     0x2             /* destination is a gateway */
 
1976
 
 
1977
/*
 
1978
 * Huge version for userland compatibility.
 
1979
 */
 
1980
struct rt_metrics {
 
1981
        u_long  rmx_locks;      /* Kernel must leave these values alone */
 
1982
        u_long  rmx_mtu;        /* MTU for this path */
 
1983
        u_long  rmx_hopcount;   /* max hops expected */
 
1984
        u_long  rmx_expire;     /* lifetime for route, e.g. redirect */
 
1985
        u_long  rmx_recvpipe;   /* inbound delay-bandwidth product */
 
1986
        u_long  rmx_sendpipe;   /* outbound delay-bandwidth product */
 
1987
        u_long  rmx_ssthresh;   /* outbound gateway buffer limit */
 
1988
        u_long  rmx_rtt;        /* estimated round trip time */
 
1989
        u_long  rmx_rttvar;     /* estimated rtt variance */
 
1990
        u_long  rmx_pksent;     /* packets sent using this route */
 
1991
};
 
1992
 
 
1993
/*
 
1994
 * Structures for routing messages.
 
1995
 */
 
1996
struct rt_msghdr {
 
1997
        u_short rtm_msglen;     /* to skip over non-understood messages */
 
1998
        u_char  rtm_version;    /* future binary compatibility */
 
1999
        u_char  rtm_type;       /* message type */
 
2000
        u_short rtm_index;      /* index for associated ifp */
 
2001
        int     rtm_flags;      /* flags, incl. kern & message, e.g. DONE */
 
2002
        int     rtm_addrs;      /* bitmask identifying sockaddrs in msg */
 
2003
        pid_t   rtm_pid;        /* identify sender */
 
2004
        int     rtm_seq;        /* for sender to identify action */
 
2005
        int     rtm_errno;      /* why failed */
 
2006
        int     rtm_use;        /* from rtentry */
 
2007
        u_long  rtm_inits;      /* which metrics we are initializing */
 
2008
        struct  rt_metrics rtm_rmx; /* metrics themselves */
 
2009
};
 
2010
 
 
2011
struct {
 
2012
  struct rt_msghdr m_rtm;
 
2013
  char       m_space[512];
 
2014
} m_rtmsg;
 
2015
 
 
2016
#define ROUNDUP(a) \
 
2017
        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
 
2018
 
 
2019
bool
 
2020
get_default_gateway (in_addr_t *ret, in_addr_t *netmask)
 
2021
{
 
2022
  struct gc_arena gc = gc_new ();
 
2023
  int s, seq, l, rtm_addrs, i;
 
2024
  pid_t pid;
 
2025
  struct sockaddr so_dst, so_mask;
 
2026
  char *cp = m_rtmsg.m_space; 
 
2027
  struct sockaddr *gate = NULL, *sa;
 
2028
  struct  rt_msghdr *rtm_aux;
 
2029
 
 
2030
#define NEXTADDR(w, u) \
 
2031
        if (rtm_addrs & (w)) {\
 
2032
            l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
 
2033
        }
 
2034
 
 
2035
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
 
2036
 
 
2037
#define rtm m_rtmsg.m_rtm
 
2038
 
 
2039
  pid = getpid();
 
2040
  seq = 0;
 
2041
  rtm_addrs = RTA_DST | RTA_NETMASK;
 
2042
 
 
2043
  bzero(&so_dst, sizeof(so_dst));
 
2044
  bzero(&so_mask, sizeof(so_mask));
 
2045
  bzero(&rtm, sizeof(struct rt_msghdr));
 
2046
 
 
2047
  rtm.rtm_type = RTM_GET;
 
2048
  rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
 
2049
  rtm.rtm_version = RTM_VERSION;
 
2050
  rtm.rtm_seq = ++seq;
 
2051
  rtm.rtm_addrs = rtm_addrs; 
 
2052
 
 
2053
  so_dst.sa_family = AF_INET;
 
2054
  so_dst.sa_len = sizeof(struct sockaddr_in);
 
2055
  so_mask.sa_family = AF_INET;
 
2056
  so_mask.sa_len = sizeof(struct sockaddr_in);
 
2057
 
 
2058
  NEXTADDR(RTA_DST, so_dst);
 
2059
  NEXTADDR(RTA_NETMASK, so_mask);
 
2060
 
 
2061
  rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
 
2062
 
 
2063
  s = socket(PF_ROUTE, SOCK_RAW, 0);
 
2064
 
 
2065
  if (write(s, (char *)&m_rtmsg, l) < 0)
 
2066
    {
 
2067
      warn("writing to routing socket");
 
2068
      gc_free (&gc);
 
2069
      close(s);
 
2070
      return false;
 
2071
    }
 
2072
 
 
2073
  do {
 
2074
    l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
 
2075
  } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
 
2076
                        
 
2077
  close(s);
 
2078
 
 
2079
  rtm_aux = &rtm;
 
2080
 
 
2081
  cp = ((char *)(rtm_aux + 1));
 
2082
  if (rtm_aux->rtm_addrs) {
 
2083
    for (i = 1; i; i <<= 1)
 
2084
      if (i & rtm_aux->rtm_addrs) {
 
2085
        sa = (struct sockaddr *)cp;
 
2086
        if (i == RTA_GATEWAY )
 
2087
          gate = sa;
 
2088
        ADVANCE(cp, sa);
 
2089
      }
 
2090
  }
 
2091
  else
 
2092
    {
 
2093
      gc_free (&gc);
 
2094
      return false;
 
2095
    }
 
2096
 
 
2097
 
 
2098
  if (gate != NULL )
 
2099
    {
 
2100
      *ret = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
 
2101
#if 0
 
2102
      msg (M_INFO, "gw %s",
 
2103
           print_in_addr_t ((in_addr_t) *ret, 0, &gc));
 
2104
#endif
 
2105
 
 
2106
      if (netmask)
 
2107
        {
 
2108
          *netmask = 0xFFFFFF00; // FIXME -- get the real netmask of the adapter containing the default gateway
 
2109
        }
 
2110
 
 
2111
      gc_free (&gc);
 
2112
      return true;
 
2113
    }
 
2114
  else
 
2115
    {
 
2116
      gc_free (&gc);
 
2117
      return false;
 
2118
    }
 
2119
}
 
2120
 
 
2121
#else
 
2122
 
 
2123
bool
 
2124
get_default_gateway (in_addr_t *ret, in_addr_t *netmask)  /* PLATFORM-SPECIFIC */
 
2125
{
 
2126
  return false;
 
2127
}
 
2128
 
 
2129
#endif
 
2130
 
 
2131
bool
 
2132
netmask_to_netbits (const in_addr_t network, const in_addr_t netmask, int *netbits)
 
2133
{
 
2134
  int i;
 
2135
  const int addrlen = sizeof (in_addr_t) * 8;
 
2136
 
 
2137
  if ((network & netmask) == network)
 
2138
    {
 
2139
      for (i = 0; i <= addrlen; ++i)
 
2140
        {
 
2141
          in_addr_t mask = netbits_to_netmask (i);
 
2142
          if (mask == netmask)
 
2143
            {
 
2144
              if (i == addrlen)
 
2145
                *netbits = -1;
 
2146
              else
 
2147
                *netbits = i;
 
2148
              return true;
 
2149
            }
 
2150
        }
 
2151
    }
 
2152
  return false;
 
2153
}
 
2154
 
 
2155
/*
 
2156
 * get_bypass_addresses() is used by the redirect-gateway bypass-x
 
2157
 * functions to build a route bypass to selected DHCP/DNS servers,
 
2158
 * so that outgoing packets to these servers don't end up in the tunnel.
 
2159
 */
 
2160
 
 
2161
#if defined(WIN32)
 
2162
 
 
2163
static void
 
2164
add_host_route_if_nonlocal (struct route_bypass *rb, const in_addr_t addr)
 
2165
{
 
2166
  if (test_local_addr(addr) == TLA_NONLOCAL && addr != 0 && addr != ~0)
 
2167
    add_bypass_address (rb, addr);
 
2168
}
 
2169
 
 
2170
static void
 
2171
add_host_route_array (struct route_bypass *rb, const IP_ADDR_STRING *iplist)
 
2172
{
 
2173
  while (iplist)
 
2174
    {
 
2175
      bool succeed = false;
 
2176
      const in_addr_t ip = getaddr (GETADDR_HOST_ORDER, iplist->IpAddress.String, 0, &succeed, NULL);
 
2177
      if (succeed)
 
2178
        {
 
2179
          add_host_route_if_nonlocal (rb, ip);
 
2180
        }
 
2181
      iplist = iplist->Next;
 
2182
    }
 
2183
}
 
2184
 
 
2185
static void
 
2186
get_bypass_addresses (struct route_bypass *rb, const unsigned int flags)
 
2187
{
 
2188
  struct gc_arena gc = gc_new ();
 
2189
  /*bool ret_bool = false;*/
 
2190
 
 
2191
  /* get full routing table */
 
2192
  const MIB_IPFORWARDTABLE *routes = get_windows_routing_table (&gc);
 
2193
 
 
2194
  /* get the route which represents the default gateway */
 
2195
  const MIB_IPFORWARDROW *row = get_default_gateway_row (routes);
 
2196
 
 
2197
  if (row)
 
2198
    {
 
2199
      /* get the adapter which the default gateway is associated with */
 
2200
      const IP_ADAPTER_INFO *dgi = get_adapter_info (row->dwForwardIfIndex, &gc);
 
2201
 
 
2202
      /* get extra adapter info, such as DNS addresses */
 
2203
      const IP_PER_ADAPTER_INFO *pai = get_per_adapter_info (row->dwForwardIfIndex, &gc);
 
2204
 
 
2205
      /* Bypass DHCP server address */
 
2206
      if ((flags & RG_BYPASS_DHCP) && dgi && dgi->DhcpEnabled)
 
2207
        add_host_route_array (rb, &dgi->DhcpServer);
 
2208
 
 
2209
      /* Bypass DNS server addresses */
 
2210
      if ((flags & RG_BYPASS_DNS) && pai)
 
2211
        add_host_route_array (rb, &pai->DnsServerList);
 
2212
    }
 
2213
 
 
2214
  gc_free (&gc);
 
2215
}
 
2216
 
 
2217
#else
 
2218
 
 
2219
static void
 
2220
get_bypass_addresses (struct route_bypass *rb, const unsigned int flags)  /* PLATFORM-SPECIFIC */
 
2221
{
 
2222
}
 
2223
 
 
2224
#endif
 
2225
 
 
2226
#if AUTO_USERID || defined(ENABLE_PUSH_PEER_INFO)
 
2227
 
 
2228
#if defined(TARGET_LINUX)
 
2229
 
 
2230
bool
 
2231
get_default_gateway_mac_addr (unsigned char *macaddr)
 
2232
{
 
2233
  struct ifreq *ifr, *ifend;
 
2234
  in_addr_t ina, mask;
 
2235
  struct ifreq ifreq;
 
2236
  struct ifconf ifc;
 
2237
  struct ifreq ifs[20]; // Maximum number of interfaces to scan
 
2238
  int sd = -1;
 
2239
  in_addr_t gwip = 0;
 
2240
  bool ret = false;
 
2241
 
 
2242
  if (!get_default_gateway (&gwip, NULL))
 
2243
    {
 
2244
      msg (M_WARN, "GDGMA: get_default_gateway failed");
 
2245
      goto err;
 
2246
    }
 
2247
 
 
2248
  if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
 
2249
    {
 
2250
      msg (M_WARN, "GDGMA: socket() failed");
 
2251
      goto err;
 
2252
    }
 
2253
 
 
2254
  ifc.ifc_len = sizeof (ifs);
 
2255
  ifc.ifc_req = ifs;
 
2256
  if (ioctl (sd, SIOCGIFCONF, &ifc) < 0)
 
2257
    {
 
2258
      msg (M_WARN, "GDGMA: ioctl(SIOCGIFCONF) failed");
 
2259
      goto err;
 
2260
    }
 
2261
 
 
2262
  /* scan through interface list */
 
2263
  ifend = ifs + (ifc.ifc_len / sizeof (struct ifreq));
 
2264
  for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
 
2265
    {
 
2266
      if (ifr->ifr_addr.sa_family == AF_INET)
 
2267
        {
 
2268
          ina = ntohl(((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
 
2269
          strncpynt (ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
 
2270
 
 
2271
          dmsg (D_AUTO_USERID, "GDGMA: %s", ifreq.ifr_name);
 
2272
 
 
2273
          /* check that the interface is up, and not point-to-point or loopback */
 
2274
          if (ioctl (sd, SIOCGIFFLAGS, &ifreq) < 0)
 
2275
            {
 
2276
              dmsg (D_AUTO_USERID, "GDGMA: SIOCGIFFLAGS(%s) failed", ifreq.ifr_name);
 
2277
              continue;
 
2278
            }
 
2279
 
 
2280
          if ((ifreq.ifr_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP)
 
2281
            {
 
2282
              dmsg (D_AUTO_USERID, "GDGMA: interface %s is down or loopback", ifreq.ifr_name);
 
2283
              continue;
 
2284
            }
 
2285
 
 
2286
          /* get interface netmask and check for correct subnet */
 
2287
          if (ioctl (sd, SIOCGIFNETMASK, &ifreq) < 0)
 
2288
            {
 
2289
              dmsg (D_AUTO_USERID, "GDGMA: SIOCGIFNETMASK(%s) failed", ifreq.ifr_name);
 
2290
              continue;
 
2291
            }
 
2292
 
 
2293
          mask = ntohl(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
 
2294
          if (((gwip ^ ina) & mask) != 0)
 
2295
            {
 
2296
              dmsg (D_AUTO_USERID, "GDGMA: gwip=0x%08x ina=0x%08x mask=0x%08x",
 
2297
                    (unsigned int)gwip,
 
2298
                    (unsigned int)ina,
 
2299
                    (unsigned int)mask);
 
2300
              continue;
 
2301
            }
 
2302
          break;
 
2303
        }
 
2304
    }
 
2305
  if (ifr >= ifend)
 
2306
    {
 
2307
      msg (M_WARN, "GDGMA: couldn't find gw interface");
 
2308
      goto err;
 
2309
    }
 
2310
 
 
2311
  /* now get the hardware address. */
 
2312
  memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
 
2313
  if (ioctl (sd, SIOCGIFHWADDR, &ifreq) < 0)
 
2314
    {
 
2315
      msg (M_WARN, "GDGMA: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
 
2316
      goto err;
 
2317
    }
 
2318
 
 
2319
  memcpy (macaddr, &ifreq.ifr_hwaddr.sa_data, 6);
 
2320
  ret = true;
 
2321
 
 
2322
 err:
 
2323
  if (sd >= 0)
 
2324
    close (sd);
 
2325
  return ret;
 
2326
}
 
2327
 
 
2328
#elif defined(WIN32)
 
2329
 
 
2330
bool
 
2331
get_default_gateway_mac_addr (unsigned char *macaddr)
 
2332
{
 
2333
  struct gc_arena gc = gc_new ();
 
2334
  const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
 
2335
  in_addr_t gwip = 0;
 
2336
  DWORD a_index;
 
2337
  const IP_ADAPTER_INFO *ai;
 
2338
 
 
2339
  if (!get_default_gateway (&gwip, NULL))
 
2340
    {
 
2341
      msg (M_WARN, "GDGMA: get_default_gateway failed");
 
2342
      goto err;
 
2343
    }
 
2344
 
 
2345
  a_index = adapter_index_of_ip (adapters, gwip, NULL, NULL);
 
2346
  ai = get_adapter (adapters, a_index);
 
2347
 
 
2348
  if (!ai)
 
2349
    {
 
2350
      msg (M_WARN, "GDGMA: couldn't find gw interface");
 
2351
      goto err;
 
2352
    }
 
2353
 
 
2354
  memcpy (macaddr, ai->Address, 6);
 
2355
 
 
2356
  gc_free (&gc);
 
2357
  return true;
 
2358
 
 
2359
 err:
 
2360
  gc_free (&gc);
 
2361
  return false;
 
2362
}
 
2363
 
 
2364
#else
 
2365
 
 
2366
bool
 
2367
get_default_gateway_mac_addr (unsigned char *macaddr) /* PLATFORM-SPECIFIC */
 
2368
{
 
2369
  return false;
 
2370
}
 
2371
 
 
2372
#endif
 
2373
#endif /* AUTO_USERID */
 
2374
 
 
2375
/*
 
2376
 * Test if addr is reachable via a local interface (return ILA_LOCAL),
 
2377
 * or if it needs to be routed via the default gateway (return
 
2378
 * ILA_NONLOCAL).  If the target platform doesn't implement this
 
2379
 * function, return ILA_NOT_IMPLEMENTED.
 
2380
 *
 
2381
 * Used by redirect-gateway autolocal feature
 
2382
 */
 
2383
 
 
2384
#if defined(WIN32)
 
2385
 
 
2386
int
 
2387
test_local_addr (const in_addr_t addr)
 
2388
{
 
2389
  struct gc_arena gc = gc_new ();
 
2390
  const in_addr_t nonlocal_netmask = 0x80000000L; /* routes with netmask <= to this are considered non-local */
 
2391
  bool ret = TLA_NONLOCAL;
 
2392
 
 
2393
  /* get full routing table */
 
2394
  const MIB_IPFORWARDTABLE *rt = get_windows_routing_table (&gc);
 
2395
  if (rt)
 
2396
    {
 
2397
      int i;
 
2398
      for (i = 0; i < rt->dwNumEntries; ++i)
 
2399
        {
 
2400
          const MIB_IPFORWARDROW *row = &rt->table[i];
 
2401
          const in_addr_t net = ntohl (row->dwForwardDest);
 
2402
          const in_addr_t mask = ntohl (row->dwForwardMask);
 
2403
          if (mask > nonlocal_netmask && (addr & mask) == net)
 
2404
            {
 
2405
              ret = TLA_LOCAL;
 
2406
              break;
 
2407
            }
 
2408
        }
 
2409
    }
 
2410
 
 
2411
  gc_free (&gc);
 
2412
  return ret;
 
2413
}
 
2414
 
 
2415
#else
 
2416
 
 
2417
 
 
2418
int
 
2419
test_local_addr (const in_addr_t addr) /* PLATFORM-SPECIFIC */
 
2420
{
 
2421
  return TLA_NOT_IMPLEMENTED;
 
2422
}
 
2423
 
 
2424
#endif