]> git.ipfire.org Git - thirdparty/openvpn.git/blame - src/openvpn/route.c
Set tls-version-max to 1.1 if cryptoapicert is used
[thirdparty/openvpn.git] / src / openvpn / route.c
CommitLineData
6fbf66fa
JY
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 *
564a2109 8 * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
6fbf66fa
JY
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
c110b289
ABL
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#elif defined(_MSC_VER)
32#include "config-msvc.h"
33#endif
34
6fbf66fa
JY
35#include "syshead.h"
36
37#include "common.h"
38#include "error.h"
39#include "route.h"
40#include "misc.h"
41#include "socket.h"
42#include "manage.h"
5a2e9a25 43#include "win32.h"
1840c852 44#include "options.h"
6fbf66fa
JY
45
46#include "memdbg.h"
47
12e46092
ABL
48#ifdef WIN32
49#define METRIC_NOT_USED ((DWORD)-1)
50#endif
51
b57e005b 52static void delete_route (struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es);
576dc96c 53
3c7f2f55
JY
54static void get_bypass_addresses (struct route_bypass *rb, const unsigned int flags);
55
56#ifdef ENABLE_DEBUG
57
58static void
59print_bypass_addresses (const struct route_bypass *rb)
60{
61 struct gc_arena gc = gc_new ();
62 int i;
63 for (i = 0; i < rb->n_bypass; ++i)
64 {
775a6ac2 65 msg (D_ROUTE, "ROUTE: bypass_host_route[%d]=%s",
3c7f2f55
JY
66 i,
67 print_in_addr_t (rb->bypass[i], 0, &gc));
68 }
69 gc_free (&gc);
70}
71
72#endif
73
d02a86d3
JY
74static bool
75add_bypass_address (struct route_bypass *rb, const in_addr_t a)
76{
77 int i;
78 for (i = 0; i < rb->n_bypass; ++i)
79 {
80 if (a == rb->bypass[i]) /* avoid duplicates */
81 return true;
82 }
83 if (rb->n_bypass < N_ROUTE_BYPASS)
84 {
85 rb->bypass[rb->n_bypass++] = a;
86 return true;
87 }
88 else
89 {
90 return false;
91 }
92}
93
6fbf66fa 94struct route_option_list *
d0085293 95new_route_option_list (struct gc_arena *a)
6fbf66fa
JY
96{
97 struct route_option_list *ret;
d0085293
HH
98 ALLOC_OBJ_CLEAR_GC (ret, struct route_option_list, a);
99 ret->gc = a;
6fbf66fa
JY
100 return ret;
101}
102
512cda46 103struct route_ipv6_option_list *
d0085293 104new_route_ipv6_option_list (struct gc_arena *a)
512cda46
GD
105{
106 struct route_ipv6_option_list *ret;
d0085293
HH
107 ALLOC_OBJ_CLEAR_GC (ret, struct route_ipv6_option_list, a);
108 ret->gc = a;
512cda46
GD
109 return ret;
110}
111
d0085293
HH
112/*
113 * NOTE: structs are cloned/copied shallow by design.
114 * The routes list from src will stay intact since it is allocated using
115 * the options->gc. The cloned/copied lists will share this common tail
116 * to avoid copying the data around between pulls. Pulled routes use
117 * the c2->gc so they get freed immediately after a reconnect.
118 */
673f583f
JY
119struct route_option_list *
120clone_route_option_list (const struct route_option_list *src, struct gc_arena *a)
121{
d0085293
HH
122 struct route_option_list *ret;
123 ALLOC_OBJ_GC (ret, struct route_option_list, a);
124 *ret = *src;
673f583f
JY
125 return ret;
126}
127
91402236
GD
128struct route_ipv6_option_list *
129clone_route_ipv6_option_list (const struct route_ipv6_option_list *src, struct gc_arena *a)
130{
d0085293
HH
131 struct route_ipv6_option_list *ret;
132 ALLOC_OBJ_GC (ret, struct route_ipv6_option_list, a);
133 *ret = *src;
91402236
GD
134 return ret;
135}
136
673f583f 137void
d0085293 138copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src, struct gc_arena *a)
673f583f 139{
d0085293
HH
140 *dest = *src;
141 dest->gc = a;
673f583f
JY
142}
143
91402236
GD
144void
145copy_route_ipv6_option_list (struct route_ipv6_option_list *dest,
d0085293
HH
146 const struct route_ipv6_option_list *src,
147 struct gc_arena *a)
512cda46 148{
d0085293
HH
149 *dest = *src;
150 dest->gc = a;
512cda46
GD
151}
152
6fbf66fa 153static const char *
b57e005b 154route_string (const struct route_ipv4 *r, struct gc_arena *gc)
6fbf66fa
JY
155{
156 struct buffer out = alloc_buf_gc (256, gc);
157 buf_printf (&out, "ROUTE network %s netmask %s gateway %s",
158 print_in_addr_t (r->network, 0, gc),
159 print_in_addr_t (r->netmask, 0, gc),
160 print_in_addr_t (r->gateway, 0, gc)
161 );
7fb0e07e 162 if (r->flags & RT_METRIC_DEFINED)
6fbf66fa
JY
163 buf_printf (&out, " metric %d", r->metric);
164 return BSTR (&out);
165}
166
167static bool
168is_route_parm_defined (const char *parm)
169{
170 if (!parm)
171 return false;
172 if (!strcmp (parm, "default"))
173 return false;
174 return true;
175}
176
177static void
178setenv_route_addr (struct env_set *es, const char *key, const in_addr_t addr, int i)
179{
180 struct gc_arena gc = gc_new ();
181 struct buffer name = alloc_buf_gc (256, &gc);
182 if (i >= 0)
183 buf_printf (&name, "route_%s_%d", key, i);
184 else
185 buf_printf (&name, "route_%s", key);
186 setenv_str (es, BSTR (&name), print_in_addr_t (addr, 0, &gc));
187 gc_free (&gc);
188}
189
190static bool
7fb0e07e 191get_special_addr (const struct route_list *rl,
6fbf66fa
JY
192 const char *string,
193 in_addr_t *out,
194 bool *status)
195{
b4073a76
JY
196 if (status)
197 *status = true;
6fbf66fa
JY
198 if (!strcmp (string, "vpn_gateway"))
199 {
7fb0e07e 200 if (rl)
6fbf66fa 201 {
7fb0e07e
JY
202 if (rl->spec.flags & RTSA_REMOTE_ENDPOINT)
203 *out = rl->spec.remote_endpoint;
b4073a76
JY
204 else
205 {
206 msg (M_INFO, PACKAGE_NAME " ROUTE: vpn_gateway undefined");
207 if (status)
208 *status = false;
209 }
6fbf66fa
JY
210 }
211 return true;
212 }
213 else if (!strcmp (string, "net_gateway"))
214 {
7fb0e07e 215 if (rl)
6fbf66fa 216 {
7fb0e07e
JY
217 if (rl->rgi.flags & RGI_ADDR_DEFINED)
218 *out = rl->rgi.gateway.addr;
b4073a76
JY
219 else
220 {
221 msg (M_INFO, PACKAGE_NAME " ROUTE: net_gateway undefined -- unable to get default gateway from system");
222 if (status)
223 *status = false;
224 }
6fbf66fa
JY
225 }
226 return true;
227 }
228 else if (!strcmp (string, "remote_host"))
229 {
7fb0e07e 230 if (rl)
6fbf66fa 231 {
7fb0e07e
JY
232 if (rl->spec.flags & RTSA_REMOTE_HOST)
233 *out = rl->spec.remote_host;
b4073a76
JY
234 else
235 {
236 msg (M_INFO, PACKAGE_NAME " ROUTE: remote_host undefined");
237 if (status)
238 *status = false;
239 }
6fbf66fa
JY
240 }
241 return true;
242 }
243 return false;
244}
245
b4073a76
JY
246bool
247is_special_addr (const char *addr_str)
248{
249 if (addr_str)
250 return get_special_addr (NULL, addr_str, NULL, NULL);
251 else
252 return false;
253}
254
6fbf66fa 255static bool
b57e005b 256init_route (struct route_ipv4 *r,
f2d6f3bc 257 struct addrinfo **network_list,
6fbf66fa 258 const struct route_option *ro,
7fb0e07e 259 const struct route_list *rl)
6fbf66fa 260{
32e576d2 261 const in_addr_t default_netmask = IPV4_NETMASK_HOST;
6fbf66fa 262 bool status;
f2d6f3bc
AS
263 int ret;
264 struct in_addr special;
6fbf66fa 265
7fb0e07e 266 CLEAR (*r);
6fbf66fa 267 r->option = ro;
6fbf66fa
JY
268
269 /* network */
270
271 if (!is_route_parm_defined (ro->network))
272 {
273 goto fail;
274 }
f2d6f3bc
AS
275
276
277 /* get_special_addr replaces specialaddr with a special ip addr
278 like gw. getaddrinfo is called to convert a a addrinfo struct */
279
a2466d9e 280 if(get_special_addr (rl, ro->network, (in_addr_t *) &special.s_addr, &status))
6fbf66fa 281 {
f2d6f3bc 282 special.s_addr = htonl(special.s_addr);
076fd3e4 283 ret = openvpn_getaddrinfo(0, inet_ntoa(special), NULL, 0, NULL,
f2d6f3bc 284 AF_INET, network_list);
6fbf66fa 285 }
f2d6f3bc
AS
286 else
287 ret = openvpn_getaddrinfo(GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL,
076fd3e4 288 ro->network, NULL, 0, NULL, AF_INET, network_list);
f2d6f3bc
AS
289
290 status = (ret == 0);
6fbf66fa
JY
291
292 if (!status)
293 goto fail;
294
295 /* netmask */
296
297 if (is_route_parm_defined (ro->netmask))
298 {
299 r->netmask = getaddr (
300 GETADDR_HOST_ORDER
301 | GETADDR_WARN_ON_SIGNAL,
302 ro->netmask,
303 0,
304 &status,
305 NULL);
306 if (!status)
307 goto fail;
308 }
309 else
310 r->netmask = default_netmask;
311
312 /* gateway */
313
314 if (is_route_parm_defined (ro->gateway))
315 {
7fb0e07e 316 if (!get_special_addr (rl, ro->gateway, &r->gateway, &status))
6fbf66fa
JY
317 {
318 r->gateway = getaddr (
319 GETADDR_RESOLVE
320 | GETADDR_HOST_ORDER
321 | GETADDR_WARN_ON_SIGNAL,
322 ro->gateway,
323 0,
324 &status,
325 NULL);
326 }
327 if (!status)
328 goto fail;
329 }
330 else
331 {
7fb0e07e
JY
332 if (rl->spec.flags & RTSA_REMOTE_ENDPOINT)
333 r->gateway = rl->spec.remote_endpoint;
6fbf66fa
JY
334 else
335 {
336 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");
337 goto fail;
338 }
339 }
340
341 /* metric */
342
6fbf66fa
JY
343 r->metric = 0;
344 if (is_route_parm_defined (ro->metric))
345 {
346 r->metric = atoi (ro->metric);
347 if (r->metric < 0)
348 {
349 msg (M_WARN, PACKAGE_NAME " ROUTE: route metric for network %s (%s) must be >= 0",
350 ro->network,
351 ro->metric);
352 goto fail;
353 }
7fb0e07e 354 r->flags |= RT_METRIC_DEFINED;
6fbf66fa 355 }
7fb0e07e 356 else if (rl->spec.flags & RTSA_DEFAULT_METRIC)
6fbf66fa 357 {
7fb0e07e
JY
358 r->metric = rl->spec.default_metric;
359 r->flags |= RT_METRIC_DEFINED;
6fbf66fa
JY
360 }
361
7fb0e07e 362 r->flags |= RT_DEFINED;
6fbf66fa
JY
363
364 return true;
365
366 fail:
367 msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve route for host/network: %s",
368 ro->network);
6fbf66fa
JY
369 return false;
370}
371
512cda46
GD
372static bool
373init_route_ipv6 (struct route_ipv6 *r6,
374 const struct route_ipv6_option *r6o,
375 const struct route_ipv6_list *rl6 )
376{
512cda46
GD
377 r6->defined = false;
378
1840c852 379 if ( !get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, NULL, M_WARN ))
512cda46
GD
380 goto fail;
381
382 /* gateway */
383 if (is_route_parm_defined (r6o->gateway))
384 {
385 if ( inet_pton( AF_INET6, r6o->gateway, &r6->gateway ) != 1 )
386 {
387 msg( M_WARN, PACKAGE_NAME "ROUTE6: cannot parse gateway spec '%s'", r6o->gateway );
388 }
389 }
390 else if (rl6->remote_endpoint_defined)
391 {
392 r6->gateway = rl6->remote_endpoint_ipv6;
393 }
394 else
395 {
396 msg (M_WARN, PACKAGE_NAME " ROUTE6: " PACKAGE_NAME " needs a gateway parameter for a --route-ipv6 option and no default was specified by either --route-ipv6-gateway or --ifconfig-ipv6 options");
397 goto fail;
398 }
399
400 /* metric */
401
402 r6->metric_defined = false;
c37d9135 403 r6->metric = -1;
512cda46
GD
404 if (is_route_parm_defined (r6o->metric))
405 {
406 r6->metric = atoi (r6o->metric);
407 if (r6->metric < 0)
408 {
409 msg (M_WARN, PACKAGE_NAME " ROUTE: route metric for network %s (%s) must be >= 0",
410 r6o->prefix,
411 r6o->metric);
412 goto fail;
413 }
414 r6->metric_defined = true;
415 }
416 else if (rl6->default_metric_defined)
417 {
418 r6->metric = rl6->default_metric;
419 r6->metric_defined = true;
420 }
421
422 r6->defined = true;
423
424 return true;
425
426 fail:
427 msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve route for host/network: %s",
428 r6o->prefix);
429 r6->defined = false;
430 return false;
431}
432
6fbf66fa
JY
433void
434add_route_to_option_list (struct route_option_list *l,
435 const char *network,
436 const char *netmask,
437 const char *gateway,
438 const char *metric)
439{
440 struct route_option *ro;
d0085293 441 ALLOC_OBJ_GC (ro, struct route_option, l->gc);
6fbf66fa
JY
442 ro->network = network;
443 ro->netmask = netmask;
444 ro->gateway = gateway;
445 ro->metric = metric;
d0085293
HH
446 ro->next = l->routes;
447 l->routes = ro;
448
6fbf66fa
JY
449}
450
512cda46
GD
451void
452add_route_ipv6_to_option_list (struct route_ipv6_option_list *l,
453 const char *prefix,
454 const char *gateway,
455 const char *metric)
456{
457 struct route_ipv6_option *ro;
d0085293 458 ALLOC_OBJ_GC (ro, struct route_ipv6_option, l->gc);
512cda46
GD
459 ro->prefix = prefix;
460 ro->gateway = gateway;
461 ro->metric = metric;
d0085293
HH
462 ro->next = l->routes_ipv6;
463 l->routes_ipv6 = ro;
512cda46
GD
464}
465
6fbf66fa
JY
466void
467clear_route_list (struct route_list *rl)
468{
d0085293
HH
469 gc_free (&rl->gc);
470 CLEAR (*rl);
6fbf66fa
JY
471}
472
512cda46
GD
473void
474clear_route_ipv6_list (struct route_ipv6_list *rl6)
475{
d0085293
HH
476 gc_free (&rl6->gc);
477 CLEAR (*rl6);
512cda46
GD
478}
479
03731db3 480void
7fb0e07e
JY
481route_list_add_vpn_gateway (struct route_list *rl,
482 struct env_set *es,
483 const in_addr_t addr)
03731db3 484{
eb95f367 485 ASSERT(rl);
03731db3 486 rl->spec.remote_endpoint = addr;
7fb0e07e 487 rl->spec.flags |= RTSA_REMOTE_ENDPOINT;
03731db3
JY
488 setenv_route_addr (es, "vpn_gateway", rl->spec.remote_endpoint, -1);
489}
490
7fb0e07e
JY
491static void
492add_block_local_item (struct route_list *rl,
493 const struct route_gateway_address *gateway,
494 in_addr_t target)
495{
496 const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
497 if ((rl->rgi.flags & rgi_needed) == rgi_needed
d0085293 498 && rl->rgi.gateway.netmask < 0xFFFFFFFF)
7fb0e07e 499 {
d0085293 500 struct route_ipv4 *r1, *r2;
7fb0e07e
JY
501 unsigned int l2;
502
d0085293
HH
503 ALLOC_OBJ_GC (r1, struct route_ipv4, &rl->gc);
504 ALLOC_OBJ_GC (r2, struct route_ipv4, &rl->gc);
505
7fb0e07e 506 /* split a route into two smaller blocking routes, and direct them to target */
7fb0e07e 507 l2 = ((~gateway->netmask)+1)>>1;
d0085293
HH
508 r1->flags = RT_DEFINED;
509 r1->gateway = target;
510 r1->network = gateway->addr & gateway->netmask;
511 r1->netmask = ~(l2-1);
512 r1->next = rl->routes;
513 rl->routes = r1;
514
515 *r2 = *r1;
516 r2->network += l2;
517 r2->next = rl->routes;
518 rl->routes = r2;
7fb0e07e
JY
519 }
520}
521
522static void
523add_block_local (struct route_list *rl)
524{
525 const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
526 if ((rl->flags & RG_BLOCK_LOCAL)
527 && (rl->rgi.flags & rgi_needed) == rgi_needed
528 && (rl->spec.flags & RTSA_REMOTE_ENDPOINT)
529 && rl->spec.remote_host_local != TLA_LOCAL)
530 {
531 size_t i;
532
533 /* add bypass for gateway addr */
534 add_bypass_address (&rl->spec.bypass, rl->rgi.gateway.addr);
535
536 /* block access to local subnet */
537 add_block_local_item (rl, &rl->rgi.gateway, rl->spec.remote_endpoint);
538
539 /* process additional subnets on gateway interface */
540 for (i = 0; i < rl->rgi.n_addrs; ++i)
541 {
542 const struct route_gateway_address *gwa = &rl->rgi.addrs[i];
543 /* omit the add/subnet in &rl->rgi which we processed above */
544 if (!((rl->rgi.gateway.addr & rl->rgi.gateway.netmask) == (gwa->addr & gwa->netmask)
545 && rl->rgi.gateway.netmask == gwa->netmask))
546 add_block_local_item (rl, gwa, rl->spec.remote_endpoint);
547 }
548 }
549}
550
6fbf66fa
JY
551bool
552init_route_list (struct route_list *rl,
553 const struct route_option_list *opt,
554 const char *remote_endpoint,
40ac3d7a 555 int default_metric,
6fbf66fa
JY
556 in_addr_t remote_host,
557 struct env_set *es)
558{
3c7f2f55 559 struct gc_arena gc = gc_new ();
6fbf66fa
JY
560 bool ret = true;
561
562 clear_route_list (rl);
563
3c7f2f55
JY
564 rl->flags = opt->flags;
565
6fbf66fa
JY
566 if (remote_host)
567 {
568 rl->spec.remote_host = remote_host;
7fb0e07e 569 rl->spec.flags |= RTSA_REMOTE_HOST;
6fbf66fa
JY
570 }
571
40ac3d7a
JY
572 if (default_metric)
573 {
574 rl->spec.default_metric = default_metric;
7fb0e07e 575 rl->spec.flags |= RTSA_DEFAULT_METRIC;
40ac3d7a
JY
576 }
577
7fb0e07e
JY
578 get_default_gateway (&rl->rgi);
579 if (rl->rgi.flags & RGI_ADDR_DEFINED)
6fbf66fa 580 {
7fb0e07e 581 setenv_route_addr (es, "net_gateway", rl->rgi.gateway.addr, -1);
c29e08a2 582#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
7fb0e07e
JY
583 print_default_gateway (D_ROUTE, &rl->rgi);
584#endif
3c7f2f55 585 }
03653f42
JY
586 else
587 {
775a6ac2 588 dmsg (D_ROUTE, "ROUTE: default_gateway=UNDEF");
03653f42 589 }
3c7f2f55 590
7fb0e07e
JY
591 if (rl->spec.flags & RTSA_REMOTE_HOST)
592 rl->spec.remote_host_local = test_local_addr (remote_host, &rl->rgi);
6fbf66fa
JY
593
594 if (is_route_parm_defined (remote_endpoint))
595 {
7fb0e07e 596 bool defined = false;
6fbf66fa
JY
597 rl->spec.remote_endpoint = getaddr (
598 GETADDR_RESOLVE
599 | GETADDR_HOST_ORDER
600 | GETADDR_WARN_ON_SIGNAL,
601 remote_endpoint,
602 0,
7fb0e07e 603 &defined,
6fbf66fa
JY
604 NULL);
605
7fb0e07e 606 if (defined)
6fbf66fa
JY
607 {
608 setenv_route_addr (es, "vpn_gateway", rl->spec.remote_endpoint, -1);
7fb0e07e 609 rl->spec.flags |= RTSA_REMOTE_ENDPOINT;
6fbf66fa
JY
610 }
611 else
612 {
613 msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve default gateway: %s",
614 remote_endpoint);
615 ret = false;
616 }
617 }
7fb0e07e
JY
618
619 if (rl->flags & RG_ENABLE)
620 {
621 add_block_local (rl);
622 get_bypass_addresses (&rl->spec.bypass, rl->flags);
623#ifdef ENABLE_DEBUG
624 print_bypass_addresses (&rl->spec.bypass);
625#endif
626 }
6fbf66fa 627
6fbf66fa
JY
628 /* parse the routes from opt to rl */
629 {
d0085293
HH
630 struct route_option *ro;
631 for (ro = opt->routes; ro; ro = ro->next)
6fbf66fa 632 {
f2d6f3bc 633 struct addrinfo* netlist;
b57e005b 634 struct route_ipv4 r;
59afc4a5 635
d0085293 636 if (!init_route (&r, &netlist, ro, rl))
6fbf66fa
JY
637 ret = false;
638 else
f9b2ada0 639 {
f2d6f3bc 640 struct addrinfo* curele;
e719a053 641 gc_addspecial(netlist, &gc_freeaddrinfo_callback, &gc);
f2d6f3bc 642 for (curele = netlist; curele; curele = curele->ai_next)
f9b2ada0 643 {
d0085293
HH
644 struct route_ipv4 *new;
645 ALLOC_OBJ_GC (new, struct route_ipv4, &rl->gc);
646 *new = r;
647 new->network = ntohl (((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr);
648 new->next = rl->routes;
649 rl->routes = new;
f9b2ada0
JY
650 }
651 }
6fbf66fa 652 }
6fbf66fa
JY
653 }
654
3c7f2f55 655 gc_free (&gc);
6fbf66fa
JY
656 return ret;
657}
658
512cda46
GD
659bool
660init_route_ipv6_list (struct route_ipv6_list *rl6,
661 const struct route_ipv6_option_list *opt6,
662 const char *remote_endpoint,
663 int default_metric,
664 struct env_set *es)
665{
666 struct gc_arena gc = gc_new ();
667 bool ret = true;
668
669 clear_route_ipv6_list (rl6);
670
671 rl6->flags = opt6->flags;
672
c37d9135 673 if (default_metric >= 0 )
512cda46
GD
674 {
675 rl6->default_metric = default_metric;
676 rl6->default_metric_defined = true;
677 }
678
679 /* "default_gateway" is stuff for "redirect-gateway", which we don't
680 * do for IPv6 yet -> TODO
681 */
682 {
683 dmsg (D_ROUTE, "ROUTE6: default_gateway=UNDEF");
684 }
685
686 if ( is_route_parm_defined( remote_endpoint ))
687 {
688 if ( inet_pton( AF_INET6, remote_endpoint,
689 &rl6->remote_endpoint_ipv6) == 1 )
690 {
691 rl6->remote_endpoint_defined = true;
692 }
693 else
694 {
695 msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve default gateway: %s", remote_endpoint);
696 ret = false;
697 }
698 }
699 else
700 rl6->remote_endpoint_defined = false;
701
702
d0085293 703 /* parse the routes from opt6 to rl6 */
512cda46 704 {
d0085293
HH
705 struct route_ipv6_option *ro6;
706 for (ro6 = opt6->routes_ipv6; ro6; ro6 = ro6->next)
512cda46 707 {
d0085293
HH
708 struct route_ipv6 *r6;
709 ALLOC_OBJ_GC (r6, struct route_ipv6, &rl6->gc);
710 if (!init_route_ipv6 (r6, ro6, rl6))
512cda46
GD
711 ret = false;
712 else
d0085293
HH
713 {
714 r6->next = rl6->routes_ipv6;
715 rl6->routes_ipv6 = r6;
716 }
512cda46 717 }
512cda46
GD
718 }
719
720 gc_free (&gc);
721 return ret;
722}
723
6fbf66fa
JY
724static void
725add_route3 (in_addr_t network,
726 in_addr_t netmask,
727 in_addr_t gateway,
728 const struct tuntap *tt,
729 unsigned int flags,
7fb0e07e 730 const struct route_gateway_info *rgi,
6fbf66fa
JY
731 const struct env_set *es)
732{
b57e005b 733 struct route_ipv4 r;
6fbf66fa 734 CLEAR (r);
7fb0e07e 735 r.flags = RT_DEFINED;
6fbf66fa
JY
736 r.network = network;
737 r.netmask = netmask;
738 r.gateway = gateway;
7fb0e07e 739 add_route (&r, tt, flags, rgi, es);
6fbf66fa
JY
740}
741
742static void
743del_route3 (in_addr_t network,
744 in_addr_t netmask,
745 in_addr_t gateway,
746 const struct tuntap *tt,
747 unsigned int flags,
7fb0e07e 748 const struct route_gateway_info *rgi,
6fbf66fa
JY
749 const struct env_set *es)
750{
b57e005b 751 struct route_ipv4 r;
6fbf66fa 752 CLEAR (r);
7fb0e07e 753 r.flags = RT_DEFINED|RT_ADDED;
6fbf66fa
JY
754 r.network = network;
755 r.netmask = netmask;
756 r.gateway = gateway;
7fb0e07e 757 delete_route (&r, tt, flags, rgi, es);
6fbf66fa
JY
758}
759
3c7f2f55
JY
760static void
761add_bypass_routes (struct route_bypass *rb,
762 in_addr_t gateway,
763 const struct tuntap *tt,
764 unsigned int flags,
7fb0e07e 765 const struct route_gateway_info *rgi,
3c7f2f55
JY
766 const struct env_set *es)
767{
768 int i;
769 for (i = 0; i < rb->n_bypass; ++i)
770 {
7fb0e07e 771 if (rb->bypass[i])
3c7f2f55 772 add_route3 (rb->bypass[i],
32e576d2 773 IPV4_NETMASK_HOST,
3c7f2f55
JY
774 gateway,
775 tt,
8fc83a2d 776 flags | ROUTE_REF_GW,
7fb0e07e 777 rgi,
3c7f2f55
JY
778 es);
779 }
780}
781
782static void
783del_bypass_routes (struct route_bypass *rb,
784 in_addr_t gateway,
785 const struct tuntap *tt,
786 unsigned int flags,
7fb0e07e 787 const struct route_gateway_info *rgi,
3c7f2f55
JY
788 const struct env_set *es)
789{
790 int i;
791 for (i = 0; i < rb->n_bypass; ++i)
792 {
7fb0e07e 793 if (rb->bypass[i])
3c7f2f55 794 del_route3 (rb->bypass[i],
32e576d2 795 IPV4_NETMASK_HOST,
3c7f2f55
JY
796 gateway,
797 tt,
8fc83a2d 798 flags | ROUTE_REF_GW,
7fb0e07e 799 rgi,
3c7f2f55
JY
800 es);
801 }
802}
803
6fbf66fa
JY
804static void
805redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
806{
807 const char err[] = "NOTE: unable to redirect default gateway --";
808
f0257abb 809 if ( rl && rl->flags & RG_ENABLE )
6fbf66fa 810 {
7fb0e07e 811 if (!(rl->spec.flags & RTSA_REMOTE_ENDPOINT))
6fbf66fa
JY
812 {
813 msg (M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
814 }
7fb0e07e 815 else if (!(rl->rgi.flags & RGI_ADDR_DEFINED))
6fbf66fa
JY
816 {
817 msg (M_WARN, "%s Cannot read current default gateway from system", err);
818 }
7fb0e07e 819 else if (!(rl->spec.flags & RTSA_REMOTE_HOST))
6fbf66fa
JY
820 {
821 msg (M_WARN, "%s Cannot obtain current remote host address", err);
822 }
823 else
824 {
775a6ac2
JY
825 bool local = BOOL_CAST(rl->flags & RG_LOCAL);
826 if (rl->flags & RG_AUTO_LOCAL) {
7fb0e07e 827 const int tla = rl->spec.remote_host_local;
775a6ac2
JY
828 if (tla == TLA_NONLOCAL)
829 {
830 dmsg (D_ROUTE, "ROUTE remote_host is NOT LOCAL");
831 local = false;
832 }
833 else if (tla == TLA_LOCAL)
834 {
835 dmsg (D_ROUTE, "ROUTE remote_host is LOCAL");
836 local = true;
837 }
838 }
839 if (!local)
840 {
841 /* route remote host to original default gateway */
6caf7f3d
JC
842 /* if remote_host is not ipv4 (ie: ipv6), just skip
843 * adding this special /32 route */
9d4c64b5 844 if (rl->spec.remote_host != IPV4_INVALID_ADDR) {
efa85c8b 845 add_route3 (rl->spec.remote_host,
32e576d2 846 IPV4_NETMASK_HOST,
576dc96c 847 rl->rgi.gateway.addr,
efa85c8b 848 tt,
8fc83a2d 849 flags | ROUTE_REF_GW,
576dc96c 850 &rl->rgi,
efa85c8b 851 es);
576dc96c 852 rl->iflags |= RL_DID_LOCAL;
efa85c8b
JC
853 } else {
854 dmsg (D_ROUTE, "ROUTE remote_host protocol differs from tunneled");
855 }
775a6ac2 856 }
6fbf66fa 857
3c7f2f55 858 /* route DHCP/DNS server traffic through original default gateway */
7fb0e07e 859 add_bypass_routes (&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags, &rl->rgi, es);
3c7f2f55 860
b723833b
JY
861 if (rl->flags & RG_REROUTE_GW)
862 {
863 if (rl->flags & RG_DEF1)
864 {
865 /* add new default route (1st component) */
866 add_route3 (0x00000000,
867 0x80000000,
868 rl->spec.remote_endpoint,
869 tt,
870 flags,
7fb0e07e 871 &rl->rgi,
b723833b
JY
872 es);
873
874 /* add new default route (2nd component) */
875 add_route3 (0x80000000,
876 0x80000000,
877 rl->spec.remote_endpoint,
878 tt,
879 flags,
7fb0e07e 880 &rl->rgi,
b723833b
JY
881 es);
882 }
883 else
884 {
885 /* delete default route */
886 del_route3 (0,
887 0,
7fb0e07e 888 rl->rgi.gateway.addr,
b723833b 889 tt,
8fc83a2d 890 flags | ROUTE_REF_GW,
7fb0e07e 891 &rl->rgi,
b723833b
JY
892 es);
893
894 /* add new default route */
895 add_route3 (0,
896 0,
897 rl->spec.remote_endpoint,
898 tt,
899 flags,
7fb0e07e 900 &rl->rgi,
b723833b
JY
901 es);
902 }
903 }
904
905 /* set a flag so we can undo later */
7fb0e07e 906 rl->iflags |= RL_DID_REDIRECT_DEFAULT_GATEWAY;
b723833b
JY
907 }
908 }
909}
910
911static void
912undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
913{
f0257abb 914 if ( rl && rl->iflags & RL_DID_REDIRECT_DEFAULT_GATEWAY )
b723833b
JY
915 {
916 /* delete remote host route */
7fb0e07e 917 if (rl->iflags & RL_DID_LOCAL)
775a6ac2
JY
918 {
919 del_route3 (rl->spec.remote_host,
32e576d2 920 IPV4_NETMASK_HOST,
7fb0e07e 921 rl->rgi.gateway.addr,
775a6ac2 922 tt,
8fc83a2d 923 flags | ROUTE_REF_GW,
7fb0e07e 924 &rl->rgi,
775a6ac2 925 es);
7fb0e07e 926 rl->iflags &= ~RL_DID_LOCAL;
775a6ac2 927 }
b723833b
JY
928
929 /* delete special DHCP/DNS bypass route */
7fb0e07e 930 del_bypass_routes (&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags, &rl->rgi, es);
b723833b
JY
931
932 if (rl->flags & RG_REROUTE_GW)
933 {
3c7f2f55 934 if (rl->flags & RG_DEF1)
6fbf66fa 935 {
b723833b
JY
936 /* delete default route (1st component) */
937 del_route3 (0x00000000,
6fbf66fa
JY
938 0x80000000,
939 rl->spec.remote_endpoint,
940 tt,
941 flags,
7fb0e07e 942 &rl->rgi,
6fbf66fa
JY
943 es);
944
b723833b
JY
945 /* delete default route (2nd component) */
946 del_route3 (0x80000000,
6fbf66fa
JY
947 0x80000000,
948 rl->spec.remote_endpoint,
949 tt,
950 flags,
7fb0e07e 951 &rl->rgi,
6fbf66fa
JY
952 es);
953 }
954 else
955 {
956 /* delete default route */
957 del_route3 (0,
958 0,
b723833b 959 rl->spec.remote_endpoint,
6fbf66fa
JY
960 tt,
961 flags,
7fb0e07e 962 &rl->rgi,
6fbf66fa
JY
963 es);
964
b723833b 965 /* restore original default route */
6fbf66fa
JY
966 add_route3 (0,
967 0,
7fb0e07e 968 rl->rgi.gateway.addr,
6fbf66fa 969 tt,
8fc83a2d 970 flags | ROUTE_REF_GW,
7fb0e07e 971 &rl->rgi,
6fbf66fa
JY
972 es);
973 }
6fbf66fa
JY
974 }
975
7fb0e07e 976 rl->iflags &= ~RL_DID_REDIRECT_DEFAULT_GATEWAY;
6fbf66fa
JY
977 }
978}
979
980void
576dc96c 981add_routes (struct route_list *rl, struct route_ipv6_list *rl6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
6fbf66fa 982{
d02a86d3 983 redirect_default_route_to_vpn (rl, tt, flags, es);
f0257abb 984 if ( rl && !(rl->iflags & RL_ROUTES_ADDED) )
6fbf66fa 985 {
d0085293 986 struct route_ipv4 *r;
6fbf66fa
JY
987
988#ifdef ENABLE_MANAGEMENT
d0085293 989 if (management && rl->routes)
6fbf66fa
JY
990 {
991 management_set_state (management,
992 OPENVPN_STATE_ADD_ROUTES,
993 NULL,
5ad84585 994 0,
6fbf66fa
JY
995 0);
996 }
997#endif
d0085293
HH
998
999 for (r = rl->routes; r; r = r->next)
6fbf66fa 1000 {
f77c60d3 1001 check_subnet_conflict (r->network, r->netmask, "route");
6fbf66fa 1002 if (flags & ROUTE_DELETE_FIRST)
7fb0e07e
JY
1003 delete_route (r, tt, flags, &rl->rgi, es);
1004 add_route (r, tt, flags, &rl->rgi, es);
6fbf66fa 1005 }
7fb0e07e 1006 rl->iflags |= RL_ROUTES_ADDED;
6fbf66fa 1007 }
512cda46
GD
1008 if (rl6 && !rl6->routes_added)
1009 {
d0085293
HH
1010 struct route_ipv6 *r;
1011 for (r = rl6->routes_ipv6; r; r = r->next)
512cda46 1012 {
512cda46
GD
1013 if (flags & ROUTE_DELETE_FIRST)
1014 delete_route_ipv6 (r, tt, flags, es);
1015 add_route_ipv6 (r, tt, flags, es);
1016 }
1017 rl6->routes_added = true;
1018 }
6fbf66fa
JY
1019}
1020
1021void
512cda46
GD
1022delete_routes (struct route_list *rl, struct route_ipv6_list *rl6,
1023 const struct tuntap *tt, unsigned int flags, const struct env_set *es)
6fbf66fa 1024{
f0257abb 1025 if ( rl && rl->iflags & RL_ROUTES_ADDED )
6fbf66fa 1026 {
d0085293
HH
1027 struct route_ipv4 *r;
1028 for (r = rl->routes; r; r = r->next)
6fbf66fa 1029 {
7fb0e07e 1030 delete_route (r, tt, flags, &rl->rgi, es);
6fbf66fa 1031 }
7fb0e07e 1032 rl->iflags &= ~RL_ROUTES_ADDED;
6fbf66fa 1033 }
6fbf66fa 1034
576dc96c 1035 undo_redirect_default_route_to_vpn (rl, tt, flags, es);
f0257abb
GD
1036
1037 if ( rl )
1038 {
1039 clear_route_list (rl);
1040 }
512cda46
GD
1041
1042 if ( rl6 && rl6->routes_added )
1043 {
d0085293
HH
1044 struct route_ipv6 *r6;
1045 for (r6 = rl6->routes_ipv6; r6; r6 = r6->next)
512cda46 1046 {
512cda46
GD
1047 delete_route_ipv6 (r6, tt, flags, es);
1048 }
1049 rl6->routes_added = false;
1050 }
1051
1052 if ( rl6 )
1053 {
1054 clear_route_ipv6_list (rl6);
1055 }
6fbf66fa
JY
1056}
1057
6c61d0dd 1058#ifndef ENABLE_SMALL
6fbf66fa
JY
1059
1060static const char *
1061show_opt (const char *option)
1062{
1063 if (!option)
1064 return "nil";
1065 else
1066 return option;
1067}
1068
1069static void
1070print_route_option (const struct route_option *ro, int level)
1071{
1072 msg (level, " route %s/%s/%s/%s",
1073 show_opt (ro->network),
1074 show_opt (ro->netmask),
1075 show_opt (ro->gateway),
1076 show_opt (ro->metric));
1077}
1078
1079void
1080print_route_options (const struct route_option_list *rol,
1081 int level)
1082{
d0085293 1083 struct route_option *ro;
3c7f2f55 1084 if (rol->flags & RG_ENABLE)
6fbf66fa 1085 msg (level, " [redirect_default_gateway local=%d]",
3c7f2f55 1086 (rol->flags & RG_LOCAL) != 0);
d0085293
HH
1087 for (ro = rol->routes; ro; ro = ro->next)
1088 print_route_option (ro, level);
6fbf66fa
JY
1089}
1090
7fb0e07e
JY
1091void
1092print_default_gateway(const int msglevel, const struct route_gateway_info *rgi)
1093{
1094 struct gc_arena gc = gc_new ();
1095 if (rgi->flags & RGI_ADDR_DEFINED)
1096 {
1097 struct buffer out = alloc_buf_gc (256, &gc);
1098 buf_printf (&out, "ROUTE_GATEWAY");
8fc83a2d
JY
1099 if (rgi->flags & RGI_ON_LINK)
1100 buf_printf (&out, " ON_LINK");
1101 else
1102 buf_printf (&out, " %s", print_in_addr_t (rgi->gateway.addr, 0, &gc));
7fb0e07e
JY
1103 if (rgi->flags & RGI_NETMASK_DEFINED)
1104 buf_printf (&out, "/%s", print_in_addr_t (rgi->gateway.netmask, 0, &gc));
1105#ifdef WIN32
1106 if (rgi->flags & RGI_IFACE_DEFINED)
1107 buf_printf (&out, " I=%u", (unsigned int)rgi->adapter_index);
1108#else
1109 if (rgi->flags & RGI_IFACE_DEFINED)
1110 buf_printf (&out, " IFACE=%s", rgi->iface);
1111#endif
1112 if (rgi->flags & RGI_HWADDR_DEFINED)
1113 buf_printf (&out, " HWADDR=%s", format_hex_ex (rgi->hwaddr, 6, 0, 1, ":", &gc));
1114 msg (msglevel, "%s", BSTR (&out));
1115 }
1116 gc_free (&gc);
1117}
1118
6fbf66fa
JY
1119#endif
1120
1121static void
b57e005b 1122print_route (const struct route_ipv4 *r, int level)
6fbf66fa
JY
1123{
1124 struct gc_arena gc = gc_new ();
7fb0e07e 1125 if (r->flags & RT_DEFINED)
6fbf66fa
JY
1126 msg (level, "%s", route_string (r, &gc));
1127 gc_free (&gc);
1128}
1129
1130void
1131print_routes (const struct route_list *rl, int level)
1132{
d0085293
HH
1133 struct route_ipv4 *r;
1134 for (r = rl->routes; r; r = r->next)
1135 print_route (r, level);
6fbf66fa
JY
1136}
1137
1138static void
b57e005b 1139setenv_route (struct env_set *es, const struct route_ipv4 *r, int i)
6fbf66fa
JY
1140{
1141 struct gc_arena gc = gc_new ();
7fb0e07e 1142 if (r->flags & RT_DEFINED)
6fbf66fa
JY
1143 {
1144 setenv_route_addr (es, "network", r->network, i);
1145 setenv_route_addr (es, "netmask", r->netmask, i);
1146 setenv_route_addr (es, "gateway", r->gateway, i);
1147
7fb0e07e 1148 if (r->flags & RT_METRIC_DEFINED)
6fbf66fa
JY
1149 {
1150 struct buffer name = alloc_buf_gc (256, &gc);
1151 buf_printf (&name, "route_metric_%d", i);
1152 setenv_int (es, BSTR (&name), r->metric);
1153 }
1154 }
1155 gc_free (&gc);
1156}
1157
1158void
1159setenv_routes (struct env_set *es, const struct route_list *rl)
1160{
d0085293
HH
1161 int i = 1;
1162 struct route_ipv4 *r;
1163 for (r = rl->routes; r; r = r->next)
1164 setenv_route (es, r, i++);
6fbf66fa
JY
1165}
1166
512cda46
GD
1167static void
1168setenv_route_ipv6 (struct env_set *es, const struct route_ipv6 *r6, int i)
1169{
1170 struct gc_arena gc = gc_new ();
1171 if (r6->defined)
1172 {
1173 struct buffer name1 = alloc_buf_gc( 256, &gc );
1174 struct buffer val = alloc_buf_gc( 256, &gc );
1175 struct buffer name2 = alloc_buf_gc( 256, &gc );
1176
1177 buf_printf( &name1, "route_ipv6_network_%d", i );
1178 buf_printf( &val, "%s/%d", print_in6_addr( r6->network, 0, &gc ),
1179 r6->netbits );
1180 setenv_str( es, BSTR(&name1), BSTR(&val) );
1181
1182 buf_printf( &name2, "route_ipv6_gateway_%d", i );
1183 setenv_str( es, BSTR(&name2), print_in6_addr( r6->gateway, 0, &gc ));
1184 }
1185 gc_free (&gc);
1186}
1187void
1188setenv_routes_ipv6 (struct env_set *es, const struct route_ipv6_list *rl6)
1189{
d0085293
HH
1190 int i = 1;
1191 struct route_ipv6 *r6;
1192 for (r6 = rl6->routes_ipv6; r6; r6 = r6->next)
1193 setenv_route_ipv6 (es, r6, i++);
512cda46
GD
1194}
1195
7fb0e07e
JY
1196/*
1197 * local_route() determines whether the gateway of a provided host
1198 * route is on the same interface that owns the default gateway.
1199 * It uses the data structure
1200 * returned by get_default_gateway() (struct route_gateway_info)
1201 * to determine this. If the route is local, LR_MATCH is returned.
1202 * When adding routes into the kernel, if LR_MATCH is defined for
1203 * a given route, the route should explicitly reference the default
1204 * gateway interface as the route destination. For example, here
1205 * is an example on Linux that uses LR_MATCH:
1206 *
576dc96c 1207 * route add -net 10.10.0.1 netmask 255.255.255.255 dev eth0
7fb0e07e
JY
1208 *
1209 * This capability is needed by the "default-gateway block-local"
1210 * directive, to allow client access to the local subnet to be
1211 * blocked but still allow access to the local default gateway.
1212 */
1213
1214/* local_route() return values */
1215#define LR_NOMATCH 0 /* route is not local */
1216#define LR_MATCH 1 /* route is local */
1217#define LR_ERROR 2 /* caller should abort adding route */
1218
1219static int
1220local_route (in_addr_t network,
1221 in_addr_t netmask,
1222 in_addr_t gateway,
1223 const struct route_gateway_info *rgi)
1224{
1225 /* set LR_MATCH on local host routes */
1226 const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED|RGI_IFACE_DEFINED);
1227 if (rgi
1228 && (rgi->flags & rgi_needed) == rgi_needed
1229 && gateway == rgi->gateway.addr
1230 && netmask == 0xFFFFFFFF)
1231 {
1232 if (((network ^ rgi->gateway.addr) & rgi->gateway.netmask) == 0)
1233 return LR_MATCH;
1234 else
1235 {
1236 /* examine additional subnets on gateway interface */
1237 size_t i;
1238 for (i = 0; i < rgi->n_addrs; ++i)
1239 {
1240 const struct route_gateway_address *gwa = &rgi->addrs[i];
1241 if (((network ^ gwa->addr) & gwa->netmask) == 0)
1242 return LR_MATCH;
1243 }
1244 }
1245 }
1246 return LR_NOMATCH;
1247}
1248
8fc83a2d
JY
1249/* Return true if the "on-link" form of the route should be used. This is when the gateway for a
1250 a route is specified as an interface rather than an address. */
1251static inline bool
1252is_on_link (const int is_local_route, const unsigned int flags, const struct route_gateway_info *rgi)
1253{
1254 return rgi && (is_local_route == LR_MATCH || ((flags & ROUTE_REF_GW) && (rgi->flags & RGI_ON_LINK)));
1255}
1256
6d5d1010 1257void
b57e005b 1258add_route (struct route_ipv4 *r,
7fb0e07e
JY
1259 const struct tuntap *tt,
1260 unsigned int flags,
1261 const struct route_gateway_info *rgi, /* may be NULL */
1262 const struct env_set *es)
6fbf66fa
JY
1263{
1264 struct gc_arena gc;
5a2e9a25 1265 struct argv argv;
6fbf66fa
JY
1266 const char *network;
1267 const char *netmask;
1268 const char *gateway;
1269 bool status = false;
7fb0e07e 1270 int is_local_route;
6fbf66fa 1271
7fb0e07e 1272 if (!(r->flags & RT_DEFINED))
6fbf66fa
JY
1273 return;
1274
1275 gc_init (&gc);
5a2e9a25 1276 argv_init (&argv);
6fbf66fa
JY
1277
1278 network = print_in_addr_t (r->network, 0, &gc);
1279 netmask = print_in_addr_t (r->netmask, 0, &gc);
1280 gateway = print_in_addr_t (r->gateway, 0, &gc);
1281
7fb0e07e
JY
1282 is_local_route = local_route(r->network, r->netmask, r->gateway, rgi);
1283 if (is_local_route == LR_ERROR)
1284 goto done;
6fbf66fa
JY
1285
1286#if defined(TARGET_LINUX)
51bd56f4 1287#ifdef ENABLE_IPROUTE
baa195b9 1288 argv_printf (&argv, "%s route add %s/%d",
0aee9ca7 1289 iproute_path,
6fbf66fa 1290 network,
baa195b9
PH
1291 count_netmask_bits(netmask));
1292
7fb0e07e 1293 if (r->flags & RT_METRIC_DEFINED)
5a2e9a25 1294 argv_printf_cat (&argv, "metric %d", r->metric);
6fbf66fa 1295
baa195b9
PH
1296 if (is_on_link (is_local_route, flags, rgi))
1297 argv_printf_cat (&argv, "dev %s", rgi->iface);
1298 else
1299 argv_printf_cat (&argv, "via %s", gateway);
6fbf66fa 1300#else
7fb0e07e
JY
1301 argv_printf (&argv, "%s add -net %s netmask %s",
1302 ROUTE_PATH,
1303 network,
1304 netmask);
1305 if (r->flags & RT_METRIC_DEFINED)
5a2e9a25 1306 argv_printf_cat (&argv, "metric %d", r->metric);
8fc83a2d 1307 if (is_on_link (is_local_route, flags, rgi))
7fb0e07e
JY
1308 argv_printf_cat (&argv, "dev %s", rgi->iface);
1309 else
1310 argv_printf_cat (&argv, "gw %s", gateway);
1311
51bd56f4 1312#endif /*ENABLE_IPROUTE*/
5a2e9a25
JY
1313 argv_msg (D_ROUTE, &argv);
1314 status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route add command failed");
6fbf66fa 1315
a55b3cdb 1316#elif defined (TARGET_ANDROID)
05660e78 1317 struct buffer out = alloc_buf_gc (128, &gc);
a55b3cdb 1318
05660e78
AS
1319 if (rgi)
1320 buf_printf (&out, "%s %s %s dev %s", network, netmask, gateway, rgi->iface);
1321 else
1322 buf_printf (&out, "%s %s %s", network, netmask, gateway);
a55b3cdb
AS
1323 management_android_control (management, "ROUTE", buf_bptr(&out));
1324
6fbf66fa 1325#elif defined (WIN32)
7fb0e07e 1326 {
12e46092 1327 DWORD ai = TUN_ADAPTER_INDEX_INVALID;
7fb0e07e
JY
1328 argv_printf (&argv, "%s%sc ADD %s MASK %s %s",
1329 get_win_sys_path(),
1330 WIN_ROUTE_PATH_SUFFIX,
1331 network,
1332 netmask,
1333 gateway);
1334 if (r->flags & RT_METRIC_DEFINED)
1335 argv_printf_cat (&argv, "METRIC %d", r->metric);
8fc83a2d 1336 if (is_on_link (is_local_route, flags, rgi))
7fb0e07e
JY
1337 {
1338 ai = rgi->adapter_index;
1339 argv_printf_cat (&argv, "IF %u", (unsigned int)ai);
1340 }
6fbf66fa 1341
7fb0e07e 1342 argv_msg (D_ROUTE, &argv);
6fbf66fa 1343
7fb0e07e
JY
1344 if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_IPAPI)
1345 {
1346 status = add_route_ipapi (r, tt, ai);
1347 msg (D_ROUTE, "Route addition via IPAPI %s", status ? "succeeded" : "failed");
1348 }
1349 else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_EXE)
1350 {
1351 netcmd_semaphore_lock ();
1352 status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add command failed");
1353 netcmd_semaphore_release ();
1354 }
1355 else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_ADAPTIVE)
1356 {
1357 status = add_route_ipapi (r, tt, ai);
1358 msg (D_ROUTE, "Route addition via IPAPI %s [adaptive]", status ? "succeeded" : "failed");
1359 if (!status)
1360 {
1361 msg (D_ROUTE, "Route addition fallback to route.exe");
1362 netcmd_semaphore_lock ();
1363 status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add command failed [adaptive]");
1364 netcmd_semaphore_release ();
1365 }
1366 }
1367 else
1368 {
1369 ASSERT (0);
1370 }
1371 }
6fbf66fa
JY
1372
1373#elif defined (TARGET_SOLARIS)
1374
1375 /* example: route add 192.0.2.32 -netmask 255.255.255.224 somegateway */
1376
5a2e9a25
JY
1377 argv_printf (&argv, "%s add",
1378 ROUTE_PATH);
6fbf66fa 1379
5a2e9a25 1380 argv_printf_cat (&argv, "%s -netmask %s %s",
6fbf66fa
JY
1381 network,
1382 netmask,
1383 gateway);
1384
792e8956
GD
1385 /* Solaris can only distinguish between "metric 0" == "on-link on the
1386 * interface where the IP address given is configured" and "metric > 0"
1387 * == "use gateway specified" (no finer-grained route metrics available)
1388 *
1389 * More recent versions of Solaris can also do "-interface", but that
1390 * would break backwards compatibility with older versions for no gain.
1391 */
1392 if (r->flags & RT_METRIC_DEFINED )
1393 argv_printf_cat (&argv, "%d", r->metric);
f0eac1a5 1394
5a2e9a25
JY
1395 argv_msg (D_ROUTE, &argv);
1396 status = openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route add command failed");
6fbf66fa
JY
1397
1398#elif defined(TARGET_FREEBSD)
1399
5a2e9a25
JY
1400 argv_printf (&argv, "%s add",
1401 ROUTE_PATH);
6fbf66fa
JY
1402
1403#if 0
7fb0e07e 1404 if (r->flags & RT_METRIC_DEFINED)
5a2e9a25 1405 argv_printf_cat (&argv, "-rtt %d", r->metric);
6fbf66fa
JY
1406#endif
1407
5a2e9a25 1408 argv_printf_cat (&argv, "-net %s %s %s",
6fbf66fa
JY
1409 network,
1410 gateway,
1411 netmask);
1412
8fc83a2d 1413 /* FIXME -- add on-link support for FreeBSD */
7fb0e07e 1414
5a2e9a25
JY
1415 argv_msg (D_ROUTE, &argv);
1416 status = openvpn_execve_check (&argv, es, 0, "ERROR: FreeBSD route add command failed");
6fbf66fa 1417
1bda73a7
JY
1418#elif defined(TARGET_DRAGONFLY)
1419
5a2e9a25
JY
1420 argv_printf (&argv, "%s add",
1421 ROUTE_PATH);
1bda73a7
JY
1422
1423#if 0
7fb0e07e 1424 if (r->flags & RT_METRIC_DEFINED)
5a2e9a25 1425 argv_printf_cat (&argv, "-rtt %d", r->metric);
1bda73a7
JY
1426#endif
1427
5a2e9a25 1428 argv_printf_cat (&argv, "-net %s %s %s",
1bda73a7
JY
1429 network,
1430 gateway,
1431 netmask);
1432
8fc83a2d 1433 /* FIXME -- add on-link support for Dragonfly */
7fb0e07e 1434
5a2e9a25
JY
1435 argv_msg (D_ROUTE, &argv);
1436 status = openvpn_execve_check (&argv, es, 0, "ERROR: DragonFly route add command failed");
1bda73a7 1437
6fbf66fa
JY
1438#elif defined(TARGET_DARWIN)
1439
5a2e9a25
JY
1440 argv_printf (&argv, "%s add",
1441 ROUTE_PATH);
6fbf66fa
JY
1442
1443#if 0
7fb0e07e 1444 if (r->flags & RT_METRIC_DEFINED)
5a2e9a25 1445 argv_printf_cat (&argv, "-rtt %d", r->metric);
6fbf66fa
JY
1446#endif
1447
8fc83a2d 1448 if (is_on_link (is_local_route, flags, rgi))
7fb0e07e 1449 {
8fc83a2d 1450 /* Mac OS X route syntax for ON_LINK:
7fb0e07e
JY
1451 route add -cloning -net 10.10.0.1 -netmask 255.255.255.255 -interface en0 */
1452 argv_printf_cat (&argv, "-cloning -net %s -netmask %s -interface %s",
1453 network,
1454 netmask,
1455 rgi->iface);
1456 }
1457 else
1458 {
1459 argv_printf_cat (&argv, "-net %s %s %s",
1460 network,
1461 gateway,
1462 netmask);
1463 }
6fbf66fa 1464
5a2e9a25
JY
1465 argv_msg (D_ROUTE, &argv);
1466 status = openvpn_execve_check (&argv, es, 0, "ERROR: OS X route add command failed");
6fbf66fa
JY
1467
1468#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1469
5a2e9a25
JY
1470 argv_printf (&argv, "%s add",
1471 ROUTE_PATH);
6fbf66fa
JY
1472
1473#if 0
7fb0e07e 1474 if (r->flags & RT_METRIC_DEFINED)
5a2e9a25 1475 argv_printf_cat (&argv, "-rtt %d", r->metric);
6fbf66fa
JY
1476#endif
1477
5a2e9a25 1478 argv_printf_cat (&argv, "-net %s %s -netmask %s",
6fbf66fa
JY
1479 network,
1480 gateway,
1481 netmask);
1482
8fc83a2d 1483 /* FIXME -- add on-link support for OpenBSD/NetBSD */
7fb0e07e 1484
5a2e9a25
JY
1485 argv_msg (D_ROUTE, &argv);
1486 status = openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route add command failed");
6fbf66fa 1487
b4b92ae5
GD
1488#elif defined(TARGET_AIX)
1489
1490 {
1491 int netbits = netmask_to_netbits2(r->netmask);
1492 argv_printf (&argv, "%s add -net %s/%d %s",
1493 ROUTE_PATH,
1494 network, netbits, gateway);
1495 argv_msg (D_ROUTE, &argv);
1496 status = openvpn_execve_check (&argv, es, 0, "ERROR: AIX route add command failed");
1497 }
1498
6fbf66fa
JY
1499#else
1500 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");
1501#endif
1502
1503 done:
7fb0e07e
JY
1504 if (status)
1505 r->flags |= RT_ADDED;
1506 else
1507 r->flags &= ~RT_ADDED;
5a2e9a25 1508 argv_reset (&argv);
6fbf66fa
JY
1509 gc_free (&gc);
1510}
1511
b55e49bd
GD
1512
1513static const char *
1514print_in6_addr_netbits_only( struct in6_addr network_copy, int netbits,
1515 struct gc_arena * gc)
1516{
1517 /* clear host bit parts of route
1518 * (needed if routes are specified improperly, or if we need to
1519 * explicitely setup/clear the "connected" network routes on some OSes)
1520 */
1521 int byte = 15;
1522 int bits_to_clear = 128 - netbits;
1523
1524 while( byte >= 0 && bits_to_clear > 0 )
1525 {
1526 if ( bits_to_clear >= 8 )
1527 { network_copy.s6_addr[byte--] = 0; bits_to_clear -= 8; }
1528 else
ffa1184d 1529 { network_copy.s6_addr[byte--] &= (0xff << bits_to_clear); bits_to_clear = 0; }
b55e49bd
GD
1530 }
1531
1532 return print_in6_addr( network_copy, 0, gc);
1533}
1534
512cda46
GD
1535void
1536add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
1537{
1538 struct gc_arena gc;
1539 struct argv argv;
1540
1541 const char *network;
1542 const char *gateway;
1543 bool status = false;
1544 const char *device = tt->actual_name;
512cda46 1545
ff9c39b6
GD
1546 bool gateway_needed = false;
1547
512cda46
GD
1548 if (!r6->defined)
1549 return;
1550
1551 gc_init (&gc);
1552 argv_init (&argv);
1553
b55e49bd 1554 network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
512cda46
GD
1555 gateway = print_in6_addr( r6->gateway, 0, &gc);
1556
1840c852
GD
1557 if ( !tt->ipv6 )
1558 {
1559 msg( M_INFO, "add_route_ipv6(): not adding %s/%d, no IPv6 on if %s",
1560 network, r6->netbits, device );
1561 return;
1562 }
1563
512cda46
GD
1564 msg( M_INFO, "add_route_ipv6(%s/%d -> %s metric %d) dev %s",
1565 network, r6->netbits, gateway, r6->metric, device );
1566
1567 /*
1568 * Filter out routes which are essentially no-ops
1569 * (not currently done for IPv6)
1570 */
1571
ff9c39b6
GD
1572 /* On "tun" interface, we never set a gateway if the operating system
1573 * can do "route to interface" - it does not add value, as the target
1574 * dev already fully qualifies the route destination on point-to-point
1575 * interfaces. OTOH, on "tap" interface, we must always set the
1576 * gateway unless the route is to be an on-link network
1577 */
1578 if ( tt->type == DEV_TYPE_TAP &&
1579 !(r6->metric_defined && r6->metric == 0 ) )
1580 {
1581 gateway_needed = true;
1582 }
1583
512cda46 1584#if defined(TARGET_LINUX)
51bd56f4 1585#ifdef ENABLE_IPROUTE
512cda46
GD
1586 argv_printf (&argv, "%s -6 route add %s/%d dev %s",
1587 iproute_path,
1588 network,
1589 r6->netbits,
1590 device);
ff9c39b6
GD
1591 if (gateway_needed)
1592 argv_printf_cat (&argv, "via %s", gateway);
c37d9135 1593 if (r6->metric_defined && r6->metric > 0 )
512cda46
GD
1594 argv_printf_cat (&argv, " metric %d", r6->metric);
1595
1596#else
1597 argv_printf (&argv, "%s -A inet6 add %s/%d dev %s",
1598 ROUTE_PATH,
1599 network,
1600 r6->netbits,
1601 device);
ff9c39b6
GD
1602 if (gateway_needed)
1603 argv_printf_cat (&argv, "gw %s", gateway);
c37d9135 1604 if (r6->metric_defined && r6->metric > 0 )
512cda46 1605 argv_printf_cat (&argv, " metric %d", r6->metric);
51bd56f4 1606#endif /*ENABLE_IPROUTE*/
512cda46
GD
1607 argv_msg (D_ROUTE, &argv);
1608 status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 add command failed");
1609
a55b3cdb
AS
1610#elif defined (TARGET_ANDROID)
1611 struct buffer out = alloc_buf_gc (64, &gc);
1612
05660e78 1613 buf_printf (&out, "%s/%d %s", network, r6->netbits, device);
a55b3cdb
AS
1614
1615 management_android_control (management, "ROUTE6", buf_bptr(&out));
1616
512cda46
GD
1617#elif defined (WIN32)
1618
6607def8
GD
1619 /* netsh interface ipv6 add route 2001:db8::/32 MyTunDevice */
1620 argv_printf (&argv, "%s%sc interface ipv6 add route %s/%d %s",
1621 get_win_sys_path(),
1622 NETSH_PATH_SUFFIX,
1623 network,
1624 r6->netbits,
1625 device);
1626
a9557fcb
GD
1627 /* next-hop depends on TUN or TAP mode:
1628 * - in TAP mode, we use the "real" next-hop
1629 * - in TUN mode we use a special-case link-local address that the tapdrvr
1630 * knows about and will answer ND (neighbor discovery) packets for
1631 */
1632 if ( tt->type == DEV_TYPE_TUN )
1633 argv_printf_cat( &argv, " %s", "fe80::8" );
1634 else
1635 argv_printf_cat( &argv, " %s", gateway );
1636
6607def8
GD
1637#if 0
1638 if (r->metric_defined)
a9557fcb 1639 argv_printf_cat (&argv, " METRIC %d", r->metric);
6607def8
GD
1640#endif
1641
b55e49bd
GD
1642 /* in some versions of Windows, routes are persistent across reboots by
1643 * default, unless "store=active" is set (pointed out by Tony Lim, thanks)
1644 */
1645 argv_printf_cat( &argv, " store=active" );
1646
6607def8
GD
1647 argv_msg (D_ROUTE, &argv);
1648
1649 netcmd_semaphore_lock ();
1650 status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add ipv6 command failed");
1651 netcmd_semaphore_release ();
512cda46
GD
1652
1653#elif defined (TARGET_SOLARIS)
1654
1655 /* example: route add -inet6 2001:db8::/32 somegateway 0 */
1656
1657 /* for some weird reason, this does not work for me unless I set
1658 * "metric 0" - otherwise, the routes will be nicely installed, but
1659 * packets will just disappear somewhere. So we use "0" now...
1660 */
1661
1662 argv_printf (&argv, "%s add -inet6 %s/%d %s 0",
1663 ROUTE_PATH,
1664 network,
1665 r6->netbits,
1666 gateway );
1667
1668 argv_msg (D_ROUTE, &argv);
1669 status = openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route add -inet6 command failed");
1670
1671#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
1672
ff9c39b6 1673 argv_printf (&argv, "%s add -inet6 %s/%d",
512cda46
GD
1674 ROUTE_PATH,
1675 network,
ff9c39b6
GD
1676 r6->netbits);
1677
1678 if (gateway_needed)
1679 argv_printf_cat (&argv, "%s", gateway);
1680 else
1681 argv_printf_cat (&argv, "-iface %s", device);
512cda46
GD
1682
1683 argv_msg (D_ROUTE, &argv);
1684 status = openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route add -inet6 command failed");
1685
1686#elif defined(TARGET_DARWIN)
1687
ff9c39b6 1688 argv_printf (&argv, "%s add -inet6 %s -prefixlen %d",
512cda46 1689 ROUTE_PATH,
ff9c39b6
GD
1690 network, r6->netbits );
1691
1692 if (gateway_needed)
1693 argv_printf_cat (&argv, "%s", gateway);
1694 else
1695 argv_printf_cat (&argv, "-iface %s", device);
512cda46
GD
1696
1697 argv_msg (D_ROUTE, &argv);
1698 status = openvpn_execve_check (&argv, es, 0, "ERROR: MacOS X route add -inet6 command failed");
1699
ada9769e 1700#elif defined(TARGET_OPENBSD)
512cda46 1701
ada9769e
GD
1702 argv_printf (&argv, "%s add -inet6 %s -prefixlen %d %s",
1703 ROUTE_PATH,
1704 network, r6->netbits, gateway );
1705
1706 argv_msg (D_ROUTE, &argv);
1707 status = openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD route add -inet6 command failed");
1708
1709#elif defined(TARGET_NETBSD)
512cda46
GD
1710
1711 argv_printf (&argv, "%s add -inet6 %s/%d %s",
1712 ROUTE_PATH,
1713 network, r6->netbits, gateway );
1714
1715 argv_msg (D_ROUTE, &argv);
ada9769e 1716 status = openvpn_execve_check (&argv, es, 0, "ERROR: NetBSD route add -inet6 command failed");
512cda46 1717
b4b92ae5
GD
1718#elif defined(TARGET_AIX)
1719
1720 argv_printf (&argv, "%s add -inet6 %s/%d %s",
1721 ROUTE_PATH,
1722 network, r6->netbits, gateway);
1723 argv_msg (D_ROUTE, &argv);
1724 status = openvpn_execve_check (&argv, es, 0, "ERROR: AIX route add command failed");
1725
512cda46
GD
1726#else
1727 msg (M_FATAL, "Sorry, but I don't know how to do 'route ipv6' commands on this operating system. Try putting your routes in a --route-up script");
1728#endif
1729
1730 r6->defined = status;
1731 argv_reset (&argv);
1732 gc_free (&gc);
1733}
1734
6fbf66fa 1735static void
b57e005b 1736delete_route (struct route_ipv4 *r,
7fb0e07e
JY
1737 const struct tuntap *tt,
1738 unsigned int flags,
1739 const struct route_gateway_info *rgi,
1740 const struct env_set *es)
6fbf66fa
JY
1741{
1742 struct gc_arena gc;
5a2e9a25 1743 struct argv argv;
6fbf66fa
JY
1744 const char *network;
1745 const char *netmask;
1746 const char *gateway;
7fb0e07e 1747 int is_local_route;
6fbf66fa 1748
7fb0e07e 1749 if ((r->flags & (RT_DEFINED|RT_ADDED)) != (RT_DEFINED|RT_ADDED))
6fbf66fa
JY
1750 return;
1751
1752 gc_init (&gc);
5a2e9a25 1753 argv_init (&argv);
6fbf66fa 1754
6fbf66fa
JY
1755 network = print_in_addr_t (r->network, 0, &gc);
1756 netmask = print_in_addr_t (r->netmask, 0, &gc);
1757 gateway = print_in_addr_t (r->gateway, 0, &gc);
1758
7fb0e07e
JY
1759 is_local_route = local_route(r->network, r->netmask, r->gateway, rgi);
1760 if (is_local_route == LR_ERROR)
1761 goto done;
1762
6fbf66fa 1763#if defined(TARGET_LINUX)
51bd56f4 1764#ifdef ENABLE_IPROUTE
5a2e9a25 1765 argv_printf (&argv, "%s route del %s/%d",
0aee9ca7 1766 iproute_path,
6fbf66fa
JY
1767 network,
1768 count_netmask_bits(netmask));
1769#else
5a2e9a25 1770 argv_printf (&argv, "%s del -net %s netmask %s",
7fb0e07e
JY
1771 ROUTE_PATH,
1772 network,
1773 netmask);
51bd56f4 1774#endif /*ENABLE_IPROUTE*/
7fb0e07e 1775 if (r->flags & RT_METRIC_DEFINED)
5a2e9a25
JY
1776 argv_printf_cat (&argv, "metric %d", r->metric);
1777 argv_msg (D_ROUTE, &argv);
1778 openvpn_execve_check (&argv, es, 0, "ERROR: Linux route delete command failed");
6fbf66fa
JY
1779
1780#elif defined (WIN32)
1781
a8281352 1782 argv_printf (&argv, "%s%sc DELETE %s MASK %s %s",
5a2e9a25
JY
1783 get_win_sys_path(),
1784 WIN_ROUTE_PATH_SUFFIX,
1785 network,
1786 netmask,
1787 gateway);
6fbf66fa 1788
5a2e9a25 1789 argv_msg (D_ROUTE, &argv);
6fbf66fa
JY
1790
1791 if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_IPAPI)
1792 {
1793 const bool status = del_route_ipapi (r, tt);
1794 msg (D_ROUTE, "Route deletion via IPAPI %s", status ? "succeeded" : "failed");
1795 }
1796 else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_EXE)
1797 {
1798 netcmd_semaphore_lock ();
5a2e9a25 1799 openvpn_execve_check (&argv, es, 0, "ERROR: Windows route delete command failed");
6fbf66fa
JY
1800 netcmd_semaphore_release ();
1801 }
6215931b
JY
1802 else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_ADAPTIVE)
1803 {
1804 const bool status = del_route_ipapi (r, tt);
1805 msg (D_ROUTE, "Route deletion via IPAPI %s [adaptive]", status ? "succeeded" : "failed");
1806 if (!status)
1807 {
1808 msg (D_ROUTE, "Route deletion fallback to route.exe");
1809 netcmd_semaphore_lock ();
5a2e9a25 1810 openvpn_execve_check (&argv, es, 0, "ERROR: Windows route delete command failed [adaptive]");
6215931b
JY
1811 netcmd_semaphore_release ();
1812 }
1813 }
6fbf66fa
JY
1814 else
1815 {
1816 ASSERT (0);
1817 }
1818
1819#elif defined (TARGET_SOLARIS)
1820
5a2e9a25
JY
1821 argv_printf (&argv, "%s delete %s -netmask %s %s",
1822 ROUTE_PATH,
6fbf66fa
JY
1823 network,
1824 netmask,
1825 gateway);
1826
5a2e9a25
JY
1827 argv_msg (D_ROUTE, &argv);
1828 openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route delete command failed");
6fbf66fa
JY
1829
1830#elif defined(TARGET_FREEBSD)
1831
5a2e9a25
JY
1832 argv_printf (&argv, "%s delete -net %s %s %s",
1833 ROUTE_PATH,
6fbf66fa
JY
1834 network,
1835 gateway,
1836 netmask);
1837
5a2e9a25
JY
1838 argv_msg (D_ROUTE, &argv);
1839 openvpn_execve_check (&argv, es, 0, "ERROR: FreeBSD route delete command failed");
6fbf66fa 1840
1bda73a7
JY
1841#elif defined(TARGET_DRAGONFLY)
1842
5a2e9a25
JY
1843 argv_printf (&argv, "%s delete -net %s %s %s",
1844 ROUTE_PATH,
1bda73a7
JY
1845 network,
1846 gateway,
1847 netmask);
1848
5a2e9a25
JY
1849 argv_msg (D_ROUTE, &argv);
1850 openvpn_execve_check (&argv, es, 0, "ERROR: DragonFly route delete command failed");
1bda73a7 1851
6fbf66fa
JY
1852#elif defined(TARGET_DARWIN)
1853
8fc83a2d 1854 if (is_on_link (is_local_route, flags, rgi))
7fb0e07e
JY
1855 {
1856 argv_printf (&argv, "%s delete -cloning -net %s -netmask %s -interface %s",
1857 ROUTE_PATH,
1858 network,
1859 netmask,
1860 rgi->iface);
1861 }
1862 else
1863 {
1864 argv_printf (&argv, "%s delete -net %s %s %s",
1865 ROUTE_PATH,
1866 network,
1867 gateway,
1868 netmask);
1869 }
6fbf66fa 1870
5a2e9a25
JY
1871 argv_msg (D_ROUTE, &argv);
1872 openvpn_execve_check (&argv, es, 0, "ERROR: OS X route delete command failed");
6fbf66fa
JY
1873
1874#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1875
5a2e9a25
JY
1876 argv_printf (&argv, "%s delete -net %s %s -netmask %s",
1877 ROUTE_PATH,
6fbf66fa
JY
1878 network,
1879 gateway,
1880 netmask);
1881
5a2e9a25
JY
1882 argv_msg (D_ROUTE, &argv);
1883 openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route delete command failed");
b4b92ae5 1884
a55b3cdb
AS
1885#elif defined(TARGET_ANDROID)
1886 msg (M_NONFATAL, "Sorry, deleting routes on Android is not possible. The VpnService API allows routes to be set on connect only.");
b4b92ae5
GD
1887
1888#elif defined(TARGET_AIX)
1889
1890 {
1891 int netbits = netmask_to_netbits2(r->netmask);
1892 argv_printf (&argv, "%s delete -net %s/%d %s",
1893 ROUTE_PATH,
1894 network, netbits, gateway);
1895 argv_msg (D_ROUTE, &argv);
1896 openvpn_execve_check (&argv, es, 0, "ERROR: AIX route delete command failed");
1897 }
1898
6fbf66fa
JY
1899#else
1900 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");
1901#endif
1902
7fb0e07e
JY
1903 done:
1904 r->flags &= ~RT_ADDED;
5a2e9a25 1905 argv_reset (&argv);
6fbf66fa
JY
1906 gc_free (&gc);
1907}
1908
b55e49bd 1909void
512cda46
GD
1910delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
1911{
1912 struct gc_arena gc;
1913 struct argv argv;
1914 const char *network;
1915 const char *gateway;
1916 const char *device = tt->actual_name;
ff9c39b6 1917 bool gateway_needed = false;
512cda46
GD
1918
1919 if (!r6->defined)
1920 return;
1921
1922 gc_init (&gc);
1923 argv_init (&argv);
1924
b55e49bd 1925 network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
512cda46
GD
1926 gateway = print_in6_addr( r6->gateway, 0, &gc);
1927
1840c852
GD
1928 if ( !tt->ipv6 )
1929 {
1930 msg( M_INFO, "delete_route_ipv6(): not deleting %s/%d, no IPv6 on if %s",
1931 network, r6->netbits, device );
1932 return;
1933 }
1934
512cda46
GD
1935 msg( M_INFO, "delete_route_ipv6(%s/%d)", network, r6->netbits );
1936
ff9c39b6
GD
1937 /* if we used a gateway on "add route", we also need to specify it on
1938 * delete, otherwise some OSes will refuse to delete the route
1939 */
1940 if ( tt->type == DEV_TYPE_TAP &&
1941 !(r6->metric_defined && r6->metric == 0 ) )
1942 {
1943 gateway_needed = true;
1944 }
1945
1946
512cda46 1947#if defined(TARGET_LINUX)
51bd56f4 1948#ifdef ENABLE_IPROUTE
512cda46
GD
1949 argv_printf (&argv, "%s -6 route del %s/%d dev %s",
1950 iproute_path,
1951 network,
1952 r6->netbits,
1953 device);
ff9c39b6
GD
1954 if (gateway_needed)
1955 argv_printf_cat (&argv, "via %s", gateway);
512cda46
GD
1956#else
1957 argv_printf (&argv, "%s -A inet6 del %s/%d dev %s",
1958 ROUTE_PATH,
1959 network,
1960 r6->netbits,
1961 device);
ff9c39b6
GD
1962 if (gateway_needed)
1963 argv_printf_cat (&argv, "gw %s", gateway);
1964 if (r6->metric_defined && r6->metric > 0 )
1965 argv_printf_cat (&argv, " metric %d", r6->metric);
51bd56f4 1966#endif /*ENABLE_IPROUTE*/
512cda46
GD
1967 argv_msg (D_ROUTE, &argv);
1968 openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 del command failed");
1969
1970#elif defined (WIN32)
1971
6607def8
GD
1972 /* netsh interface ipv6 delete route 2001:db8::/32 MyTunDevice */
1973 argv_printf (&argv, "%s%sc interface ipv6 delete route %s/%d %s",
1974 get_win_sys_path(),
1975 NETSH_PATH_SUFFIX,
1976 network,
1977 r6->netbits,
1978 device);
1979
94d50a17
GD
1980 /* next-hop depends on TUN or TAP mode:
1981 * - in TAP mode, we use the "real" next-hop
1982 * - in TUN mode we use a special-case link-local address that the tapdrvr
1983 * knows about and will answer ND (neighbor discovery) packets for
1984 * (and "route deletion without specifying next-hop" does not work...)
1985 */
1986 if ( tt->type == DEV_TYPE_TUN )
1987 argv_printf_cat( &argv, " %s", "fe80::8" );
1988 else
1989 argv_printf_cat( &argv, " %s", gateway );
1990
6607def8
GD
1991#if 0
1992 if (r->metric_defined)
1993 argv_printf_cat (&argv, "METRIC %d", r->metric);
1994#endif
1995
4b4fac91
GD
1996 /* Windows XP to 7 "just delete" routes, wherever they came from, but
1997 * in Windows 8(.1?), if you create them with "store=active", this is
1998 * how you should delete them as well (pointed out by Cedric Tabary)
1999 */
2000 argv_printf_cat( &argv, " store=active" );
2001
6607def8
GD
2002 argv_msg (D_ROUTE, &argv);
2003
2004 netcmd_semaphore_lock ();
4b4fac91 2005 openvpn_execve_check (&argv, es, 0, "ERROR: Windows route delete ipv6 command failed");
6607def8 2006 netcmd_semaphore_release ();
512cda46
GD
2007
2008#elif defined (TARGET_SOLARIS)
2009
2010 /* example: route delete -inet6 2001:db8::/32 somegateway */
2011 /* GERT-TODO: this is untested, but should work */
2012
2013 argv_printf (&argv, "%s delete -inet6 %s/%d %s",
2014 ROUTE_PATH,
2015 network,
2016 r6->netbits,
2017 gateway );
2018
2019 argv_msg (D_ROUTE, &argv);
2020 openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route delete -inet6 command failed");
2021
2022#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2023
ff9c39b6 2024 argv_printf (&argv, "%s delete -inet6 %s/%d",
512cda46
GD
2025 ROUTE_PATH,
2026 network,
ff9c39b6
GD
2027 r6->netbits );
2028
2029 if (gateway_needed)
2030 argv_printf_cat (&argv, "%s", gateway);
2031 else
2032 argv_printf_cat (&argv, "-iface %s", device);
512cda46
GD
2033
2034 argv_msg (D_ROUTE, &argv);
2035 openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route delete -inet6 command failed");
2036
2037#elif defined(TARGET_DARWIN)
2038
ff9c39b6 2039 argv_printf (&argv, "%s delete -inet6 %s -prefixlen %d",
512cda46 2040 ROUTE_PATH,
ff9c39b6
GD
2041 network, r6->netbits );
2042
2043 if (gateway_needed)
2044 argv_printf_cat (&argv, "%s", gateway);
2045 else
2046 argv_printf_cat (&argv, "-iface %s", device);
512cda46
GD
2047
2048 argv_msg (D_ROUTE, &argv);
ff9c39b6 2049 openvpn_execve_check (&argv, es, 0, "ERROR: MacOS X route delete -inet6 command failed");
512cda46 2050
ada9769e 2051#elif defined(TARGET_OPENBSD)
512cda46 2052
ada9769e
GD
2053 argv_printf (&argv, "%s delete -inet6 %s -prefixlen %d %s",
2054 ROUTE_PATH,
2055 network, r6->netbits, gateway );
2056
2057 argv_msg (D_ROUTE, &argv);
2058 openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD route delete -inet6 command failed");
2059
2060#elif defined(TARGET_NETBSD)
512cda46
GD
2061
2062 argv_printf (&argv, "%s delete -inet6 %s/%d %s",
2063 ROUTE_PATH,
2064 network, r6->netbits, gateway );
2065
2066 argv_msg (D_ROUTE, &argv);
ada9769e 2067 openvpn_execve_check (&argv, es, 0, "ERROR: NetBSD route delete -inet6 command failed");
512cda46 2068
b4b92ae5
GD
2069#elif defined(TARGET_AIX)
2070
2071 argv_printf (&argv, "%s delete -inet6 %s/%d %s",
2072 ROUTE_PATH,
2073 network, r6->netbits, gateway);
2074 argv_msg (D_ROUTE, &argv);
2075 openvpn_execve_check (&argv, es, 0, "ERROR: AIX route add command failed");
2076
512cda46
GD
2077#else
2078 msg (M_FATAL, "Sorry, but I don't know how to do 'route ipv6' commands on this operating system. Try putting your routes in a --route-down script");
2079#endif
2080
2081 argv_reset (&argv);
2082 gc_free (&gc);
2083}
2084
6fbf66fa
JY
2085/*
2086 * The --redirect-gateway option requires OS-specific code below
2087 * to get the current default gateway.
2088 */
2089
2090#if defined(WIN32)
2091
2092static const MIB_IPFORWARDTABLE *
2093get_windows_routing_table (struct gc_arena *gc)
2094{
2095 ULONG size = 0;
2096 PMIB_IPFORWARDTABLE rt = NULL;
2097 DWORD status;
2098
2099 status = GetIpForwardTable (NULL, &size, TRUE);
2100 if (status == ERROR_INSUFFICIENT_BUFFER)
2101 {
2102 rt = (PMIB_IPFORWARDTABLE) gc_malloc (size, false, gc);
2103 status = GetIpForwardTable (rt, &size, TRUE);
2104 if (status != NO_ERROR)
2105 {
2106 msg (D_ROUTE, "NOTE: GetIpForwardTable returned error: %s (code=%u)",
2107 strerror_win32 (status, gc),
2108 (unsigned int)status);
2109 rt = NULL;
2110 }
2111 }
2112 return rt;
2113}
2114
2115static int
2116test_route (const IP_ADAPTER_INFO *adapters,
2117 const in_addr_t gateway,
2118 DWORD *index)
2119{
2120 int count = 0;
f77c60d3 2121 DWORD i = adapter_index_of_ip (adapters, gateway, &count, NULL);
6fbf66fa
JY
2122 if (index)
2123 *index = i;
2124 return count;
2125}
2126
2127static void
2128test_route_helper (bool *ret,
2129 int *count,
2130 int *good,
2131 int *ambig,
2132 const IP_ADAPTER_INFO *adapters,
2133 const in_addr_t gateway)
2134{
2135 int c;
2136
2137 ++*count;
2138 c = test_route (adapters, gateway, NULL);
2139 if (c == 0)
2140 *ret = false;
2141 else
2142 ++*good;
2143 if (c > 1)
2144 ++*ambig;
2145}
2146
2147/*
2148 * If we tried to add routes now, would we succeed?
2149 */
2150bool
2151test_routes (const struct route_list *rl, const struct tuntap *tt)
2152{
2153 struct gc_arena gc = gc_new ();
2154 const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
2155 bool ret = false;
2156 int count = 0;
2157 int good = 0;
2158 int ambig = 0;
d0085293 2159 int len = -1;
6fbf66fa
JY
2160 bool adapter_up = false;
2161
2162 if (is_adapter_up (tt, adapters))
2163 {
2164 ret = true;
2165 adapter_up = true;
2166
2167 if (rl)
2168 {
60b40a58 2169 struct route_ipv4 *r;
d0085293
HH
2170 for (r = rl->routes, len = 0; r; r = r->next, ++len)
2171 test_route_helper (&ret, &count, &good, &ambig, adapters, r->gateway);
6fbf66fa 2172
7fb0e07e 2173 if ((rl->flags & RG_ENABLE) && (rl->spec.flags & RTSA_REMOTE_ENDPOINT))
6fbf66fa
JY
2174 test_route_helper (&ret, &count, &good, &ambig, adapters, rl->spec.remote_endpoint);
2175 }
2176 }
2177
2178 msg (D_ROUTE, "TEST ROUTES: %d/%d succeeded len=%d ret=%d a=%d u/d=%s",
2179 good,
2180 count,
d0085293 2181 len,
6fbf66fa
JY
2182 (int)ret,
2183 ambig,
2184 adapter_up ? "up" : "down");
2185
2186 gc_free (&gc);
2187 return ret;
2188}
2189
3c7f2f55
JY
2190static const MIB_IPFORWARDROW *
2191get_default_gateway_row (const MIB_IPFORWARDTABLE *routes)
6fbf66fa 2192{
348fb443 2193 struct gc_arena gc = gc_new ();
12e46092 2194 DWORD lowest_metric = MAXDWORD;
3c7f2f55 2195 const MIB_IPFORWARDROW *ret = NULL;
6fbf66fa 2196 int i;
348fb443 2197 int best = -1;
6fbf66fa 2198
3c7f2f55 2199 if (routes)
6fbf66fa 2200 {
3c7f2f55
JY
2201 for (i = 0; i < routes->dwNumEntries; ++i)
2202 {
2203 const MIB_IPFORWARDROW *row = &routes->table[i];
2204 const in_addr_t net = ntohl (row->dwForwardDest);
2205 const in_addr_t mask = ntohl (row->dwForwardMask);
2206 const DWORD index = row->dwForwardIfIndex;
348fb443 2207 const DWORD metric = row->dwForwardMetric1;
6fbf66fa 2208
348fb443
JY
2209 dmsg (D_ROUTE_DEBUG, "GDGR: route[%d] %s/%s i=%d m=%d",
2210 i,
2211 print_in_addr_t ((in_addr_t) net, 0, &gc),
2212 print_in_addr_t ((in_addr_t) mask, 0, &gc),
2213 (int)index,
2214 (int)metric);
3c7f2f55 2215
348fb443 2216 if (!net && !mask && metric < lowest_metric)
3c7f2f55
JY
2217 {
2218 ret = row;
348fb443
JY
2219 lowest_metric = metric;
2220 best = i;
3c7f2f55 2221 }
6fbf66fa
JY
2222 }
2223 }
348fb443
JY
2224
2225 dmsg (D_ROUTE_DEBUG, "GDGR: best=%d lm=%u", best, (unsigned int)lowest_metric);
2226
2227 gc_free (&gc);
3c7f2f55
JY
2228 return ret;
2229}
2230
7fb0e07e
JY
2231void
2232get_default_gateway (struct route_gateway_info *rgi)
3c7f2f55
JY
2233{
2234 struct gc_arena gc = gc_new ();
3c7f2f55 2235
f77c60d3 2236 const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
3c7f2f55
JY
2237 const MIB_IPFORWARDTABLE *routes = get_windows_routing_table (&gc);
2238 const MIB_IPFORWARDROW *row = get_default_gateway_row (routes);
7fb0e07e
JY
2239 DWORD a_index;
2240 const IP_ADAPTER_INFO *ai;
2241
2242 CLEAR(*rgi);
3c7f2f55
JY
2243
2244 if (row)
2245 {
7fb0e07e
JY
2246 rgi->gateway.addr = ntohl (row->dwForwardNextHop);
2247 if (rgi->gateway.addr)
f77c60d3 2248 {
7fb0e07e
JY
2249 rgi->flags |= RGI_ADDR_DEFINED;
2250 a_index = adapter_index_of_ip (adapters, rgi->gateway.addr, NULL, &rgi->gateway.netmask);
12e46092 2251 if (a_index != TUN_ADAPTER_INDEX_INVALID)
7fb0e07e
JY
2252 {
2253 rgi->adapter_index = a_index;
2254 rgi->flags |= (RGI_IFACE_DEFINED|RGI_NETMASK_DEFINED);
2255 ai = get_adapter (adapters, a_index);
2256 if (ai)
2257 {
2258 memcpy (rgi->hwaddr, ai->Address, 6);
2259 rgi->flags |= RGI_HWADDR_DEFINED;
2260 }
2261 }
f77c60d3 2262 }
3c7f2f55
JY
2263 }
2264
6fbf66fa 2265 gc_free (&gc);
6fbf66fa
JY
2266}
2267
2268static DWORD
b57e005b 2269windows_route_find_if_index (const struct route_ipv4 *r, const struct tuntap *tt)
6fbf66fa
JY
2270{
2271 struct gc_arena gc = gc_new ();
12e46092 2272 DWORD ret = TUN_ADAPTER_INDEX_INVALID;
6fbf66fa
JY
2273 int count = 0;
2274 const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
2275 const IP_ADAPTER_INFO *tun_adapter = get_tun_adapter (tt, adapters);
2276 bool on_tun = false;
2277
2278 /* first test on tun interface */
2279 if (is_ip_in_adapter_subnet (tun_adapter, r->gateway, NULL))
2280 {
2281 ret = tun_adapter->Index;
2282 count = 1;
2283 on_tun = true;
2284 }
2285 else /* test on other interfaces */
2286 {
2287 count = test_route (adapters, r->gateway, &ret);
2288 }
2289
2290 if (count == 0)
2291 {
2292 msg (M_WARN, "Warning: route gateway is not reachable on any active network adapters: %s",
2293 print_in_addr_t (r->gateway, 0, &gc));
12e46092 2294 ret = TUN_ADAPTER_INDEX_INVALID;
6fbf66fa
JY
2295 }
2296 else if (count > 1)
2297 {
2298 msg (M_WARN, "Warning: route gateway is ambiguous: %s (%d matches)",
2299 print_in_addr_t (r->gateway, 0, &gc),
2300 count);
12e46092 2301 ret = TUN_ADAPTER_INDEX_INVALID;
6fbf66fa
JY
2302 }
2303
2304 dmsg (D_ROUTE_DEBUG, "DEBUG: route find if: on_tun=%d count=%d index=%d",
2305 on_tun,
2306 count,
2307 (int)ret);
2308
2309 gc_free (&gc);
2310 return ret;
2311}
2312
2313bool
b57e005b 2314add_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt, DWORD adapter_index)
6fbf66fa
JY
2315{
2316 struct gc_arena gc = gc_new ();
2317 bool ret = false;
2318 DWORD status;
12e46092 2319 const DWORD if_index = (adapter_index == TUN_ADAPTER_INDEX_INVALID) ? windows_route_find_if_index (r, tt) : adapter_index;
6fbf66fa 2320
12e46092 2321 if (if_index != TUN_ADAPTER_INDEX_INVALID)
6fbf66fa
JY
2322 {
2323 MIB_IPFORWARDROW fr;
2324 CLEAR (fr);
2325 fr.dwForwardDest = htonl (r->network);
2326 fr.dwForwardMask = htonl (r->netmask);
2327 fr.dwForwardPolicy = 0;
2328 fr.dwForwardNextHop = htonl (r->gateway);
2329 fr.dwForwardIfIndex = if_index;
2330 fr.dwForwardType = 4; /* the next hop is not the final dest */
2331 fr.dwForwardProto = 3; /* PROTO_IP_NETMGMT */
2332 fr.dwForwardAge = 0;
2333 fr.dwForwardNextHopAS = 0;
7fb0e07e 2334 fr.dwForwardMetric1 = (r->flags & RT_METRIC_DEFINED) ? r->metric : 1;
12e46092
ABL
2335 fr.dwForwardMetric2 = METRIC_NOT_USED;
2336 fr.dwForwardMetric3 = METRIC_NOT_USED;
2337 fr.dwForwardMetric4 = METRIC_NOT_USED;
2338 fr.dwForwardMetric5 = METRIC_NOT_USED;
6fbf66fa
JY
2339
2340 if ((r->network & r->netmask) != r->network)
2341 msg (M_WARN, "Warning: address %s is not a network address in relation to netmask %s",
2342 print_in_addr_t (r->network, 0, &gc),
2343 print_in_addr_t (r->netmask, 0, &gc));
2344
2345 status = CreateIpForwardEntry (&fr);
2346
2347 if (status == NO_ERROR)
2348 ret = true;
2349 else
2350 {
94a43500
JY
2351 /* failed, try increasing the metric to work around Vista issue */
2352 const unsigned int forward_metric_limit = 2048; /* iteratively retry higher metrics up to this limit */
6fbf66fa 2353
94a43500
JY
2354 for ( ; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
2355 {
2356 /* try a different forward type=3 ("the next hop is the final dest") in addition to 4.
2357 --redirect-gateway over RRAS seems to need this. */
2358 for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
2359 {
2360 status = CreateIpForwardEntry (&fr);
2361 if (status == NO_ERROR)
2362 {
2363 msg (D_ROUTE, "ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%u and dwForwardType=%u",
2364 (unsigned int)fr.dwForwardMetric1,
2365 (unsigned int)fr.dwForwardType);
2366 ret = true;
2367 goto doublebreak;
2368 }
2369 else if (status != ERROR_BAD_ARGUMENTS)
2370 goto doublebreak;
2371 }
2372 }
6fbf66fa 2373
94a43500
JY
2374 doublebreak:
2375 if (status != NO_ERROR)
2376 msg (M_WARN, "ROUTE: route addition failed using CreateIpForwardEntry: %s [status=%u if_index=%u]",
6fbf66fa 2377 strerror_win32 (status, &gc),
94a43500 2378 (unsigned int)status,
6fbf66fa
JY
2379 (unsigned int)if_index);
2380 }
2381 }
2382
2383 gc_free (&gc);
2384 return ret;
2385}
2386
2387bool
b57e005b 2388del_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt)
6fbf66fa
JY
2389{
2390 struct gc_arena gc = gc_new ();
2391 bool ret = false;
2392 DWORD status;
2393 const DWORD if_index = windows_route_find_if_index (r, tt);
2394
12e46092 2395 if (if_index != TUN_ADAPTER_INDEX_INVALID)
6fbf66fa
JY
2396 {
2397 MIB_IPFORWARDROW fr;
2398 CLEAR (fr);
2399
2400 fr.dwForwardDest = htonl (r->network);
2401 fr.dwForwardMask = htonl (r->netmask);
2402 fr.dwForwardPolicy = 0;
2403 fr.dwForwardNextHop = htonl (r->gateway);
2404 fr.dwForwardIfIndex = if_index;
2405
2406 status = DeleteIpForwardEntry (&fr);
2407
2408 if (status == NO_ERROR)
2409 ret = true;
2410 else
2411 msg (M_WARN, "ROUTE: route deletion failed using DeleteIpForwardEntry: %s",
2412 strerror_win32 (status, &gc));
2413 }
2414
2415 gc_free (&gc);
2416 return ret;
2417}
2418
2419static const char *
2420format_route_entry (const MIB_IPFORWARDROW *r, struct gc_arena *gc)
2421{
2422 struct buffer out = alloc_buf_gc (256, gc);
2423 buf_printf (&out, "%s %s %s p=%d i=%d t=%d pr=%d a=%d h=%d m=%d/%d/%d/%d/%d",
2424 print_in_addr_t (r->dwForwardDest, IA_NET_ORDER, gc),
2425 print_in_addr_t (r->dwForwardMask, IA_NET_ORDER, gc),
2426 print_in_addr_t (r->dwForwardNextHop, IA_NET_ORDER, gc),
2427 (int)r->dwForwardPolicy,
2428 (int)r->dwForwardIfIndex,
2429 (int)r->dwForwardType,
2430 (int)r->dwForwardProto,
2431 (int)r->dwForwardAge,
2432 (int)r->dwForwardNextHopAS,
2433 (int)r->dwForwardMetric1,
2434 (int)r->dwForwardMetric2,
2435 (int)r->dwForwardMetric3,
2436 (int)r->dwForwardMetric4,
2437 (int)r->dwForwardMetric5);
2438 return BSTR (&out);
2439}
2440
2441/*
2442 * Show current routing table
2443 */
2444void
2445show_routes (int msglev)
2446{
2447 struct gc_arena gc = gc_new ();
2448 int i;
2449
2450 const MIB_IPFORWARDTABLE *rt = get_windows_routing_table (&gc);
2451
2452 msg (msglev, "SYSTEM ROUTING TABLE");
2453 if (rt)
2454 {
2455 for (i = 0; i < rt->dwNumEntries; ++i)
2456 {
2457 msg (msglev, "%s", format_route_entry (&rt->table[i], &gc));
2458 }
2459 }
2460 gc_free (&gc);
2461}
2462
a55b3cdb 2463#elif defined(TARGET_LINUX) || defined(TARGET_ANDROID)
6fbf66fa 2464
7fb0e07e
JY
2465void
2466get_default_gateway (struct route_gateway_info *rgi)
6fbf66fa
JY
2467{
2468 struct gc_arena gc = gc_new ();
7fb0e07e 2469 int sd = -1;
8fc83a2d
JY
2470 char best_name[16];
2471 best_name[0] = 0;
7fb0e07e
JY
2472
2473 CLEAR(*rgi);
2474
2475 /* get default gateway IP addr */
2476 {
2477 FILE *fp = fopen ("/proc/net/route", "r");
2478 if (fp)
2479 {
2480 char line[256];
2481 int count = 0;
112731fc 2482 unsigned int lowest_metric = UINT_MAX;
7fb0e07e 2483 in_addr_t best_gw = 0;
8fc83a2d 2484 bool found = false;
7fb0e07e
JY
2485 while (fgets (line, sizeof (line), fp) != NULL)
2486 {
2487 if (count)
2488 {
2489 unsigned int net_x = 0;
2490 unsigned int mask_x = 0;
2491 unsigned int gw_x = 0;
2492 unsigned int metric = 0;
2493 unsigned int flags = 0;
8fc83a2d
JY
2494 char name[16];
2495 name[0] = 0;
2496 const int np = sscanf (line, "%15s\t%x\t%x\t%x\t%*s\t%*s\t%d\t%x",
2497 name,
7fb0e07e
JY
2498 &net_x,
2499 &gw_x,
2500 &flags,
2501 &metric,
2502 &mask_x);
8fc83a2d 2503 if (np == 6 && (flags & IFF_UP))
7fb0e07e
JY
2504 {
2505 const in_addr_t net = ntohl (net_x);
2506 const in_addr_t mask = ntohl (mask_x);
2507 const in_addr_t gw = ntohl (gw_x);
2508
2509 if (!net && !mask && metric < lowest_metric)
2510 {
8fc83a2d 2511 found = true;
7fb0e07e 2512 best_gw = gw;
8fc83a2d 2513 strcpy (best_name, name);
7fb0e07e
JY
2514 lowest_metric = metric;
2515 }
2516 }
2517 }
2518 ++count;
2519 }
2520 fclose (fp);
2521
8fc83a2d 2522 if (found)
7fb0e07e
JY
2523 {
2524 rgi->gateway.addr = best_gw;
2525 rgi->flags |= RGI_ADDR_DEFINED;
8fc83a2d
JY
2526 if (!rgi->gateway.addr && best_name[0])
2527 rgi->flags |= RGI_ON_LINK;
7fb0e07e
JY
2528 }
2529 }
2530 }
2531
2532 /* scan adapter list */
2533 if (rgi->flags & RGI_ADDR_DEFINED)
2534 {
2535 struct ifreq *ifr, *ifend;
2536 in_addr_t addr, netmask;
2537 struct ifreq ifreq;
2538 struct ifconf ifc;
2539 struct ifreq ifs[20]; /* Maximum number of interfaces to scan */
2540
2541 if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
6fbf66fa 2542 {
7fb0e07e
JY
2543 msg (M_WARN, "GDG: socket() failed");
2544 goto done;
2545 }
2546 ifc.ifc_len = sizeof (ifs);
2547 ifc.ifc_req = ifs;
2548 if (ioctl (sd, SIOCGIFCONF, &ifc) < 0)
2549 {
2550 msg (M_WARN, "GDG: ioctl(SIOCGIFCONF) failed");
2551 goto done;
6fbf66fa 2552 }
c9241348 2553
7fb0e07e
JY
2554 /* scan through interface list */
2555 ifend = ifs + (ifc.ifc_len / sizeof (struct ifreq));
2556 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
03653f42 2557 {
7fb0e07e 2558 if (ifr->ifr_addr.sa_family == AF_INET)
f77c60d3 2559 {
7fb0e07e
JY
2560 /* get interface addr */
2561 addr = ntohl(((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
2562
2563 /* get interface name */
2564 strncpynt (ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
2565
8fc83a2d 2566 /* check that the interface is up */
7fb0e07e
JY
2567 if (ioctl (sd, SIOCGIFFLAGS, &ifreq) < 0)
2568 continue;
2569 if (!(ifreq.ifr_flags & IFF_UP))
2570 continue;
2571
8fc83a2d
JY
2572 if (rgi->flags & RGI_ON_LINK)
2573 {
2574 /* check that interface name of current interface
2575 matches interface name of best default route */
2576 if (strcmp(ifreq.ifr_name, best_name))
2577 continue;
2578#if 0
2579 /* if point-to-point link, use remote addr as route gateway */
2580 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl (sd, SIOCGIFDSTADDR, &ifreq) >= 0)
2581 {
2582 rgi->gateway.addr = ntohl(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
2583 if (rgi->gateway.addr)
2584 rgi->flags &= ~RGI_ON_LINK;
2585 }
2586#endif
2587 }
2588 else
2589 {
2590 /* get interface netmask */
2591 if (ioctl (sd, SIOCGIFNETMASK, &ifreq) < 0)
2592 continue;
2593 netmask = ntohl(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
2594
2595 /* check that interface matches default route */
2596 if (((rgi->gateway.addr ^ addr) & netmask) != 0)
2597 continue;
2598
2599 /* save netmask */
2600 rgi->gateway.netmask = netmask;
2601 rgi->flags |= RGI_NETMASK_DEFINED;
2602 }
7fb0e07e 2603
8fc83a2d 2604 /* save iface name */
7fb0e07e 2605 strncpynt (rgi->iface, ifreq.ifr_name, sizeof(rgi->iface));
8fc83a2d 2606 rgi->flags |= RGI_IFACE_DEFINED;
576dc96c 2607
7fb0e07e
JY
2608 /* now get the hardware address. */
2609 memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
2610 if (ioctl (sd, SIOCGIFHWADDR, &ifreq) < 0)
2611 {
2612 msg (M_WARN, "GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
2613 goto done;
2614 }
2615 memcpy (rgi->hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
2616 rgi->flags |= RGI_HWADDR_DEFINED;
2617
2618 break;
f77c60d3 2619 }
03653f42 2620 }
6fbf66fa
JY
2621 }
2622
7fb0e07e
JY
2623 done:
2624 if (sd >= 0)
2625 close (sd);
6fbf66fa 2626 gc_free (&gc);
6fbf66fa
JY
2627}
2628
cab6305b
GD
2629#elif defined(TARGET_DARWIN) || \
2630 defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) || \
2631 defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
6fbf66fa
JY
2632
2633#include <sys/types.h>
2634#include <sys/socket.h>
2635#include <netinet/in.h>
6a8ea970
JY
2636#include <net/route.h>
2637#include <net/if_dl.h>
6fbf66fa 2638
6a8ea970 2639struct rtmsg {
6fbf66fa
JY
2640 struct rt_msghdr m_rtm;
2641 char m_space[512];
6a8ea970 2642};
6fbf66fa 2643
cab6305b
GD
2644/* the route socket code is identical for all 4 supported BSDs and for
2645 * MacOS X (Darwin), with one crucial difference: when going from
2646 * 32 bit to 64 bit, the BSDs increased the structure size but kept
2647 * source code compatibility by keeping the use of "long", while
2648 * MacOS X decided to keep binary compatibility by *changing* the API
2649 * to use "uint32_t", thus 32 bit on all OS X variants
2650 *
2651 * We used to have a large amount of duplicate code here which really
2652 * differed only in this (long) vs. (uint32_t) - IMHO, worse than
2653 * having a combined block for all BSDs with this single #ifdef inside
2654 */
2655
2656#if defined(TARGET_DARWIN)
2657# define ROUNDUP(a) \
3f7c03a2 2658 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
cab6305b
GD
2659#else
2660# define ROUNDUP(a) \
2661 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
2662#endif
6fbf66fa 2663
7fb0e07e
JY
2664#define NEXTADDR(w, u) \
2665 if (rtm_addrs & (w)) {\
2666 l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
2667 }
2668
2669#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
2670
2671#define max(a,b) ((a) > (b) ? (a) : (b))
2672
2673void
2674get_default_gateway (struct route_gateway_info *rgi)
6fbf66fa
JY
2675{
2676 struct gc_arena gc = gc_new ();
6a8ea970 2677 struct rtmsg m_rtmsg;
7fb0e07e
JY
2678 int sockfd = -1;
2679 int seq, l, pid, rtm_addrs, i;
6fbf66fa
JY
2680 struct sockaddr so_dst, so_mask;
2681 char *cp = m_rtmsg.m_space;
6a8ea970 2682 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
6fbf66fa
JY
2683 struct rt_msghdr *rtm_aux;
2684
7fb0e07e 2685# define rtm m_rtmsg.m_rtm
6fbf66fa 2686
7fb0e07e 2687 CLEAR(*rgi);
6fbf66fa 2688
7fb0e07e 2689 /* setup data to send to routing socket */
6fbf66fa
JY
2690 pid = getpid();
2691 seq = 0;
6a8ea970 2692 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
6fbf66fa 2693
6a8ea970 2694 bzero(&m_rtmsg, sizeof(m_rtmsg));
6fbf66fa
JY
2695 bzero(&so_dst, sizeof(so_dst));
2696 bzero(&so_mask, sizeof(so_mask));
2697 bzero(&rtm, sizeof(struct rt_msghdr));
2698
2699 rtm.rtm_type = RTM_GET;
2700 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
2701 rtm.rtm_version = RTM_VERSION;
2702 rtm.rtm_seq = ++seq;
2703 rtm.rtm_addrs = rtm_addrs;
2704
2705 so_dst.sa_family = AF_INET;
2706 so_dst.sa_len = sizeof(struct sockaddr_in);
2707 so_mask.sa_family = AF_INET;
2708 so_mask.sa_len = sizeof(struct sockaddr_in);
2709
2710 NEXTADDR(RTA_DST, so_dst);
2711 NEXTADDR(RTA_NETMASK, so_mask);
2712
2713 rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
2714
7fb0e07e
JY
2715 /* transact with routing socket */
2716 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
2717 if (sockfd < 0)
6fbf66fa 2718 {
7fb0e07e
JY
2719 msg (M_WARN, "GDG: socket #1 failed");
2720 goto done;
2721 }
2722 if (write(sockfd, (char *)&m_rtmsg, l) < 0)
2723 {
2724 msg (M_WARN, "GDG: problem writing to routing socket");
2725 goto done;
6fbf66fa 2726 }
6fbf66fa 2727 do {
7fb0e07e 2728 l = read(sockfd, (char *)&m_rtmsg, sizeof(m_rtmsg));
6fbf66fa 2729 } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
7fb0e07e
JY
2730 close(sockfd);
2731 sockfd = -1;
6fbf66fa 2732
7fb0e07e 2733 /* extract return data from routing socket */
6fbf66fa 2734 rtm_aux = &rtm;
6fbf66fa 2735 cp = ((char *)(rtm_aux + 1));
7fb0e07e
JY
2736 if (rtm_aux->rtm_addrs)
2737 {
2738 for (i = 1; i; i <<= 1)
2739 {
2740 if (i & rtm_aux->rtm_addrs)
2741 {
2742 sa = (struct sockaddr *)cp;
2743 if (i == RTA_GATEWAY )
2744 gate = sa;
2745 else if (i == RTA_IFP)
2746 ifp = sa;
2747 ADVANCE(cp, sa);
2748 }
2749 }
2750 }
6fbf66fa 2751 else
7fb0e07e
JY
2752 goto done;
2753
2754 /* get gateway addr and interface name */
2755 if (gate != NULL )
6fbf66fa 2756 {
7fb0e07e
JY
2757 /* get default gateway addr */
2758 rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
2759 if (rgi->gateway.addr)
2760 rgi->flags |= RGI_ADDR_DEFINED;
2761
2762 if (ifp)
2763 {
2764 /* get interface name */
2765 const struct sockaddr_dl *adl = (struct sockaddr_dl *) ifp;
7fb0e07e
JY
2766 if (adl->sdl_nlen && adl->sdl_nlen < sizeof(rgi->iface))
2767 {
2768 memcpy (rgi->iface, adl->sdl_data, adl->sdl_nlen);
2769 rgi->iface[adl->sdl_nlen] = '\0';
2770 rgi->flags |= RGI_IFACE_DEFINED;
2771 }
2772 }
6fbf66fa
JY
2773 }
2774
7fb0e07e
JY
2775 /* get netmask of interface that owns default gateway */
2776 if (rgi->flags & RGI_IFACE_DEFINED) {
2777 struct ifreq ifr;
6fbf66fa 2778
7fb0e07e
JY
2779 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2780 if (sockfd < 0)
2781 {
2782 msg (M_WARN, "GDG: socket #2 failed");
2783 goto done;
2784 }
2785
2786 CLEAR(ifr);
2787 ifr.ifr_addr.sa_family = AF_INET;
2788 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
2789
2790 if (ioctl(sockfd, SIOCGIFNETMASK, (char *)&ifr) < 0)
2791 {
2792 msg (M_WARN, "GDG: ioctl #1 failed");
2793 goto done;
2794 }
2795 close(sockfd);
2796 sockfd = -1;
2797
2798 rgi->gateway.netmask = ntohl(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
2799 rgi->flags |= RGI_NETMASK_DEFINED;
2800 }
2801
2802 /* try to read MAC addr associated with interface that owns default gateway */
2803 if (rgi->flags & RGI_IFACE_DEFINED)
6fbf66fa 2804 {
7fb0e07e
JY
2805 struct ifconf ifc;
2806 struct ifreq *ifr;
2807 const int bufsize = 4096;
2808 char *buffer;
6fbf66fa 2809
7fb0e07e
JY
2810 buffer = (char *) gc_malloc (bufsize, true, &gc);
2811 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2812 if (sockfd < 0)
f77c60d3 2813 {
7fb0e07e
JY
2814 msg (M_WARN, "GDG: socket #3 failed");
2815 goto done;
f77c60d3
JY
2816 }
2817
7fb0e07e
JY
2818 ifc.ifc_len = bufsize;
2819 ifc.ifc_buf = buffer;
2820
2821 if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0)
6a8ea970 2822 {
7fb0e07e
JY
2823 msg (M_WARN, "GDG: ioctl #2 failed");
2824 goto done;
6a8ea970 2825 }
7fb0e07e
JY
2826 close(sockfd);
2827 sockfd = -1;
6a8ea970 2828
7fb0e07e
JY
2829 for (cp = buffer; cp <= buffer + ifc.ifc_len - sizeof(struct ifreq); )
2830 {
2831 ifr = (struct ifreq *)cp;
2832 const size_t len = sizeof(ifr->ifr_name) + max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);
2833 if (!ifr->ifr_addr.sa_family)
2834 break;
2835 if (!strncmp(ifr->ifr_name, rgi->iface, IFNAMSIZ))
2836 {
2837 if (ifr->ifr_addr.sa_family == AF_LINK)
2838 {
2839 struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
2840 memcpy(rgi->hwaddr, LLADDR(sdl), 6);
2841 rgi->flags |= RGI_HWADDR_DEFINED;
2842 }
2843 }
2844 cp += len;
2845 }
6fbf66fa 2846 }
6fbf66fa 2847
7fb0e07e
JY
2848 done:
2849 if (sockfd >= 0)
2850 close(sockfd);
2851 gc_free (&gc);
6a8ea970
JY
2852}
2853
7fb0e07e
JY
2854#undef max
2855
6fbf66fa
JY
2856#else
2857
7fb0e07e
JY
2858/*
2859 * This is a platform-specific method that returns data about
2860 * the current default gateway. Return data is placed into
2861 * a struct route_gateway_info object provided by caller. The
2862 * implementation should CLEAR the structure before adding
2863 * data to it.
2864 *
2865 * Data returned includes:
2866 * 1. default gateway address (rgi->gateway.addr)
2867 * 2. netmask of interface that owns default gateway
2868 * (rgi->gateway.netmask)
2869 * 3. hardware address (i.e. MAC address) of interface that owns
2870 * default gateway (rgi->hwaddr)
2871 * 4. interface name (or adapter index on Windows) that owns default
2872 * gateway (rgi->iface or rgi->adapter_index)
2873 * 5. an array of additional address/netmask pairs defined by
2874 * interface that owns default gateway (rgi->addrs with length
2875 * given in rgi->n_addrs)
2876 *
2877 * The flags RGI_x_DEFINED may be used to indicate which of the data
2878 * members were successfully returned (set in rgi->flags). All of
2879 * the data members are optional, however certain OpenVPN functionality
2880 * may be disabled by missing items.
2881 */
2882void
2883get_default_gateway (struct route_gateway_info *rgi)
6fbf66fa 2884{
7fb0e07e 2885 CLEAR(*rgi);
6fbf66fa
JY
2886}
2887
2888#endif
2889
2890bool
2891netmask_to_netbits (const in_addr_t network, const in_addr_t netmask, int *netbits)
2892{
2893 int i;
2894 const int addrlen = sizeof (in_addr_t) * 8;
2895
2896 if ((network & netmask) == network)
2897 {
2898 for (i = 0; i <= addrlen; ++i)
2899 {
2900 in_addr_t mask = netbits_to_netmask (i);
2901 if (mask == netmask)
2902 {
2903 if (i == addrlen)
2904 *netbits = -1;
2905 else
2906 *netbits = i;
2907 return true;
2908 }
2909 }
2910 }
2911 return false;
2912}
3c7f2f55 2913
b4b92ae5
GD
2914/* similar to netmask_to_netbits(), but don't mess with base address
2915 * etc., just convert to netbits - non-mappable masks are returned as "-1"
2916 */
2917int netmask_to_netbits2 (in_addr_t netmask)
2918{
2919 int i;
2920 const int addrlen = sizeof (in_addr_t) * 8;
2921
2922 for (i = 0; i <= addrlen; ++i)
2923 {
2924 in_addr_t mask = netbits_to_netmask (i);
2925 if (mask == netmask)
2926 {
2927 return i;
2928 }
2929 }
2930 return -1;
2931}
2932
2933
3c7f2f55
JY
2934/*
2935 * get_bypass_addresses() is used by the redirect-gateway bypass-x
2936 * functions to build a route bypass to selected DHCP/DNS servers,
2937 * so that outgoing packets to these servers don't end up in the tunnel.
2938 */
2939
2940#if defined(WIN32)
2941
2942static void
775a6ac2 2943add_host_route_if_nonlocal (struct route_bypass *rb, const in_addr_t addr)
3c7f2f55 2944{
32e576d2 2945 if (test_local_addr(addr, NULL) == TLA_NONLOCAL && addr != 0 && addr != IPV4_NETMASK_HOST)
d02a86d3 2946 add_bypass_address (rb, addr);
3c7f2f55
JY
2947}
2948
2949static void
775a6ac2 2950add_host_route_array (struct route_bypass *rb, const IP_ADDR_STRING *iplist)
3c7f2f55
JY
2951{
2952 while (iplist)
2953 {
2954 bool succeed = false;
2955 const in_addr_t ip = getaddr (GETADDR_HOST_ORDER, iplist->IpAddress.String, 0, &succeed, NULL);
2956 if (succeed)
2957 {
775a6ac2 2958 add_host_route_if_nonlocal (rb, ip);
3c7f2f55
JY
2959 }
2960 iplist = iplist->Next;
2961 }
2962}
2963
2964static void
2965get_bypass_addresses (struct route_bypass *rb, const unsigned int flags)
2966{
2967 struct gc_arena gc = gc_new ();
c373382c 2968 /*bool ret_bool = false;*/
3c7f2f55
JY
2969
2970 /* get full routing table */
2971 const MIB_IPFORWARDTABLE *routes = get_windows_routing_table (&gc);
2972
2973 /* get the route which represents the default gateway */
2974 const MIB_IPFORWARDROW *row = get_default_gateway_row (routes);
2975
2976 if (row)
2977 {
2978 /* get the adapter which the default gateway is associated with */
2979 const IP_ADAPTER_INFO *dgi = get_adapter_info (row->dwForwardIfIndex, &gc);
2980
2981 /* get extra adapter info, such as DNS addresses */
2982 const IP_PER_ADAPTER_INFO *pai = get_per_adapter_info (row->dwForwardIfIndex, &gc);
2983
2984 /* Bypass DHCP server address */
2985 if ((flags & RG_BYPASS_DHCP) && dgi && dgi->DhcpEnabled)
775a6ac2 2986 add_host_route_array (rb, &dgi->DhcpServer);
3c7f2f55
JY
2987
2988 /* Bypass DNS server addresses */
2989 if ((flags & RG_BYPASS_DNS) && pai)
775a6ac2 2990 add_host_route_array (rb, &pai->DnsServerList);
3c7f2f55
JY
2991 }
2992
2993 gc_free (&gc);
2994}
2995
2996#else
2997
2998static void
c705be2a 2999get_bypass_addresses (struct route_bypass *rb, const unsigned int flags) /* PLATFORM-SPECIFIC */
3c7f2f55
JY
3000{
3001}
3002
3003#endif
5f31881e 3004
775a6ac2
JY
3005/*
3006 * Test if addr is reachable via a local interface (return ILA_LOCAL),
3007 * or if it needs to be routed via the default gateway (return
3008 * ILA_NONLOCAL). If the target platform doesn't implement this
3009 * function, return ILA_NOT_IMPLEMENTED.
3010 *
3011 * Used by redirect-gateway autolocal feature
3012 */
3013
3014#if defined(WIN32)
3015
3016int
7fb0e07e 3017test_local_addr (const in_addr_t addr, const struct route_gateway_info *rgi)
775a6ac2
JY
3018{
3019 struct gc_arena gc = gc_new ();
3020 const in_addr_t nonlocal_netmask = 0x80000000L; /* routes with netmask <= to this are considered non-local */
3021 bool ret = TLA_NONLOCAL;
3022
3023 /* get full routing table */
3024 const MIB_IPFORWARDTABLE *rt = get_windows_routing_table (&gc);
3025 if (rt)
3026 {
3027 int i;
3028 for (i = 0; i < rt->dwNumEntries; ++i)
3029 {
3030 const MIB_IPFORWARDROW *row = &rt->table[i];
3031 const in_addr_t net = ntohl (row->dwForwardDest);
3032 const in_addr_t mask = ntohl (row->dwForwardMask);
3033 if (mask > nonlocal_netmask && (addr & mask) == net)
3034 {
3035 ret = TLA_LOCAL;
3036 break;
3037 }
3038 }
3039 }
3040
3041 gc_free (&gc);
3042 return ret;
3043}
3044
3045#else
3046
775a6ac2 3047int
7fb0e07e 3048test_local_addr (const in_addr_t addr, const struct route_gateway_info *rgi) /* PLATFORM-SPECIFIC */
775a6ac2 3049{
7fb0e07e
JY
3050 if (rgi)
3051 {
3052 if (local_route (addr, 0xFFFFFFFF, rgi->gateway.addr, rgi))
3053 return TLA_LOCAL;
3054 else
3055 return TLA_NONLOCAL;
3056 }
775a6ac2
JY
3057 return TLA_NOT_IMPLEMENTED;
3058}
3059
3060#endif