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