OpenVPN: update to 2.3.5
[tomato/davidwu.git] / release / src / router / openvpn / src / openvpn / route.c
blobcc85e4d85232d42c311d4e8fb3e995ad68aef177
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.
8 * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
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.
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.
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
26 * Support routines for adding/deleting network routes.
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #elif defined(_MSC_VER)
32 #include "config-msvc.h"
33 #endif
35 #include "syshead.h"
37 #include "common.h"
38 #include "error.h"
39 #include "route.h"
40 #include "misc.h"
41 #include "socket.h"
42 #include "manage.h"
43 #include "win32.h"
44 #include "options.h"
46 #include "memdbg.h"
48 #ifdef WIN32
49 #define METRIC_NOT_USED ((DWORD)-1)
50 #endif
52 static 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);
54 static void get_bypass_addresses (struct route_bypass *rb, const unsigned int flags);
56 #ifdef ENABLE_DEBUG
58 static void
59 print_bypass_addresses (const struct route_bypass *rb)
61 struct gc_arena gc = gc_new ();
62 int i;
63 for (i = 0; i < rb->n_bypass; ++i)
65 msg (D_ROUTE, "ROUTE: bypass_host_route[%d]=%s",
67 print_in_addr_t (rb->bypass[i], 0, &gc));
69 gc_free (&gc);
72 #endif
74 static bool
75 add_bypass_address (struct route_bypass *rb, const in_addr_t a)
77 int i;
78 for (i = 0; i < rb->n_bypass; ++i)
80 if (a == rb->bypass[i]) /* avoid duplicates */
81 return true;
83 if (rb->n_bypass < N_ROUTE_BYPASS)
85 rb->bypass[rb->n_bypass++] = a;
86 return true;
88 else
90 return false;
94 struct route_option_list *
95 new_route_option_list (const int max_routes, struct gc_arena *a)
97 struct route_option_list *ret;
98 ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_option_list, struct route_option, max_routes, a);
99 ret->capacity = max_routes;
100 return ret;
103 struct route_ipv6_option_list *
104 new_route_ipv6_option_list (const int max_routes, struct gc_arena *a)
106 struct route_ipv6_option_list *ret;
107 ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_ipv6_option_list, struct route_ipv6_option, max_routes, a);
108 ret->capacity = max_routes;
109 return ret;
112 struct route_option_list *
113 clone_route_option_list (const struct route_option_list *src, struct gc_arena *a)
115 const size_t rl_size = array_mult_safe (sizeof(struct route_option), src->capacity, sizeof(struct route_option_list));
116 struct route_option_list *ret = gc_malloc (rl_size, false, a);
117 memcpy (ret, src, rl_size);
118 return ret;
121 struct route_ipv6_option_list *
122 clone_route_ipv6_option_list (const struct route_ipv6_option_list *src, struct gc_arena *a)
124 const size_t rl_size = array_mult_safe (sizeof(struct route_ipv6_option), src->capacity, sizeof(struct route_ipv6_option_list));
125 struct route_ipv6_option_list *ret = gc_malloc (rl_size, false, a);
126 memcpy (ret, src, rl_size);
127 return ret;
130 void
131 copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src)
133 const size_t src_size = array_mult_safe (sizeof(struct route_option), src->capacity, sizeof(struct route_option_list));
134 if (src->capacity > dest->capacity)
135 msg (M_FATAL, PACKAGE_NAME " ROUTE: (copy) number of route options in src (%d) is greater than route list capacity in dest (%d)", src->capacity, dest->capacity);
136 memcpy (dest, src, src_size);
139 void
140 copy_route_ipv6_option_list (struct route_ipv6_option_list *dest,
141 const struct route_ipv6_option_list *src)
143 const size_t src_size = array_mult_safe (sizeof(struct route_ipv6_option), src->capacity, sizeof(struct route_ipv6_option_list));
144 if (src->capacity > dest->capacity)
145 msg (M_FATAL, PACKAGE_NAME " ROUTE: (copy) number of route options in src (%d) is greater than route list capacity in dest (%d)", src->capacity, dest->capacity);
146 memcpy (dest, src, src_size);
149 struct route_list *
150 new_route_list (const int max_routes, struct gc_arena *a)
152 struct route_list *ret;
153 ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_list, struct route_ipv4, max_routes, a);
154 ret->capacity = max_routes;
155 return ret;
158 struct route_ipv6_list *
159 new_route_ipv6_list (const int max_routes, struct gc_arena *a)
161 struct route_ipv6_list *ret;
162 ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_ipv6_list, struct route_ipv6, max_routes, a);
163 ret->capacity = max_routes;
164 return ret;
167 static const char *
168 route_string (const struct route_ipv4 *r, struct gc_arena *gc)
170 struct buffer out = alloc_buf_gc (256, gc);
171 buf_printf (&out, "ROUTE network %s netmask %s gateway %s",
172 print_in_addr_t (r->network, 0, gc),
173 print_in_addr_t (r->netmask, 0, gc),
174 print_in_addr_t (r->gateway, 0, gc)
176 if (r->flags & RT_METRIC_DEFINED)
177 buf_printf (&out, " metric %d", r->metric);
178 return BSTR (&out);
181 static bool
182 is_route_parm_defined (const char *parm)
184 if (!parm)
185 return false;
186 if (!strcmp (parm, "default"))
187 return false;
188 return true;
191 static void
192 setenv_route_addr (struct env_set *es, const char *key, const in_addr_t addr, int i)
194 struct gc_arena gc = gc_new ();
195 struct buffer name = alloc_buf_gc (256, &gc);
196 if (i >= 0)
197 buf_printf (&name, "route_%s_%d", key, i);
198 else
199 buf_printf (&name, "route_%s", key);
200 setenv_str (es, BSTR (&name), print_in_addr_t (addr, 0, &gc));
201 gc_free (&gc);
204 static bool
205 get_special_addr (const struct route_list *rl,
206 const char *string,
207 in_addr_t *out,
208 bool *status)
210 if (status)
211 *status = true;
212 if (!strcmp (string, "vpn_gateway"))
214 if (rl)
216 if (rl->spec.flags & RTSA_REMOTE_ENDPOINT)
217 *out = rl->spec.remote_endpoint;
218 else
220 msg (M_INFO, PACKAGE_NAME " ROUTE: vpn_gateway undefined");
221 if (status)
222 *status = false;
225 return true;
227 else if (!strcmp (string, "net_gateway"))
229 if (rl)
231 if (rl->rgi.flags & RGI_ADDR_DEFINED)
232 *out = rl->rgi.gateway.addr;
233 else
235 msg (M_INFO, PACKAGE_NAME " ROUTE: net_gateway undefined -- unable to get default gateway from system");
236 if (status)
237 *status = false;
240 return true;
242 else if (!strcmp (string, "remote_host"))
244 if (rl)
246 if (rl->spec.flags & RTSA_REMOTE_HOST)
247 *out = rl->spec.remote_host;
248 else
250 msg (M_INFO, PACKAGE_NAME " ROUTE: remote_host undefined");
251 if (status)
252 *status = false;
255 return true;
257 return false;
260 bool
261 is_special_addr (const char *addr_str)
263 if (addr_str)
264 return get_special_addr (NULL, addr_str, NULL, NULL);
265 else
266 return false;
269 static bool
270 init_route (struct route_ipv4 *r,
271 struct addrinfo **network_list,
272 const struct route_option *ro,
273 const struct route_list *rl)
275 const in_addr_t default_netmask = IPV4_NETMASK_HOST;
276 bool status;
277 int ret;
278 struct in_addr special;
280 CLEAR (*r);
281 r->option = ro;
283 /* network */
285 if (!is_route_parm_defined (ro->network))
287 goto fail;
291 /* get_special_addr replaces specialaddr with a special ip addr
292 like gw. getaddrinfo is called to convert a a addrinfo struct */
294 if(get_special_addr (rl, ro->network, &special.s_addr, &status))
296 special.s_addr = htonl(special.s_addr);
297 ret = openvpn_getaddrinfo(0, inet_ntoa(special), 0, NULL,
298 AF_INET, network_list);
300 else
301 ret = openvpn_getaddrinfo(GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL,
302 ro->network, 0, NULL, AF_INET, network_list);
304 status = (ret == 0);
306 if (!status)
307 goto fail;
309 /* netmask */
311 if (is_route_parm_defined (ro->netmask))
313 r->netmask = getaddr (
314 GETADDR_HOST_ORDER
315 | GETADDR_WARN_ON_SIGNAL,
316 ro->netmask,
318 &status,
319 NULL);
320 if (!status)
321 goto fail;
323 else
324 r->netmask = default_netmask;
326 /* gateway */
328 if (is_route_parm_defined (ro->gateway))
330 if (!get_special_addr (rl, ro->gateway, &r->gateway, &status))
332 r->gateway = getaddr (
333 GETADDR_RESOLVE
334 | GETADDR_HOST_ORDER
335 | GETADDR_WARN_ON_SIGNAL,
336 ro->gateway,
338 &status,
339 NULL);
341 if (!status)
342 goto fail;
344 else
346 if (rl->spec.flags & RTSA_REMOTE_ENDPOINT)
347 r->gateway = rl->spec.remote_endpoint;
348 else
350 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");
351 goto fail;
355 /* metric */
357 r->metric = 0;
358 if (is_route_parm_defined (ro->metric))
360 r->metric = atoi (ro->metric);
361 if (r->metric < 0)
363 msg (M_WARN, PACKAGE_NAME " ROUTE: route metric for network %s (%s) must be >= 0",
364 ro->network,
365 ro->metric);
366 goto fail;
368 r->flags |= RT_METRIC_DEFINED;
370 else if (rl->spec.flags & RTSA_DEFAULT_METRIC)
372 r->metric = rl->spec.default_metric;
373 r->flags |= RT_METRIC_DEFINED;
376 r->flags |= RT_DEFINED;
378 return true;
380 fail:
381 msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve route for host/network: %s",
382 ro->network);
383 return false;
386 static bool
387 init_route_ipv6 (struct route_ipv6 *r6,
388 const struct route_ipv6_option *r6o,
389 const struct route_ipv6_list *rl6 )
391 r6->defined = false;
393 if ( !get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, NULL, M_WARN ))
394 goto fail;
396 /* gateway */
397 if (is_route_parm_defined (r6o->gateway))
399 if ( inet_pton( AF_INET6, r6o->gateway, &r6->gateway ) != 1 )
401 msg( M_WARN, PACKAGE_NAME "ROUTE6: cannot parse gateway spec '%s'", r6o->gateway );
404 else if (rl6->remote_endpoint_defined)
406 r6->gateway = rl6->remote_endpoint_ipv6;
408 else
410 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");
411 goto fail;
414 /* metric */
416 r6->metric_defined = false;
417 r6->metric = -1;
418 if (is_route_parm_defined (r6o->metric))
420 r6->metric = atoi (r6o->metric);
421 if (r6->metric < 0)
423 msg (M_WARN, PACKAGE_NAME " ROUTE: route metric for network %s (%s) must be >= 0",
424 r6o->prefix,
425 r6o->metric);
426 goto fail;
428 r6->metric_defined = true;
430 else if (rl6->default_metric_defined)
432 r6->metric = rl6->default_metric;
433 r6->metric_defined = true;
436 r6->defined = true;
438 return true;
440 fail:
441 msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve route for host/network: %s",
442 r6o->prefix);
443 r6->defined = false;
444 return false;
447 void
448 add_route_to_option_list (struct route_option_list *l,
449 const char *network,
450 const char *netmask,
451 const char *gateway,
452 const char *metric)
454 struct route_option *ro;
455 if (l->n >= l->capacity)
456 msg (M_FATAL, PACKAGE_NAME " ROUTE: cannot add more than %d routes -- please increase the max-routes option in the client configuration file",
457 l->capacity);
458 ro = &l->routes[l->n];
459 ro->network = network;
460 ro->netmask = netmask;
461 ro->gateway = gateway;
462 ro->metric = metric;
463 ++l->n;
466 void
467 add_route_ipv6_to_option_list (struct route_ipv6_option_list *l,
468 const char *prefix,
469 const char *gateway,
470 const char *metric)
472 struct route_ipv6_option *ro;
473 if (l->n >= l->capacity)
474 msg (M_FATAL, PACKAGE_NAME " ROUTE: cannot add more than %d IPv6 routes -- please increase the max-routes option in the client configuration file",
475 l->capacity);
476 ro = &l->routes_ipv6[l->n];
477 ro->prefix = prefix;
478 ro->gateway = gateway;
479 ro->metric = metric;
480 ++l->n;
483 void
484 clear_route_list (struct route_list *rl)
486 const int capacity = rl->capacity;
487 const size_t rl_size = array_mult_safe (sizeof(struct route_ipv4), capacity, sizeof(struct route_list));
488 memset(rl, 0, rl_size);
489 rl->capacity = capacity;
492 void
493 clear_route_ipv6_list (struct route_ipv6_list *rl6)
495 const int capacity = rl6->capacity;
496 const size_t rl6_size = array_mult_safe (sizeof(struct route_ipv6), capacity, sizeof(struct route_ipv6_list));
497 memset(rl6, 0, rl6_size);
498 rl6->capacity = capacity;
501 void
502 route_list_add_vpn_gateway (struct route_list *rl,
503 struct env_set *es,
504 const in_addr_t addr)
506 ASSERT(rl);
507 rl->spec.remote_endpoint = addr;
508 rl->spec.flags |= RTSA_REMOTE_ENDPOINT;
509 setenv_route_addr (es, "vpn_gateway", rl->spec.remote_endpoint, -1);
512 static void
513 add_block_local_item (struct route_list *rl,
514 const struct route_gateway_address *gateway,
515 in_addr_t target)
517 const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
518 if ((rl->rgi.flags & rgi_needed) == rgi_needed
519 && rl->rgi.gateway.netmask < 0xFFFFFFFF
520 && (rl->n)+2 <= rl->capacity)
522 struct route_ipv4 r;
523 unsigned int l2;
525 /* split a route into two smaller blocking routes, and direct them to target */
526 CLEAR(r);
527 r.flags = RT_DEFINED;
528 r.gateway = target;
529 r.network = gateway->addr & gateway->netmask;
530 l2 = ((~gateway->netmask)+1)>>1;
531 r.netmask = ~(l2-1);
532 rl->routes[rl->n++] = r;
533 r.network += l2;
534 rl->routes[rl->n++] = r;
538 static void
539 add_block_local (struct route_list *rl)
541 const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
542 if ((rl->flags & RG_BLOCK_LOCAL)
543 && (rl->rgi.flags & rgi_needed) == rgi_needed
544 && (rl->spec.flags & RTSA_REMOTE_ENDPOINT)
545 && rl->spec.remote_host_local != TLA_LOCAL)
547 size_t i;
549 /* add bypass for gateway addr */
550 add_bypass_address (&rl->spec.bypass, rl->rgi.gateway.addr);
552 /* block access to local subnet */
553 add_block_local_item (rl, &rl->rgi.gateway, rl->spec.remote_endpoint);
555 /* process additional subnets on gateway interface */
556 for (i = 0; i < rl->rgi.n_addrs; ++i)
558 const struct route_gateway_address *gwa = &rl->rgi.addrs[i];
559 /* omit the add/subnet in &rl->rgi which we processed above */
560 if (!((rl->rgi.gateway.addr & rl->rgi.gateway.netmask) == (gwa->addr & gwa->netmask)
561 && rl->rgi.gateway.netmask == gwa->netmask))
562 add_block_local_item (rl, gwa, rl->spec.remote_endpoint);
567 bool
568 init_route_list (struct route_list *rl,
569 const struct route_option_list *opt,
570 const char *remote_endpoint,
571 int default_metric,
572 in_addr_t remote_host,
573 struct env_set *es)
575 struct gc_arena gc = gc_new ();
576 bool ret = true;
578 clear_route_list (rl);
580 rl->flags = opt->flags;
582 if (remote_host)
584 rl->spec.remote_host = remote_host;
585 rl->spec.flags |= RTSA_REMOTE_HOST;
588 if (default_metric)
590 rl->spec.default_metric = default_metric;
591 rl->spec.flags |= RTSA_DEFAULT_METRIC;
594 get_default_gateway (&rl->rgi);
595 if (rl->rgi.flags & RGI_ADDR_DEFINED)
597 setenv_route_addr (es, "net_gateway", rl->rgi.gateway.addr, -1);
598 #if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL)
599 print_default_gateway (D_ROUTE, &rl->rgi);
600 #endif
602 else
604 dmsg (D_ROUTE, "ROUTE: default_gateway=UNDEF");
607 if (rl->spec.flags & RTSA_REMOTE_HOST)
608 rl->spec.remote_host_local = test_local_addr (remote_host, &rl->rgi);
610 if (is_route_parm_defined (remote_endpoint))
612 bool defined = false;
613 rl->spec.remote_endpoint = getaddr (
614 GETADDR_RESOLVE
615 | GETADDR_HOST_ORDER
616 | GETADDR_WARN_ON_SIGNAL,
617 remote_endpoint,
619 &defined,
620 NULL);
622 if (defined)
624 setenv_route_addr (es, "vpn_gateway", rl->spec.remote_endpoint, -1);
625 rl->spec.flags |= RTSA_REMOTE_ENDPOINT;
627 else
629 msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve default gateway: %s",
630 remote_endpoint);
631 ret = false;
635 if (rl->flags & RG_ENABLE)
637 add_block_local (rl);
638 get_bypass_addresses (&rl->spec.bypass, rl->flags);
639 #ifdef ENABLE_DEBUG
640 print_bypass_addresses (&rl->spec.bypass);
641 #endif
644 /* parse the routes from opt to rl */
646 int i = 0;
647 int j = rl->n;
648 bool warned = false;
649 for (i = 0; i < opt->n; ++i)
651 struct addrinfo* netlist;
652 struct route_ipv4 r;
654 if (!init_route (&r,
655 &netlist,
656 &opt->routes[i],
657 rl))
658 ret = false;
659 else
661 struct addrinfo* curele;
662 for (curele = netlist; curele; curele = curele->ai_next)
664 if (j < rl->capacity)
666 r.network = ntohl(((struct sockaddr_in*)(curele)->ai_addr)->sin_addr.s_addr);
667 rl->routes[j++] = r;
669 else
671 if (!warned)
673 msg (M_WARN, PACKAGE_NAME " ROUTE: routes dropped because number of expanded routes is greater than route list capacity (%d)", rl->capacity);
674 warned = true;
678 freeaddrinfo(netlist);
681 rl->n = j;
684 gc_free (&gc);
685 return ret;
688 bool
689 init_route_ipv6_list (struct route_ipv6_list *rl6,
690 const struct route_ipv6_option_list *opt6,
691 const char *remote_endpoint,
692 int default_metric,
693 struct env_set *es)
695 struct gc_arena gc = gc_new ();
696 bool ret = true;
698 clear_route_ipv6_list (rl6);
700 rl6->flags = opt6->flags;
702 if (default_metric >= 0 )
704 rl6->default_metric = default_metric;
705 rl6->default_metric_defined = true;
708 /* "default_gateway" is stuff for "redirect-gateway", which we don't
709 * do for IPv6 yet -> TODO
712 dmsg (D_ROUTE, "ROUTE6: default_gateway=UNDEF");
715 if ( is_route_parm_defined( remote_endpoint ))
717 if ( inet_pton( AF_INET6, remote_endpoint,
718 &rl6->remote_endpoint_ipv6) == 1 )
720 rl6->remote_endpoint_defined = true;
722 else
724 msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve default gateway: %s", remote_endpoint);
725 ret = false;
728 else
729 rl6->remote_endpoint_defined = false;
732 if (!(opt6->n >= 0 && opt6->n <= rl6->capacity))
733 msg (M_FATAL, PACKAGE_NAME " ROUTE6: (init) number of route options (%d) is greater than route list capacity (%d)", opt6->n, rl6->capacity);
735 /* parse the routes from opt to rl6 */
737 int i, j = 0;
738 for (i = 0; i < opt6->n; ++i)
740 if (!init_route_ipv6 (&rl6->routes_ipv6[j],
741 &opt6->routes_ipv6[i],
742 rl6 ))
743 ret = false;
744 else
745 ++j;
747 rl6->n = j;
750 gc_free (&gc);
751 return ret;
754 static void
755 add_route3 (in_addr_t network,
756 in_addr_t netmask,
757 in_addr_t gateway,
758 const struct tuntap *tt,
759 unsigned int flags,
760 const struct route_gateway_info *rgi,
761 const struct env_set *es)
763 struct route_ipv4 r;
764 CLEAR (r);
765 r.flags = RT_DEFINED;
766 r.network = network;
767 r.netmask = netmask;
768 r.gateway = gateway;
769 add_route (&r, tt, flags, rgi, es);
772 static void
773 del_route3 (in_addr_t network,
774 in_addr_t netmask,
775 in_addr_t gateway,
776 const struct tuntap *tt,
777 unsigned int flags,
778 const struct route_gateway_info *rgi,
779 const struct env_set *es)
781 struct route_ipv4 r;
782 CLEAR (r);
783 r.flags = RT_DEFINED|RT_ADDED;
784 r.network = network;
785 r.netmask = netmask;
786 r.gateway = gateway;
787 delete_route (&r, tt, flags, rgi, es);
790 static void
791 add_bypass_routes (struct route_bypass *rb,
792 in_addr_t gateway,
793 const struct tuntap *tt,
794 unsigned int flags,
795 const struct route_gateway_info *rgi,
796 const struct env_set *es)
798 int i;
799 for (i = 0; i < rb->n_bypass; ++i)
801 if (rb->bypass[i])
802 add_route3 (rb->bypass[i],
803 IPV4_NETMASK_HOST,
804 gateway,
806 flags | ROUTE_REF_GW,
807 rgi,
808 es);
812 static void
813 del_bypass_routes (struct route_bypass *rb,
814 in_addr_t gateway,
815 const struct tuntap *tt,
816 unsigned int flags,
817 const struct route_gateway_info *rgi,
818 const struct env_set *es)
820 int i;
821 for (i = 0; i < rb->n_bypass; ++i)
823 if (rb->bypass[i])
824 del_route3 (rb->bypass[i],
825 IPV4_NETMASK_HOST,
826 gateway,
828 flags | ROUTE_REF_GW,
829 rgi,
830 es);
834 static void
835 redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
837 const char err[] = "NOTE: unable to redirect default gateway --";
839 if ( rl && rl->flags & RG_ENABLE )
841 if (!(rl->spec.flags & RTSA_REMOTE_ENDPOINT))
843 msg (M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
845 else if (!(rl->rgi.flags & RGI_ADDR_DEFINED))
847 msg (M_WARN, "%s Cannot read current default gateway from system", err);
849 else if (!(rl->spec.flags & RTSA_REMOTE_HOST))
851 msg (M_WARN, "%s Cannot obtain current remote host address", err);
853 else
855 bool local = BOOL_CAST(rl->flags & RG_LOCAL);
856 if (rl->flags & RG_AUTO_LOCAL) {
857 const int tla = rl->spec.remote_host_local;
858 if (tla == TLA_NONLOCAL)
860 dmsg (D_ROUTE, "ROUTE remote_host is NOT LOCAL");
861 local = false;
863 else if (tla == TLA_LOCAL)
865 dmsg (D_ROUTE, "ROUTE remote_host is LOCAL");
866 local = true;
869 if (!local)
871 /* route remote host to original default gateway */
872 /* if remote_host is not ipv4 (ie: ipv6), just skip
873 * adding this special /32 route */
874 if (rl->spec.remote_host != IPV4_INVALID_ADDR) {
875 add_route3 (rl->spec.remote_host,
876 IPV4_NETMASK_HOST,
877 rl->rgi.gateway.addr,
879 flags | ROUTE_REF_GW,
880 &rl->rgi,
881 es);
882 rl->iflags |= RL_DID_LOCAL;
883 } else {
884 dmsg (D_ROUTE, "ROUTE remote_host protocol differs from tunneled");
888 /* route DHCP/DNS server traffic through original default gateway */
889 add_bypass_routes (&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags, &rl->rgi, es);
891 if (rl->flags & RG_REROUTE_GW)
893 if (rl->flags & RG_DEF1)
895 /* add new default route (1st component) */
896 add_route3 (0x00000000,
897 0x80000000,
898 rl->spec.remote_endpoint,
900 flags,
901 &rl->rgi,
902 es);
904 /* add new default route (2nd component) */
905 add_route3 (0x80000000,
906 0x80000000,
907 rl->spec.remote_endpoint,
909 flags,
910 &rl->rgi,
911 es);
913 else
915 /* delete default route */
916 del_route3 (0,
918 rl->rgi.gateway.addr,
920 flags | ROUTE_REF_GW,
921 &rl->rgi,
922 es);
924 /* add new default route */
925 add_route3 (0,
927 rl->spec.remote_endpoint,
929 flags,
930 &rl->rgi,
931 es);
935 /* set a flag so we can undo later */
936 rl->iflags |= RL_DID_REDIRECT_DEFAULT_GATEWAY;
941 static void
942 undo_redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
944 if ( rl && rl->iflags & RL_DID_REDIRECT_DEFAULT_GATEWAY )
946 /* delete remote host route */
947 if (rl->iflags & RL_DID_LOCAL)
949 del_route3 (rl->spec.remote_host,
950 IPV4_NETMASK_HOST,
951 rl->rgi.gateway.addr,
953 flags | ROUTE_REF_GW,
954 &rl->rgi,
955 es);
956 rl->iflags &= ~RL_DID_LOCAL;
959 /* delete special DHCP/DNS bypass route */
960 del_bypass_routes (&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags, &rl->rgi, es);
962 if (rl->flags & RG_REROUTE_GW)
964 if (rl->flags & RG_DEF1)
966 /* delete default route (1st component) */
967 del_route3 (0x00000000,
968 0x80000000,
969 rl->spec.remote_endpoint,
971 flags,
972 &rl->rgi,
973 es);
975 /* delete default route (2nd component) */
976 del_route3 (0x80000000,
977 0x80000000,
978 rl->spec.remote_endpoint,
980 flags,
981 &rl->rgi,
982 es);
984 else
986 /* delete default route */
987 del_route3 (0,
989 rl->spec.remote_endpoint,
991 flags,
992 &rl->rgi,
993 es);
995 /* restore original default route */
996 add_route3 (0,
998 rl->rgi.gateway.addr,
1000 flags | ROUTE_REF_GW,
1001 &rl->rgi,
1002 es);
1006 rl->iflags &= ~RL_DID_REDIRECT_DEFAULT_GATEWAY;
1010 void
1011 add_routes (struct route_list *rl, struct route_ipv6_list *rl6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
1013 redirect_default_route_to_vpn (rl, tt, flags, es);
1014 if ( rl && !(rl->iflags & RL_ROUTES_ADDED) )
1016 int i;
1018 #ifdef ENABLE_MANAGEMENT
1019 if (management && rl->n)
1021 management_set_state (management,
1022 OPENVPN_STATE_ADD_ROUTES,
1023 NULL,
1027 #endif
1029 for (i = 0; i < rl->n; ++i)
1031 struct route_ipv4 *r = &rl->routes[i];
1032 check_subnet_conflict (r->network, r->netmask, "route");
1033 if (flags & ROUTE_DELETE_FIRST)
1034 delete_route (r, tt, flags, &rl->rgi, es);
1035 add_route (r, tt, flags, &rl->rgi, es);
1037 rl->iflags |= RL_ROUTES_ADDED;
1039 if (rl6 && !rl6->routes_added)
1041 int i;
1043 for (i = 0; i < rl6->n; ++i)
1045 struct route_ipv6 *r = &rl6->routes_ipv6[i];
1046 if (flags & ROUTE_DELETE_FIRST)
1047 delete_route_ipv6 (r, tt, flags, es);
1048 add_route_ipv6 (r, tt, flags, es);
1050 rl6->routes_added = true;
1054 void
1055 delete_routes (struct route_list *rl, struct route_ipv6_list *rl6,
1056 const struct tuntap *tt, unsigned int flags, const struct env_set *es)
1058 if ( rl && rl->iflags & RL_ROUTES_ADDED )
1060 int i;
1061 for (i = rl->n - 1; i >= 0; --i)
1063 struct route_ipv4 * r = &rl->routes[i];
1064 delete_route (r, tt, flags, &rl->rgi, es);
1066 rl->iflags &= ~RL_ROUTES_ADDED;
1069 undo_redirect_default_route_to_vpn (rl, tt, flags, es);
1071 if ( rl )
1073 clear_route_list (rl);
1076 if ( rl6 && rl6->routes_added )
1078 int i;
1079 for (i = rl6->n - 1; i >= 0; --i)
1081 const struct route_ipv6 *r6 = &rl6->routes_ipv6[i];
1082 delete_route_ipv6 (r6, tt, flags, es);
1084 rl6->routes_added = false;
1087 if ( rl6 )
1089 clear_route_ipv6_list (rl6);
1093 #ifndef ENABLE_SMALL
1095 static const char *
1096 show_opt (const char *option)
1098 if (!option)
1099 return "nil";
1100 else
1101 return option;
1104 static void
1105 print_route_option (const struct route_option *ro, int level)
1107 msg (level, " route %s/%s/%s/%s",
1108 show_opt (ro->network),
1109 show_opt (ro->netmask),
1110 show_opt (ro->gateway),
1111 show_opt (ro->metric));
1114 void
1115 print_route_options (const struct route_option_list *rol,
1116 int level)
1118 int i;
1119 if (rol->flags & RG_ENABLE)
1120 msg (level, " [redirect_default_gateway local=%d]",
1121 (rol->flags & RG_LOCAL) != 0);
1122 for (i = 0; i < rol->n; ++i)
1123 print_route_option (&rol->routes[i], level);
1126 void
1127 print_default_gateway(const int msglevel, const struct route_gateway_info *rgi)
1129 struct gc_arena gc = gc_new ();
1130 if (rgi->flags & RGI_ADDR_DEFINED)
1132 struct buffer out = alloc_buf_gc (256, &gc);
1133 buf_printf (&out, "ROUTE_GATEWAY");
1134 if (rgi->flags & RGI_ON_LINK)
1135 buf_printf (&out, " ON_LINK");
1136 else
1137 buf_printf (&out, " %s", print_in_addr_t (rgi->gateway.addr, 0, &gc));
1138 if (rgi->flags & RGI_NETMASK_DEFINED)
1139 buf_printf (&out, "/%s", print_in_addr_t (rgi->gateway.netmask, 0, &gc));
1140 #ifdef WIN32
1141 if (rgi->flags & RGI_IFACE_DEFINED)
1142 buf_printf (&out, " I=%u", (unsigned int)rgi->adapter_index);
1143 #else
1144 if (rgi->flags & RGI_IFACE_DEFINED)
1145 buf_printf (&out, " IFACE=%s", rgi->iface);
1146 #endif
1147 if (rgi->flags & RGI_HWADDR_DEFINED)
1148 buf_printf (&out, " HWADDR=%s", format_hex_ex (rgi->hwaddr, 6, 0, 1, ":", &gc));
1149 msg (msglevel, "%s", BSTR (&out));
1151 gc_free (&gc);
1154 #endif
1156 static void
1157 print_route (const struct route_ipv4 *r, int level)
1159 struct gc_arena gc = gc_new ();
1160 if (r->flags & RT_DEFINED)
1161 msg (level, "%s", route_string (r, &gc));
1162 gc_free (&gc);
1165 void
1166 print_routes (const struct route_list *rl, int level)
1168 int i;
1169 for (i = 0; i < rl->n; ++i)
1170 print_route (&rl->routes[i], level);
1173 static void
1174 setenv_route (struct env_set *es, const struct route_ipv4 *r, int i)
1176 struct gc_arena gc = gc_new ();
1177 if (r->flags & RT_DEFINED)
1179 setenv_route_addr (es, "network", r->network, i);
1180 setenv_route_addr (es, "netmask", r->netmask, i);
1181 setenv_route_addr (es, "gateway", r->gateway, i);
1183 if (r->flags & RT_METRIC_DEFINED)
1185 struct buffer name = alloc_buf_gc (256, &gc);
1186 buf_printf (&name, "route_metric_%d", i);
1187 setenv_int (es, BSTR (&name), r->metric);
1190 gc_free (&gc);
1193 void
1194 setenv_routes (struct env_set *es, const struct route_list *rl)
1196 int i;
1197 for (i = 0; i < rl->n; ++i)
1198 setenv_route (es, &rl->routes[i], i + 1);
1201 static void
1202 setenv_route_ipv6 (struct env_set *es, const struct route_ipv6 *r6, int i)
1204 struct gc_arena gc = gc_new ();
1205 if (r6->defined)
1207 struct buffer name1 = alloc_buf_gc( 256, &gc );
1208 struct buffer val = alloc_buf_gc( 256, &gc );
1209 struct buffer name2 = alloc_buf_gc( 256, &gc );
1211 buf_printf( &name1, "route_ipv6_network_%d", i );
1212 buf_printf( &val, "%s/%d", print_in6_addr( r6->network, 0, &gc ),
1213 r6->netbits );
1214 setenv_str( es, BSTR(&name1), BSTR(&val) );
1216 buf_printf( &name2, "route_ipv6_gateway_%d", i );
1217 setenv_str( es, BSTR(&name2), print_in6_addr( r6->gateway, 0, &gc ));
1219 gc_free (&gc);
1221 void
1222 setenv_routes_ipv6 (struct env_set *es, const struct route_ipv6_list *rl6)
1224 int i;
1225 for (i = 0; i < rl6->n; ++i)
1226 setenv_route_ipv6 (es, &rl6->routes_ipv6[i], i + 1);
1230 * local_route() determines whether the gateway of a provided host
1231 * route is on the same interface that owns the default gateway.
1232 * It uses the data structure
1233 * returned by get_default_gateway() (struct route_gateway_info)
1234 * to determine this. If the route is local, LR_MATCH is returned.
1235 * When adding routes into the kernel, if LR_MATCH is defined for
1236 * a given route, the route should explicitly reference the default
1237 * gateway interface as the route destination. For example, here
1238 * is an example on Linux that uses LR_MATCH:
1240 * route add -net 10.10.0.1 netmask 255.255.255.255 dev eth0
1242 * This capability is needed by the "default-gateway block-local"
1243 * directive, to allow client access to the local subnet to be
1244 * blocked but still allow access to the local default gateway.
1247 /* local_route() return values */
1248 #define LR_NOMATCH 0 /* route is not local */
1249 #define LR_MATCH 1 /* route is local */
1250 #define LR_ERROR 2 /* caller should abort adding route */
1252 static int
1253 local_route (in_addr_t network,
1254 in_addr_t netmask,
1255 in_addr_t gateway,
1256 const struct route_gateway_info *rgi)
1258 /* set LR_MATCH on local host routes */
1259 const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED|RGI_IFACE_DEFINED);
1260 if (rgi
1261 && (rgi->flags & rgi_needed) == rgi_needed
1262 && gateway == rgi->gateway.addr
1263 && netmask == 0xFFFFFFFF)
1265 if (((network ^ rgi->gateway.addr) & rgi->gateway.netmask) == 0)
1266 return LR_MATCH;
1267 else
1269 /* examine additional subnets on gateway interface */
1270 size_t i;
1271 for (i = 0; i < rgi->n_addrs; ++i)
1273 const struct route_gateway_address *gwa = &rgi->addrs[i];
1274 if (((network ^ gwa->addr) & gwa->netmask) == 0)
1275 return LR_MATCH;
1279 return LR_NOMATCH;
1282 /* Return true if the "on-link" form of the route should be used. This is when the gateway for a
1283 a route is specified as an interface rather than an address. */
1284 static inline bool
1285 is_on_link (const int is_local_route, const unsigned int flags, const struct route_gateway_info *rgi)
1287 return rgi && (is_local_route == LR_MATCH || ((flags & ROUTE_REF_GW) && (rgi->flags & RGI_ON_LINK)));
1290 void
1291 add_route (struct route_ipv4 *r,
1292 const struct tuntap *tt,
1293 unsigned int flags,
1294 const struct route_gateway_info *rgi, /* may be NULL */
1295 const struct env_set *es)
1297 struct gc_arena gc;
1298 struct argv argv;
1299 const char *network;
1300 const char *netmask;
1301 const char *gateway;
1302 bool status = false;
1303 int is_local_route;
1305 if (!(r->flags & RT_DEFINED))
1306 return;
1308 gc_init (&gc);
1309 argv_init (&argv);
1311 network = print_in_addr_t (r->network, 0, &gc);
1312 netmask = print_in_addr_t (r->netmask, 0, &gc);
1313 gateway = print_in_addr_t (r->gateway, 0, &gc);
1315 is_local_route = local_route(r->network, r->netmask, r->gateway, rgi);
1316 if (is_local_route == LR_ERROR)
1317 goto done;
1319 #if defined(TARGET_LINUX)
1320 #ifdef ENABLE_IPROUTE
1321 argv_printf (&argv, "%s route add %s/%d",
1322 iproute_path,
1323 network,
1324 count_netmask_bits(netmask));
1326 if (r->flags & RT_METRIC_DEFINED)
1327 argv_printf_cat (&argv, "metric %d", r->metric);
1329 if (is_on_link (is_local_route, flags, rgi))
1330 argv_printf_cat (&argv, "dev %s", rgi->iface);
1331 else
1332 argv_printf_cat (&argv, "via %s", gateway);
1333 #else
1334 argv_printf (&argv, "%s add -net %s netmask %s",
1335 ROUTE_PATH,
1336 network,
1337 netmask);
1338 if (r->flags & RT_METRIC_DEFINED)
1339 argv_printf_cat (&argv, "metric %d", r->metric);
1340 if (is_on_link (is_local_route, flags, rgi))
1341 argv_printf_cat (&argv, "dev %s", rgi->iface);
1342 else
1343 argv_printf_cat (&argv, "gw %s", gateway);
1345 #endif /*ENABLE_IPROUTE*/
1346 argv_msg (D_ROUTE, &argv);
1347 status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route add command failed");
1349 #elif defined (WIN32)
1351 DWORD ai = TUN_ADAPTER_INDEX_INVALID;
1352 argv_printf (&argv, "%s%sc ADD %s MASK %s %s",
1353 get_win_sys_path(),
1354 WIN_ROUTE_PATH_SUFFIX,
1355 network,
1356 netmask,
1357 gateway);
1358 if (r->flags & RT_METRIC_DEFINED)
1359 argv_printf_cat (&argv, "METRIC %d", r->metric);
1360 if (is_on_link (is_local_route, flags, rgi))
1362 ai = rgi->adapter_index;
1363 argv_printf_cat (&argv, "IF %u", (unsigned int)ai);
1366 argv_msg (D_ROUTE, &argv);
1368 if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_IPAPI)
1370 status = add_route_ipapi (r, tt, ai);
1371 msg (D_ROUTE, "Route addition via IPAPI %s", status ? "succeeded" : "failed");
1373 else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_EXE)
1375 netcmd_semaphore_lock ();
1376 status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add command failed");
1377 netcmd_semaphore_release ();
1379 else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_ADAPTIVE)
1381 status = add_route_ipapi (r, tt, ai);
1382 msg (D_ROUTE, "Route addition via IPAPI %s [adaptive]", status ? "succeeded" : "failed");
1383 if (!status)
1385 msg (D_ROUTE, "Route addition fallback to route.exe");
1386 netcmd_semaphore_lock ();
1387 status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add command failed [adaptive]");
1388 netcmd_semaphore_release ();
1391 else
1393 ASSERT (0);
1397 #elif defined (TARGET_SOLARIS)
1399 /* example: route add 192.0.2.32 -netmask 255.255.255.224 somegateway */
1401 argv_printf (&argv, "%s add",
1402 ROUTE_PATH);
1404 argv_printf_cat (&argv, "%s -netmask %s %s",
1405 network,
1406 netmask,
1407 gateway);
1409 /* Solaris can only distinguish between "metric 0" == "on-link on the
1410 * interface where the IP address given is configured" and "metric > 0"
1411 * == "use gateway specified" (no finer-grained route metrics available)
1413 * More recent versions of Solaris can also do "-interface", but that
1414 * would break backwards compatibility with older versions for no gain.
1416 if (r->flags & RT_METRIC_DEFINED )
1417 argv_printf_cat (&argv, "%d", r->metric);
1419 argv_msg (D_ROUTE, &argv);
1420 status = openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route add command failed");
1422 #elif defined(TARGET_FREEBSD)
1424 argv_printf (&argv, "%s add",
1425 ROUTE_PATH);
1427 #if 0
1428 if (r->flags & RT_METRIC_DEFINED)
1429 argv_printf_cat (&argv, "-rtt %d", r->metric);
1430 #endif
1432 argv_printf_cat (&argv, "-net %s %s %s",
1433 network,
1434 gateway,
1435 netmask);
1437 /* FIXME -- add on-link support for FreeBSD */
1439 argv_msg (D_ROUTE, &argv);
1440 status = openvpn_execve_check (&argv, es, 0, "ERROR: FreeBSD route add command failed");
1442 #elif defined(TARGET_DRAGONFLY)
1444 argv_printf (&argv, "%s add",
1445 ROUTE_PATH);
1447 #if 0
1448 if (r->flags & RT_METRIC_DEFINED)
1449 argv_printf_cat (&argv, "-rtt %d", r->metric);
1450 #endif
1452 argv_printf_cat (&argv, "-net %s %s %s",
1453 network,
1454 gateway,
1455 netmask);
1457 /* FIXME -- add on-link support for Dragonfly */
1459 argv_msg (D_ROUTE, &argv);
1460 status = openvpn_execve_check (&argv, es, 0, "ERROR: DragonFly route add command failed");
1462 #elif defined(TARGET_DARWIN)
1464 argv_printf (&argv, "%s add",
1465 ROUTE_PATH);
1467 #if 0
1468 if (r->flags & RT_METRIC_DEFINED)
1469 argv_printf_cat (&argv, "-rtt %d", r->metric);
1470 #endif
1472 if (is_on_link (is_local_route, flags, rgi))
1474 /* Mac OS X route syntax for ON_LINK:
1475 route add -cloning -net 10.10.0.1 -netmask 255.255.255.255 -interface en0 */
1476 argv_printf_cat (&argv, "-cloning -net %s -netmask %s -interface %s",
1477 network,
1478 netmask,
1479 rgi->iface);
1481 else
1483 argv_printf_cat (&argv, "-net %s %s %s",
1484 network,
1485 gateway,
1486 netmask);
1489 argv_msg (D_ROUTE, &argv);
1490 status = openvpn_execve_check (&argv, es, 0, "ERROR: OS X route add command failed");
1492 #elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1494 argv_printf (&argv, "%s add",
1495 ROUTE_PATH);
1497 #if 0
1498 if (r->flags & RT_METRIC_DEFINED)
1499 argv_printf_cat (&argv, "-rtt %d", r->metric);
1500 #endif
1502 argv_printf_cat (&argv, "-net %s %s -netmask %s",
1503 network,
1504 gateway,
1505 netmask);
1507 /* FIXME -- add on-link support for OpenBSD/NetBSD */
1509 argv_msg (D_ROUTE, &argv);
1510 status = openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route add command failed");
1512 #else
1513 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");
1514 #endif
1516 done:
1517 if (status)
1518 r->flags |= RT_ADDED;
1519 else
1520 r->flags &= ~RT_ADDED;
1521 argv_reset (&argv);
1522 gc_free (&gc);
1526 static const char *
1527 print_in6_addr_netbits_only( struct in6_addr network_copy, int netbits,
1528 struct gc_arena * gc)
1530 /* clear host bit parts of route
1531 * (needed if routes are specified improperly, or if we need to
1532 * explicitely setup/clear the "connected" network routes on some OSes)
1534 int byte = 15;
1535 int bits_to_clear = 128 - netbits;
1537 while( byte >= 0 && bits_to_clear > 0 )
1539 if ( bits_to_clear >= 8 )
1540 { network_copy.s6_addr[byte--] = 0; bits_to_clear -= 8; }
1541 else
1542 { network_copy.s6_addr[byte--] &= (0xff << bits_to_clear); bits_to_clear = 0; }
1545 return print_in6_addr( network_copy, 0, gc);
1548 void
1549 add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
1551 struct gc_arena gc;
1552 struct argv argv;
1554 const char *network;
1555 const char *gateway;
1556 bool status = false;
1557 const char *device = tt->actual_name;
1559 bool gateway_needed = false;
1561 if (!r6->defined)
1562 return;
1564 gc_init (&gc);
1565 argv_init (&argv);
1567 network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
1568 gateway = print_in6_addr( r6->gateway, 0, &gc);
1570 if ( !tt->ipv6 )
1572 msg( M_INFO, "add_route_ipv6(): not adding %s/%d, no IPv6 on if %s",
1573 network, r6->netbits, device );
1574 return;
1577 msg( M_INFO, "add_route_ipv6(%s/%d -> %s metric %d) dev %s",
1578 network, r6->netbits, gateway, r6->metric, device );
1581 * Filter out routes which are essentially no-ops
1582 * (not currently done for IPv6)
1585 /* On "tun" interface, we never set a gateway if the operating system
1586 * can do "route to interface" - it does not add value, as the target
1587 * dev already fully qualifies the route destination on point-to-point
1588 * interfaces. OTOH, on "tap" interface, we must always set the
1589 * gateway unless the route is to be an on-link network
1591 if ( tt->type == DEV_TYPE_TAP &&
1592 !(r6->metric_defined && r6->metric == 0 ) )
1594 gateway_needed = true;
1597 #if defined(TARGET_LINUX)
1598 #ifdef ENABLE_IPROUTE
1599 argv_printf (&argv, "%s -6 route add %s/%d dev %s",
1600 iproute_path,
1601 network,
1602 r6->netbits,
1603 device);
1604 if (gateway_needed)
1605 argv_printf_cat (&argv, "via %s", gateway);
1606 if (r6->metric_defined && r6->metric > 0 )
1607 argv_printf_cat (&argv, " metric %d", r6->metric);
1609 #else
1610 argv_printf (&argv, "%s -A inet6 add %s/%d dev %s",
1611 ROUTE_PATH,
1612 network,
1613 r6->netbits,
1614 device);
1615 if (gateway_needed)
1616 argv_printf_cat (&argv, "gw %s", gateway);
1617 if (r6->metric_defined && r6->metric > 0 )
1618 argv_printf_cat (&argv, " metric %d", r6->metric);
1619 #endif /*ENABLE_IPROUTE*/
1620 argv_msg (D_ROUTE, &argv);
1621 status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 add command failed");
1623 #elif defined (WIN32)
1625 /* netsh interface ipv6 add route 2001:db8::/32 MyTunDevice */
1626 argv_printf (&argv, "%s%sc interface ipv6 add route %s/%d %s",
1627 get_win_sys_path(),
1628 NETSH_PATH_SUFFIX,
1629 network,
1630 r6->netbits,
1631 device);
1633 /* next-hop depends on TUN or TAP mode:
1634 * - in TAP mode, we use the "real" next-hop
1635 * - in TUN mode we use a special-case link-local address that the tapdrvr
1636 * knows about and will answer ND (neighbor discovery) packets for
1638 if ( tt->type == DEV_TYPE_TUN )
1639 argv_printf_cat( &argv, " %s", "fe80::8" );
1640 else
1641 argv_printf_cat( &argv, " %s", gateway );
1643 #if 0
1644 if (r->metric_defined)
1645 argv_printf_cat (&argv, " METRIC %d", r->metric);
1646 #endif
1648 /* in some versions of Windows, routes are persistent across reboots by
1649 * default, unless "store=active" is set (pointed out by Tony Lim, thanks)
1651 argv_printf_cat( &argv, " store=active" );
1653 argv_msg (D_ROUTE, &argv);
1655 netcmd_semaphore_lock ();
1656 status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add ipv6 command failed");
1657 netcmd_semaphore_release ();
1659 #elif defined (TARGET_SOLARIS)
1661 /* example: route add -inet6 2001:db8::/32 somegateway 0 */
1663 /* for some weird reason, this does not work for me unless I set
1664 * "metric 0" - otherwise, the routes will be nicely installed, but
1665 * packets will just disappear somewhere. So we use "0" now...
1668 argv_printf (&argv, "%s add -inet6 %s/%d %s 0",
1669 ROUTE_PATH,
1670 network,
1671 r6->netbits,
1672 gateway );
1674 argv_msg (D_ROUTE, &argv);
1675 status = openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route add -inet6 command failed");
1677 #elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
1679 argv_printf (&argv, "%s add -inet6 %s/%d",
1680 ROUTE_PATH,
1681 network,
1682 r6->netbits);
1684 if (gateway_needed)
1685 argv_printf_cat (&argv, "%s", gateway);
1686 else
1687 argv_printf_cat (&argv, "-iface %s", device);
1689 argv_msg (D_ROUTE, &argv);
1690 status = openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route add -inet6 command failed");
1692 #elif defined(TARGET_DARWIN)
1694 argv_printf (&argv, "%s add -inet6 %s -prefixlen %d",
1695 ROUTE_PATH,
1696 network, r6->netbits );
1698 if (gateway_needed)
1699 argv_printf_cat (&argv, "%s", gateway);
1700 else
1701 argv_printf_cat (&argv, "-iface %s", device);
1703 argv_msg (D_ROUTE, &argv);
1704 status = openvpn_execve_check (&argv, es, 0, "ERROR: MacOS X route add -inet6 command failed");
1706 #elif defined(TARGET_OPENBSD)
1708 argv_printf (&argv, "%s add -inet6 %s -prefixlen %d %s",
1709 ROUTE_PATH,
1710 network, r6->netbits, gateway );
1712 argv_msg (D_ROUTE, &argv);
1713 status = openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD route add -inet6 command failed");
1715 #elif defined(TARGET_NETBSD)
1717 argv_printf (&argv, "%s add -inet6 %s/%d %s",
1718 ROUTE_PATH,
1719 network, r6->netbits, gateway );
1721 argv_msg (D_ROUTE, &argv);
1722 status = openvpn_execve_check (&argv, es, 0, "ERROR: NetBSD route add -inet6 command failed");
1724 #else
1725 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");
1726 #endif
1728 r6->defined = status;
1729 argv_reset (&argv);
1730 gc_free (&gc);
1733 static void
1734 delete_route (struct route_ipv4 *r,
1735 const struct tuntap *tt,
1736 unsigned int flags,
1737 const struct route_gateway_info *rgi,
1738 const struct env_set *es)
1740 struct gc_arena gc;
1741 struct argv argv;
1742 const char *network;
1743 const char *netmask;
1744 const char *gateway;
1745 int is_local_route;
1747 if ((r->flags & (RT_DEFINED|RT_ADDED)) != (RT_DEFINED|RT_ADDED))
1748 return;
1750 gc_init (&gc);
1751 argv_init (&argv);
1753 network = print_in_addr_t (r->network, 0, &gc);
1754 netmask = print_in_addr_t (r->netmask, 0, &gc);
1755 gateway = print_in_addr_t (r->gateway, 0, &gc);
1757 is_local_route = local_route(r->network, r->netmask, r->gateway, rgi);
1758 if (is_local_route == LR_ERROR)
1759 goto done;
1761 #if defined(TARGET_LINUX)
1762 #ifdef ENABLE_IPROUTE
1763 argv_printf (&argv, "%s route del %s/%d",
1764 iproute_path,
1765 network,
1766 count_netmask_bits(netmask));
1767 #else
1768 argv_printf (&argv, "%s del -net %s netmask %s",
1769 ROUTE_PATH,
1770 network,
1771 netmask);
1772 #endif /*ENABLE_IPROUTE*/
1773 if (r->flags & RT_METRIC_DEFINED)
1774 argv_printf_cat (&argv, "metric %d", r->metric);
1775 argv_msg (D_ROUTE, &argv);
1776 openvpn_execve_check (&argv, es, 0, "ERROR: Linux route delete command failed");
1778 #elif defined (WIN32)
1780 argv_printf (&argv, "%s%sc DELETE %s MASK %s %s",
1781 get_win_sys_path(),
1782 WIN_ROUTE_PATH_SUFFIX,
1783 network,
1784 netmask,
1785 gateway);
1787 argv_msg (D_ROUTE, &argv);
1789 if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_IPAPI)
1791 const bool status = del_route_ipapi (r, tt);
1792 msg (D_ROUTE, "Route deletion via IPAPI %s", status ? "succeeded" : "failed");
1794 else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_EXE)
1796 netcmd_semaphore_lock ();
1797 openvpn_execve_check (&argv, es, 0, "ERROR: Windows route delete command failed");
1798 netcmd_semaphore_release ();
1800 else if ((flags & ROUTE_METHOD_MASK) == ROUTE_METHOD_ADAPTIVE)
1802 const bool status = del_route_ipapi (r, tt);
1803 msg (D_ROUTE, "Route deletion via IPAPI %s [adaptive]", status ? "succeeded" : "failed");
1804 if (!status)
1806 msg (D_ROUTE, "Route deletion fallback to route.exe");
1807 netcmd_semaphore_lock ();
1808 openvpn_execve_check (&argv, es, 0, "ERROR: Windows route delete command failed [adaptive]");
1809 netcmd_semaphore_release ();
1812 else
1814 ASSERT (0);
1817 #elif defined (TARGET_SOLARIS)
1819 argv_printf (&argv, "%s delete %s -netmask %s %s",
1820 ROUTE_PATH,
1821 network,
1822 netmask,
1823 gateway);
1825 argv_msg (D_ROUTE, &argv);
1826 openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route delete command failed");
1828 #elif defined(TARGET_FREEBSD)
1830 argv_printf (&argv, "%s delete -net %s %s %s",
1831 ROUTE_PATH,
1832 network,
1833 gateway,
1834 netmask);
1836 argv_msg (D_ROUTE, &argv);
1837 openvpn_execve_check (&argv, es, 0, "ERROR: FreeBSD route delete command failed");
1839 #elif defined(TARGET_DRAGONFLY)
1841 argv_printf (&argv, "%s delete -net %s %s %s",
1842 ROUTE_PATH,
1843 network,
1844 gateway,
1845 netmask);
1847 argv_msg (D_ROUTE, &argv);
1848 openvpn_execve_check (&argv, es, 0, "ERROR: DragonFly route delete command failed");
1850 #elif defined(TARGET_DARWIN)
1852 if (is_on_link (is_local_route, flags, rgi))
1854 argv_printf (&argv, "%s delete -cloning -net %s -netmask %s -interface %s",
1855 ROUTE_PATH,
1856 network,
1857 netmask,
1858 rgi->iface);
1860 else
1862 argv_printf (&argv, "%s delete -net %s %s %s",
1863 ROUTE_PATH,
1864 network,
1865 gateway,
1866 netmask);
1869 argv_msg (D_ROUTE, &argv);
1870 openvpn_execve_check (&argv, es, 0, "ERROR: OS X route delete command failed");
1872 #elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
1874 argv_printf (&argv, "%s delete -net %s %s -netmask %s",
1875 ROUTE_PATH,
1876 network,
1877 gateway,
1878 netmask);
1880 argv_msg (D_ROUTE, &argv);
1881 openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route delete command failed");
1883 #else
1884 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");
1885 #endif
1887 done:
1888 r->flags &= ~RT_ADDED;
1889 argv_reset (&argv);
1890 gc_free (&gc);
1893 void
1894 delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
1896 struct gc_arena gc;
1897 struct argv argv;
1898 const char *network;
1899 const char *gateway;
1900 const char *device = tt->actual_name;
1901 bool gateway_needed = false;
1903 if (!r6->defined)
1904 return;
1906 gc_init (&gc);
1907 argv_init (&argv);
1909 network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
1910 gateway = print_in6_addr( r6->gateway, 0, &gc);
1912 if ( !tt->ipv6 )
1914 msg( M_INFO, "delete_route_ipv6(): not deleting %s/%d, no IPv6 on if %s",
1915 network, r6->netbits, device );
1916 return;
1919 msg( M_INFO, "delete_route_ipv6(%s/%d)", network, r6->netbits );
1921 /* if we used a gateway on "add route", we also need to specify it on
1922 * delete, otherwise some OSes will refuse to delete the route
1924 if ( tt->type == DEV_TYPE_TAP &&
1925 !(r6->metric_defined && r6->metric == 0 ) )
1927 gateway_needed = true;
1931 #if defined(TARGET_LINUX)
1932 #ifdef ENABLE_IPROUTE
1933 argv_printf (&argv, "%s -6 route del %s/%d dev %s",
1934 iproute_path,
1935 network,
1936 r6->netbits,
1937 device);
1938 if (gateway_needed)
1939 argv_printf_cat (&argv, "via %s", gateway);
1940 #else
1941 argv_printf (&argv, "%s -A inet6 del %s/%d dev %s",
1942 ROUTE_PATH,
1943 network,
1944 r6->netbits,
1945 device);
1946 if (gateway_needed)
1947 argv_printf_cat (&argv, "gw %s", gateway);
1948 if (r6->metric_defined && r6->metric > 0 )
1949 argv_printf_cat (&argv, " metric %d", r6->metric);
1950 #endif /*ENABLE_IPROUTE*/
1951 argv_msg (D_ROUTE, &argv);
1952 openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 del command failed");
1954 #elif defined (WIN32)
1956 /* netsh interface ipv6 delete route 2001:db8::/32 MyTunDevice */
1957 argv_printf (&argv, "%s%sc interface ipv6 delete route %s/%d %s",
1958 get_win_sys_path(),
1959 NETSH_PATH_SUFFIX,
1960 network,
1961 r6->netbits,
1962 device);
1964 /* next-hop depends on TUN or TAP mode:
1965 * - in TAP mode, we use the "real" next-hop
1966 * - in TUN mode we use a special-case link-local address that the tapdrvr
1967 * knows about and will answer ND (neighbor discovery) packets for
1968 * (and "route deletion without specifying next-hop" does not work...)
1970 if ( tt->type == DEV_TYPE_TUN )
1971 argv_printf_cat( &argv, " %s", "fe80::8" );
1972 else
1973 argv_printf_cat( &argv, " %s", gateway );
1975 #if 0
1976 if (r->metric_defined)
1977 argv_printf_cat (&argv, "METRIC %d", r->metric);
1978 #endif
1980 /* Windows XP to 7 "just delete" routes, wherever they came from, but
1981 * in Windows 8(.1?), if you create them with "store=active", this is
1982 * how you should delete them as well (pointed out by Cedric Tabary)
1984 argv_printf_cat( &argv, " store=active" );
1986 argv_msg (D_ROUTE, &argv);
1988 netcmd_semaphore_lock ();
1989 openvpn_execve_check (&argv, es, 0, "ERROR: Windows route delete ipv6 command failed");
1990 netcmd_semaphore_release ();
1992 #elif defined (TARGET_SOLARIS)
1994 /* example: route delete -inet6 2001:db8::/32 somegateway */
1995 /* GERT-TODO: this is untested, but should work */
1997 argv_printf (&argv, "%s delete -inet6 %s/%d %s",
1998 ROUTE_PATH,
1999 network,
2000 r6->netbits,
2001 gateway );
2003 argv_msg (D_ROUTE, &argv);
2004 openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route delete -inet6 command failed");
2006 #elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
2008 argv_printf (&argv, "%s delete -inet6 %s/%d",
2009 ROUTE_PATH,
2010 network,
2011 r6->netbits );
2013 if (gateway_needed)
2014 argv_printf_cat (&argv, "%s", gateway);
2015 else
2016 argv_printf_cat (&argv, "-iface %s", device);
2018 argv_msg (D_ROUTE, &argv);
2019 openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route delete -inet6 command failed");
2021 #elif defined(TARGET_DARWIN)
2023 argv_printf (&argv, "%s delete -inet6 %s -prefixlen %d",
2024 ROUTE_PATH,
2025 network, r6->netbits );
2027 if (gateway_needed)
2028 argv_printf_cat (&argv, "%s", gateway);
2029 else
2030 argv_printf_cat (&argv, "-iface %s", device);
2032 argv_msg (D_ROUTE, &argv);
2033 openvpn_execve_check (&argv, es, 0, "ERROR: MacOS X route delete -inet6 command failed");
2035 #elif defined(TARGET_OPENBSD)
2037 argv_printf (&argv, "%s delete -inet6 %s -prefixlen %d %s",
2038 ROUTE_PATH,
2039 network, r6->netbits, gateway );
2041 argv_msg (D_ROUTE, &argv);
2042 openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD route delete -inet6 command failed");
2044 #elif defined(TARGET_NETBSD)
2046 argv_printf (&argv, "%s delete -inet6 %s/%d %s",
2047 ROUTE_PATH,
2048 network, r6->netbits, gateway );
2050 argv_msg (D_ROUTE, &argv);
2051 openvpn_execve_check (&argv, es, 0, "ERROR: NetBSD route delete -inet6 command failed");
2053 #else
2054 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");
2055 #endif
2057 argv_reset (&argv);
2058 gc_free (&gc);
2062 * The --redirect-gateway option requires OS-specific code below
2063 * to get the current default gateway.
2066 #if defined(WIN32)
2068 static const MIB_IPFORWARDTABLE *
2069 get_windows_routing_table (struct gc_arena *gc)
2071 ULONG size = 0;
2072 PMIB_IPFORWARDTABLE rt = NULL;
2073 DWORD status;
2075 status = GetIpForwardTable (NULL, &size, TRUE);
2076 if (status == ERROR_INSUFFICIENT_BUFFER)
2078 rt = (PMIB_IPFORWARDTABLE) gc_malloc (size, false, gc);
2079 status = GetIpForwardTable (rt, &size, TRUE);
2080 if (status != NO_ERROR)
2082 msg (D_ROUTE, "NOTE: GetIpForwardTable returned error: %s (code=%u)",
2083 strerror_win32 (status, gc),
2084 (unsigned int)status);
2085 rt = NULL;
2088 return rt;
2091 static int
2092 test_route (const IP_ADAPTER_INFO *adapters,
2093 const in_addr_t gateway,
2094 DWORD *index)
2096 int count = 0;
2097 DWORD i = adapter_index_of_ip (adapters, gateway, &count, NULL);
2098 if (index)
2099 *index = i;
2100 return count;
2103 static void
2104 test_route_helper (bool *ret,
2105 int *count,
2106 int *good,
2107 int *ambig,
2108 const IP_ADAPTER_INFO *adapters,
2109 const in_addr_t gateway)
2111 int c;
2113 ++*count;
2114 c = test_route (adapters, gateway, NULL);
2115 if (c == 0)
2116 *ret = false;
2117 else
2118 ++*good;
2119 if (c > 1)
2120 ++*ambig;
2124 * If we tried to add routes now, would we succeed?
2126 bool
2127 test_routes (const struct route_list *rl, const struct tuntap *tt)
2129 struct gc_arena gc = gc_new ();
2130 const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
2131 bool ret = false;
2132 int count = 0;
2133 int good = 0;
2134 int ambig = 0;
2135 bool adapter_up = false;
2137 if (is_adapter_up (tt, adapters))
2139 ret = true;
2140 adapter_up = true;
2142 if (rl)
2144 int i;
2145 for (i = 0; i < rl->n; ++i)
2146 test_route_helper (&ret, &count, &good, &ambig, adapters, rl->routes[i].gateway);
2148 if ((rl->flags & RG_ENABLE) && (rl->spec.flags & RTSA_REMOTE_ENDPOINT))
2149 test_route_helper (&ret, &count, &good, &ambig, adapters, rl->spec.remote_endpoint);
2153 msg (D_ROUTE, "TEST ROUTES: %d/%d succeeded len=%d ret=%d a=%d u/d=%s",
2154 good,
2155 count,
2156 rl ? rl->n : -1,
2157 (int)ret,
2158 ambig,
2159 adapter_up ? "up" : "down");
2161 gc_free (&gc);
2162 return ret;
2165 static const MIB_IPFORWARDROW *
2166 get_default_gateway_row (const MIB_IPFORWARDTABLE *routes)
2168 struct gc_arena gc = gc_new ();
2169 DWORD lowest_metric = MAXDWORD;
2170 const MIB_IPFORWARDROW *ret = NULL;
2171 int i;
2172 int best = -1;
2174 if (routes)
2176 for (i = 0; i < routes->dwNumEntries; ++i)
2178 const MIB_IPFORWARDROW *row = &routes->table[i];
2179 const in_addr_t net = ntohl (row->dwForwardDest);
2180 const in_addr_t mask = ntohl (row->dwForwardMask);
2181 const DWORD index = row->dwForwardIfIndex;
2182 const DWORD metric = row->dwForwardMetric1;
2184 dmsg (D_ROUTE_DEBUG, "GDGR: route[%d] %s/%s i=%d m=%d",
2186 print_in_addr_t ((in_addr_t) net, 0, &gc),
2187 print_in_addr_t ((in_addr_t) mask, 0, &gc),
2188 (int)index,
2189 (int)metric);
2191 if (!net && !mask && metric < lowest_metric)
2193 ret = row;
2194 lowest_metric = metric;
2195 best = i;
2200 dmsg (D_ROUTE_DEBUG, "GDGR: best=%d lm=%u", best, (unsigned int)lowest_metric);
2202 gc_free (&gc);
2203 return ret;
2206 void
2207 get_default_gateway (struct route_gateway_info *rgi)
2209 struct gc_arena gc = gc_new ();
2211 const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
2212 const MIB_IPFORWARDTABLE *routes = get_windows_routing_table (&gc);
2213 const MIB_IPFORWARDROW *row = get_default_gateway_row (routes);
2214 DWORD a_index;
2215 const IP_ADAPTER_INFO *ai;
2217 CLEAR(*rgi);
2219 if (row)
2221 rgi->gateway.addr = ntohl (row->dwForwardNextHop);
2222 if (rgi->gateway.addr)
2224 rgi->flags |= RGI_ADDR_DEFINED;
2225 a_index = adapter_index_of_ip (adapters, rgi->gateway.addr, NULL, &rgi->gateway.netmask);
2226 if (a_index != TUN_ADAPTER_INDEX_INVALID)
2228 rgi->adapter_index = a_index;
2229 rgi->flags |= (RGI_IFACE_DEFINED|RGI_NETMASK_DEFINED);
2230 ai = get_adapter (adapters, a_index);
2231 if (ai)
2233 memcpy (rgi->hwaddr, ai->Address, 6);
2234 rgi->flags |= RGI_HWADDR_DEFINED;
2240 gc_free (&gc);
2243 static DWORD
2244 windows_route_find_if_index (const struct route_ipv4 *r, const struct tuntap *tt)
2246 struct gc_arena gc = gc_new ();
2247 DWORD ret = TUN_ADAPTER_INDEX_INVALID;
2248 int count = 0;
2249 const IP_ADAPTER_INFO *adapters = get_adapter_info_list (&gc);
2250 const IP_ADAPTER_INFO *tun_adapter = get_tun_adapter (tt, adapters);
2251 bool on_tun = false;
2253 /* first test on tun interface */
2254 if (is_ip_in_adapter_subnet (tun_adapter, r->gateway, NULL))
2256 ret = tun_adapter->Index;
2257 count = 1;
2258 on_tun = true;
2260 else /* test on other interfaces */
2262 count = test_route (adapters, r->gateway, &ret);
2265 if (count == 0)
2267 msg (M_WARN, "Warning: route gateway is not reachable on any active network adapters: %s",
2268 print_in_addr_t (r->gateway, 0, &gc));
2269 ret = TUN_ADAPTER_INDEX_INVALID;
2271 else if (count > 1)
2273 msg (M_WARN, "Warning: route gateway is ambiguous: %s (%d matches)",
2274 print_in_addr_t (r->gateway, 0, &gc),
2275 count);
2276 ret = TUN_ADAPTER_INDEX_INVALID;
2279 dmsg (D_ROUTE_DEBUG, "DEBUG: route find if: on_tun=%d count=%d index=%d",
2280 on_tun,
2281 count,
2282 (int)ret);
2284 gc_free (&gc);
2285 return ret;
2288 bool
2289 add_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt, DWORD adapter_index)
2291 struct gc_arena gc = gc_new ();
2292 bool ret = false;
2293 DWORD status;
2294 const DWORD if_index = (adapter_index == TUN_ADAPTER_INDEX_INVALID) ? windows_route_find_if_index (r, tt) : adapter_index;
2296 if (if_index != TUN_ADAPTER_INDEX_INVALID)
2298 MIB_IPFORWARDROW fr;
2299 CLEAR (fr);
2300 fr.dwForwardDest = htonl (r->network);
2301 fr.dwForwardMask = htonl (r->netmask);
2302 fr.dwForwardPolicy = 0;
2303 fr.dwForwardNextHop = htonl (r->gateway);
2304 fr.dwForwardIfIndex = if_index;
2305 fr.dwForwardType = 4; /* the next hop is not the final dest */
2306 fr.dwForwardProto = 3; /* PROTO_IP_NETMGMT */
2307 fr.dwForwardAge = 0;
2308 fr.dwForwardNextHopAS = 0;
2309 fr.dwForwardMetric1 = (r->flags & RT_METRIC_DEFINED) ? r->metric : 1;
2310 fr.dwForwardMetric2 = METRIC_NOT_USED;
2311 fr.dwForwardMetric3 = METRIC_NOT_USED;
2312 fr.dwForwardMetric4 = METRIC_NOT_USED;
2313 fr.dwForwardMetric5 = METRIC_NOT_USED;
2315 if ((r->network & r->netmask) != r->network)
2316 msg (M_WARN, "Warning: address %s is not a network address in relation to netmask %s",
2317 print_in_addr_t (r->network, 0, &gc),
2318 print_in_addr_t (r->netmask, 0, &gc));
2320 status = CreateIpForwardEntry (&fr);
2322 if (status == NO_ERROR)
2323 ret = true;
2324 else
2326 /* failed, try increasing the metric to work around Vista issue */
2327 const unsigned int forward_metric_limit = 2048; /* iteratively retry higher metrics up to this limit */
2329 for ( ; fr.dwForwardMetric1 <= forward_metric_limit; ++fr.dwForwardMetric1)
2331 /* try a different forward type=3 ("the next hop is the final dest") in addition to 4.
2332 --redirect-gateway over RRAS seems to need this. */
2333 for (fr.dwForwardType = 4; fr.dwForwardType >= 3; --fr.dwForwardType)
2335 status = CreateIpForwardEntry (&fr);
2336 if (status == NO_ERROR)
2338 msg (D_ROUTE, "ROUTE: CreateIpForwardEntry succeeded with dwForwardMetric1=%u and dwForwardType=%u",
2339 (unsigned int)fr.dwForwardMetric1,
2340 (unsigned int)fr.dwForwardType);
2341 ret = true;
2342 goto doublebreak;
2344 else if (status != ERROR_BAD_ARGUMENTS)
2345 goto doublebreak;
2349 doublebreak:
2350 if (status != NO_ERROR)
2351 msg (M_WARN, "ROUTE: route addition failed using CreateIpForwardEntry: %s [status=%u if_index=%u]",
2352 strerror_win32 (status, &gc),
2353 (unsigned int)status,
2354 (unsigned int)if_index);
2358 gc_free (&gc);
2359 return ret;
2362 bool
2363 del_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt)
2365 struct gc_arena gc = gc_new ();
2366 bool ret = false;
2367 DWORD status;
2368 const DWORD if_index = windows_route_find_if_index (r, tt);
2370 if (if_index != TUN_ADAPTER_INDEX_INVALID)
2372 MIB_IPFORWARDROW fr;
2373 CLEAR (fr);
2375 fr.dwForwardDest = htonl (r->network);
2376 fr.dwForwardMask = htonl (r->netmask);
2377 fr.dwForwardPolicy = 0;
2378 fr.dwForwardNextHop = htonl (r->gateway);
2379 fr.dwForwardIfIndex = if_index;
2381 status = DeleteIpForwardEntry (&fr);
2383 if (status == NO_ERROR)
2384 ret = true;
2385 else
2386 msg (M_WARN, "ROUTE: route deletion failed using DeleteIpForwardEntry: %s",
2387 strerror_win32 (status, &gc));
2390 gc_free (&gc);
2391 return ret;
2394 static const char *
2395 format_route_entry (const MIB_IPFORWARDROW *r, struct gc_arena *gc)
2397 struct buffer out = alloc_buf_gc (256, gc);
2398 buf_printf (&out, "%s %s %s p=%d i=%d t=%d pr=%d a=%d h=%d m=%d/%d/%d/%d/%d",
2399 print_in_addr_t (r->dwForwardDest, IA_NET_ORDER, gc),
2400 print_in_addr_t (r->dwForwardMask, IA_NET_ORDER, gc),
2401 print_in_addr_t (r->dwForwardNextHop, IA_NET_ORDER, gc),
2402 (int)r->dwForwardPolicy,
2403 (int)r->dwForwardIfIndex,
2404 (int)r->dwForwardType,
2405 (int)r->dwForwardProto,
2406 (int)r->dwForwardAge,
2407 (int)r->dwForwardNextHopAS,
2408 (int)r->dwForwardMetric1,
2409 (int)r->dwForwardMetric2,
2410 (int)r->dwForwardMetric3,
2411 (int)r->dwForwardMetric4,
2412 (int)r->dwForwardMetric5);
2413 return BSTR (&out);
2417 * Show current routing table
2419 void
2420 show_routes (int msglev)
2422 struct gc_arena gc = gc_new ();
2423 int i;
2425 const MIB_IPFORWARDTABLE *rt = get_windows_routing_table (&gc);
2427 msg (msglev, "SYSTEM ROUTING TABLE");
2428 if (rt)
2430 for (i = 0; i < rt->dwNumEntries; ++i)
2432 msg (msglev, "%s", format_route_entry (&rt->table[i], &gc));
2435 gc_free (&gc);
2438 #elif defined(TARGET_LINUX)
2440 void
2441 get_default_gateway (struct route_gateway_info *rgi)
2443 struct gc_arena gc = gc_new ();
2444 int sd = -1;
2445 char best_name[16];
2446 best_name[0] = 0;
2448 CLEAR(*rgi);
2450 /* get default gateway IP addr */
2452 FILE *fp = fopen ("/proc/net/route", "r");
2453 if (fp)
2455 char line[256];
2456 int count = 0;
2457 unsigned int lowest_metric = UINT_MAX;
2458 in_addr_t best_gw = 0;
2459 bool found = false;
2460 while (fgets (line, sizeof (line), fp) != NULL)
2462 if (count)
2464 unsigned int net_x = 0;
2465 unsigned int mask_x = 0;
2466 unsigned int gw_x = 0;
2467 unsigned int metric = 0;
2468 unsigned int flags = 0;
2469 char name[16];
2470 name[0] = 0;
2471 const int np = sscanf (line, "%15s\t%x\t%x\t%x\t%*s\t%*s\t%d\t%x",
2472 name,
2473 &net_x,
2474 &gw_x,
2475 &flags,
2476 &metric,
2477 &mask_x);
2478 if (np == 6 && (flags & IFF_UP))
2480 const in_addr_t net = ntohl (net_x);
2481 const in_addr_t mask = ntohl (mask_x);
2482 const in_addr_t gw = ntohl (gw_x);
2484 if (!net && !mask && metric < lowest_metric)
2486 found = true;
2487 best_gw = gw;
2488 strcpy (best_name, name);
2489 lowest_metric = metric;
2493 ++count;
2495 fclose (fp);
2497 if (found)
2499 rgi->gateway.addr = best_gw;
2500 rgi->flags |= RGI_ADDR_DEFINED;
2501 if (!rgi->gateway.addr && best_name[0])
2502 rgi->flags |= RGI_ON_LINK;
2507 /* scan adapter list */
2508 if (rgi->flags & RGI_ADDR_DEFINED)
2510 struct ifreq *ifr, *ifend;
2511 in_addr_t addr, netmask;
2512 struct ifreq ifreq;
2513 struct ifconf ifc;
2514 struct ifreq ifs[20]; /* Maximum number of interfaces to scan */
2516 if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
2518 msg (M_WARN, "GDG: socket() failed");
2519 goto done;
2521 ifc.ifc_len = sizeof (ifs);
2522 ifc.ifc_req = ifs;
2523 if (ioctl (sd, SIOCGIFCONF, &ifc) < 0)
2525 msg (M_WARN, "GDG: ioctl(SIOCGIFCONF) failed");
2526 goto done;
2529 /* scan through interface list */
2530 ifend = ifs + (ifc.ifc_len / sizeof (struct ifreq));
2531 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
2533 if (ifr->ifr_addr.sa_family == AF_INET)
2535 /* get interface addr */
2536 addr = ntohl(((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr);
2538 /* get interface name */
2539 strncpynt (ifreq.ifr_name, ifr->ifr_name, sizeof (ifreq.ifr_name));
2541 /* check that the interface is up */
2542 if (ioctl (sd, SIOCGIFFLAGS, &ifreq) < 0)
2543 continue;
2544 if (!(ifreq.ifr_flags & IFF_UP))
2545 continue;
2547 if (rgi->flags & RGI_ON_LINK)
2549 /* check that interface name of current interface
2550 matches interface name of best default route */
2551 if (strcmp(ifreq.ifr_name, best_name))
2552 continue;
2553 #if 0
2554 /* if point-to-point link, use remote addr as route gateway */
2555 if ((ifreq.ifr_flags & IFF_POINTOPOINT) && ioctl (sd, SIOCGIFDSTADDR, &ifreq) >= 0)
2557 rgi->gateway.addr = ntohl(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
2558 if (rgi->gateway.addr)
2559 rgi->flags &= ~RGI_ON_LINK;
2561 #endif
2563 else
2565 /* get interface netmask */
2566 if (ioctl (sd, SIOCGIFNETMASK, &ifreq) < 0)
2567 continue;
2568 netmask = ntohl(((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr);
2570 /* check that interface matches default route */
2571 if (((rgi->gateway.addr ^ addr) & netmask) != 0)
2572 continue;
2574 /* save netmask */
2575 rgi->gateway.netmask = netmask;
2576 rgi->flags |= RGI_NETMASK_DEFINED;
2579 /* save iface name */
2580 strncpynt (rgi->iface, ifreq.ifr_name, sizeof(rgi->iface));
2581 rgi->flags |= RGI_IFACE_DEFINED;
2583 /* now get the hardware address. */
2584 memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
2585 if (ioctl (sd, SIOCGIFHWADDR, &ifreq) < 0)
2587 msg (M_WARN, "GDG: SIOCGIFHWADDR(%s) failed", ifreq.ifr_name);
2588 goto done;
2590 memcpy (rgi->hwaddr, &ifreq.ifr_hwaddr.sa_data, 6);
2591 rgi->flags |= RGI_HWADDR_DEFINED;
2593 break;
2598 done:
2599 if (sd >= 0)
2600 close (sd);
2601 gc_free (&gc);
2604 #elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
2606 #include <sys/types.h>
2607 #include <sys/socket.h>
2608 #include <netinet/in.h>
2609 #include <net/route.h>
2611 struct {
2612 struct rt_msghdr m_rtm;
2613 char m_space[512];
2614 } m_rtmsg;
2616 #define ROUNDUP(a) \
2617 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
2620 * FIXME -- add support for netmask, hwaddr, and iface
2622 void
2623 get_default_gateway (struct route_gateway_info *rgi)
2625 struct gc_arena gc = gc_new ();
2626 int s, seq, l, pid, rtm_addrs, i;
2627 struct sockaddr so_dst, so_mask;
2628 char *cp = m_rtmsg.m_space;
2629 struct sockaddr *gate = NULL, *sa;
2630 struct rt_msghdr *rtm_aux;
2632 #define NEXTADDR(w, u) \
2633 if (rtm_addrs & (w)) {\
2634 l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
2637 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
2639 #define rtm m_rtmsg.m_rtm
2641 CLEAR(*rgi);
2643 pid = getpid();
2644 seq = 0;
2645 rtm_addrs = RTA_DST | RTA_NETMASK;
2647 bzero(&so_dst, sizeof(so_dst));
2648 bzero(&so_mask, sizeof(so_mask));
2649 bzero(&rtm, sizeof(struct rt_msghdr));
2651 rtm.rtm_type = RTM_GET;
2652 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
2653 rtm.rtm_version = RTM_VERSION;
2654 rtm.rtm_seq = ++seq;
2655 rtm.rtm_addrs = rtm_addrs;
2657 so_dst.sa_family = AF_INET;
2658 so_dst.sa_len = sizeof(struct sockaddr_in);
2659 so_mask.sa_family = AF_INET;
2660 so_mask.sa_len = sizeof(struct sockaddr_in);
2662 NEXTADDR(RTA_DST, so_dst);
2663 NEXTADDR(RTA_NETMASK, so_mask);
2665 rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
2667 s = socket(PF_ROUTE, SOCK_RAW, 0);
2669 if (write(s, (char *)&m_rtmsg, l) < 0)
2671 msg(M_WARN|M_ERRNO, "Could not retrieve default gateway from route socket:");
2672 gc_free (&gc);
2673 close(s);
2674 return;
2677 do {
2678 l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
2679 } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
2681 close(s);
2683 rtm_aux = &rtm;
2685 cp = ((char *)(rtm_aux + 1));
2686 if (rtm_aux->rtm_addrs) {
2687 for (i = 1; i; i <<= 1)
2688 if (i & rtm_aux->rtm_addrs) {
2689 sa = (struct sockaddr *)cp;
2690 if (i == RTA_GATEWAY )
2691 gate = sa;
2692 ADVANCE(cp, sa);
2695 else
2697 gc_free (&gc);
2698 return;
2702 if (gate != NULL )
2704 rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
2705 rgi->flags |= RGI_ADDR_DEFINED;
2707 gc_free (&gc);
2709 else
2711 gc_free (&gc);
2715 #elif defined(TARGET_DARWIN)
2717 #include <sys/types.h>
2718 #include <sys/socket.h>
2719 #include <netinet/in.h>
2720 #include <net/route.h>
2721 #include <net/if_dl.h>
2723 struct rtmsg {
2724 struct rt_msghdr m_rtm;
2725 char m_space[512];
2728 #define ROUNDUP(a) \
2729 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
2731 #define NEXTADDR(w, u) \
2732 if (rtm_addrs & (w)) {\
2733 l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
2736 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
2738 #define max(a,b) ((a) > (b) ? (a) : (b))
2740 void
2741 get_default_gateway (struct route_gateway_info *rgi)
2743 struct gc_arena gc = gc_new ();
2744 struct rtmsg m_rtmsg;
2745 int sockfd = -1;
2746 int seq, l, pid, rtm_addrs, i;
2747 struct sockaddr so_dst, so_mask;
2748 char *cp = m_rtmsg.m_space;
2749 struct sockaddr *gate = NULL, *ifp = NULL, *sa;
2750 struct rt_msghdr *rtm_aux;
2752 # define rtm m_rtmsg.m_rtm
2754 CLEAR(*rgi);
2756 /* setup data to send to routing socket */
2757 pid = getpid();
2758 seq = 0;
2759 rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
2761 bzero(&m_rtmsg, sizeof(m_rtmsg));
2762 bzero(&so_dst, sizeof(so_dst));
2763 bzero(&so_mask, sizeof(so_mask));
2764 bzero(&rtm, sizeof(struct rt_msghdr));
2766 rtm.rtm_type = RTM_GET;
2767 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
2768 rtm.rtm_version = RTM_VERSION;
2769 rtm.rtm_seq = ++seq;
2770 rtm.rtm_addrs = rtm_addrs;
2772 so_dst.sa_family = AF_INET;
2773 so_dst.sa_len = sizeof(struct sockaddr_in);
2774 so_mask.sa_family = AF_INET;
2775 so_mask.sa_len = sizeof(struct sockaddr_in);
2777 NEXTADDR(RTA_DST, so_dst);
2778 NEXTADDR(RTA_NETMASK, so_mask);
2780 rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
2782 /* transact with routing socket */
2783 sockfd = socket(PF_ROUTE, SOCK_RAW, 0);
2784 if (sockfd < 0)
2786 msg (M_WARN, "GDG: socket #1 failed");
2787 goto done;
2789 if (write(sockfd, (char *)&m_rtmsg, l) < 0)
2791 msg (M_WARN, "GDG: problem writing to routing socket");
2792 goto done;
2794 do {
2795 l = read(sockfd, (char *)&m_rtmsg, sizeof(m_rtmsg));
2796 } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
2797 close(sockfd);
2798 sockfd = -1;
2800 /* extract return data from routing socket */
2801 rtm_aux = &rtm;
2802 cp = ((char *)(rtm_aux + 1));
2803 if (rtm_aux->rtm_addrs)
2805 for (i = 1; i; i <<= 1)
2807 if (i & rtm_aux->rtm_addrs)
2809 sa = (struct sockaddr *)cp;
2810 if (i == RTA_GATEWAY )
2811 gate = sa;
2812 else if (i == RTA_IFP)
2813 ifp = sa;
2814 ADVANCE(cp, sa);
2818 else
2819 goto done;
2821 /* get gateway addr and interface name */
2822 if (gate != NULL )
2824 /* get default gateway addr */
2825 rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
2826 if (rgi->gateway.addr)
2827 rgi->flags |= RGI_ADDR_DEFINED;
2829 if (ifp)
2831 /* get interface name */
2832 const struct sockaddr_dl *adl = (struct sockaddr_dl *) ifp;
2833 int len = adl->sdl_nlen;
2834 if (adl->sdl_nlen && adl->sdl_nlen < sizeof(rgi->iface))
2836 memcpy (rgi->iface, adl->sdl_data, adl->sdl_nlen);
2837 rgi->iface[adl->sdl_nlen] = '\0';
2838 rgi->flags |= RGI_IFACE_DEFINED;
2843 /* get netmask of interface that owns default gateway */
2844 if (rgi->flags & RGI_IFACE_DEFINED) {
2845 struct ifreq ifr;
2847 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2848 if (sockfd < 0)
2850 msg (M_WARN, "GDG: socket #2 failed");
2851 goto done;
2854 CLEAR(ifr);
2855 ifr.ifr_addr.sa_family = AF_INET;
2856 strncpynt(ifr.ifr_name, rgi->iface, IFNAMSIZ);
2858 if (ioctl(sockfd, SIOCGIFNETMASK, (char *)&ifr) < 0)
2860 msg (M_WARN, "GDG: ioctl #1 failed");
2861 goto done;
2863 close(sockfd);
2864 sockfd = -1;
2866 rgi->gateway.netmask = ntohl(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
2867 rgi->flags |= RGI_NETMASK_DEFINED;
2870 /* try to read MAC addr associated with interface that owns default gateway */
2871 if (rgi->flags & RGI_IFACE_DEFINED)
2873 struct ifconf ifc;
2874 struct ifreq *ifr;
2875 const int bufsize = 4096;
2876 char *buffer;
2878 buffer = (char *) gc_malloc (bufsize, true, &gc);
2879 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
2880 if (sockfd < 0)
2882 msg (M_WARN, "GDG: socket #3 failed");
2883 goto done;
2886 ifc.ifc_len = bufsize;
2887 ifc.ifc_buf = buffer;
2889 if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0)
2891 msg (M_WARN, "GDG: ioctl #2 failed");
2892 goto done;
2894 close(sockfd);
2895 sockfd = -1;
2897 for (cp = buffer; cp <= buffer + ifc.ifc_len - sizeof(struct ifreq); )
2899 ifr = (struct ifreq *)cp;
2900 const size_t len = sizeof(ifr->ifr_name) + max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);
2901 if (!ifr->ifr_addr.sa_family)
2902 break;
2903 if (!strncmp(ifr->ifr_name, rgi->iface, IFNAMSIZ))
2905 if (ifr->ifr_addr.sa_family == AF_LINK)
2907 struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
2908 memcpy(rgi->hwaddr, LLADDR(sdl), 6);
2909 rgi->flags |= RGI_HWADDR_DEFINED;
2912 cp += len;
2916 done:
2917 if (sockfd >= 0)
2918 close(sockfd);
2919 gc_free (&gc);
2922 #undef max
2924 #elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD)
2926 #include <sys/types.h>
2927 #include <sys/socket.h>
2928 #include <netinet/in.h>
2929 #include <net/route.h>
2931 struct {
2932 struct rt_msghdr m_rtm;
2933 char m_space[512];
2934 } m_rtmsg;
2936 #define ROUNDUP(a) \
2937 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
2940 * FIXME -- add support for netmask, hwaddr, and iface
2942 void
2943 get_default_gateway (struct route_gateway_info *rgi)
2945 struct gc_arena gc = gc_new ();
2946 int s, seq, l, rtm_addrs, i;
2947 pid_t pid;
2948 struct sockaddr so_dst, so_mask;
2949 char *cp = m_rtmsg.m_space;
2950 struct sockaddr *gate = NULL, *sa;
2951 struct rt_msghdr *rtm_aux;
2953 #define NEXTADDR(w, u) \
2954 if (rtm_addrs & (w)) {\
2955 l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\
2958 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
2960 #define rtm m_rtmsg.m_rtm
2962 CLEAR(*rgi);
2964 pid = getpid();
2965 seq = 0;
2966 rtm_addrs = RTA_DST | RTA_NETMASK;
2968 bzero(&so_dst, sizeof(so_dst));
2969 bzero(&so_mask, sizeof(so_mask));
2970 bzero(&rtm, sizeof(struct rt_msghdr));
2972 rtm.rtm_type = RTM_GET;
2973 rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
2974 rtm.rtm_version = RTM_VERSION;
2975 rtm.rtm_seq = ++seq;
2976 rtm.rtm_addrs = rtm_addrs;
2978 so_dst.sa_family = AF_INET;
2979 so_dst.sa_len = sizeof(struct sockaddr_in);
2980 so_mask.sa_family = AF_INET;
2981 so_mask.sa_len = sizeof(struct sockaddr_in);
2983 NEXTADDR(RTA_DST, so_dst);
2984 NEXTADDR(RTA_NETMASK, so_mask);
2986 rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
2988 s = socket(PF_ROUTE, SOCK_RAW, 0);
2990 if (write(s, (char *)&m_rtmsg, l) < 0)
2992 msg(M_WARN|M_ERRNO, "Could not retrieve default gateway from route socket:");
2993 gc_free (&gc);
2994 close(s);
2995 return;
2998 do {
2999 l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
3000 } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
3002 close(s);
3004 rtm_aux = &rtm;
3006 cp = ((char *)(rtm_aux + 1));
3007 if (rtm_aux->rtm_addrs) {
3008 for (i = 1; i; i <<= 1)
3009 if (i & rtm_aux->rtm_addrs) {
3010 sa = (struct sockaddr *)cp;
3011 if (i == RTA_GATEWAY )
3012 gate = sa;
3013 ADVANCE(cp, sa);
3016 else
3018 gc_free (&gc);
3019 return;
3023 if (gate != NULL )
3025 rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr);
3026 rgi->flags |= RGI_ADDR_DEFINED;
3028 gc_free (&gc);
3030 else
3032 gc_free (&gc);
3036 #else
3039 * This is a platform-specific method that returns data about
3040 * the current default gateway. Return data is placed into
3041 * a struct route_gateway_info object provided by caller. The
3042 * implementation should CLEAR the structure before adding
3043 * data to it.
3045 * Data returned includes:
3046 * 1. default gateway address (rgi->gateway.addr)
3047 * 2. netmask of interface that owns default gateway
3048 * (rgi->gateway.netmask)
3049 * 3. hardware address (i.e. MAC address) of interface that owns
3050 * default gateway (rgi->hwaddr)
3051 * 4. interface name (or adapter index on Windows) that owns default
3052 * gateway (rgi->iface or rgi->adapter_index)
3053 * 5. an array of additional address/netmask pairs defined by
3054 * interface that owns default gateway (rgi->addrs with length
3055 * given in rgi->n_addrs)
3057 * The flags RGI_x_DEFINED may be used to indicate which of the data
3058 * members were successfully returned (set in rgi->flags). All of
3059 * the data members are optional, however certain OpenVPN functionality
3060 * may be disabled by missing items.
3062 void
3063 get_default_gateway (struct route_gateway_info *rgi)
3065 CLEAR(*rgi);
3068 #endif
3070 bool
3071 netmask_to_netbits (const in_addr_t network, const in_addr_t netmask, int *netbits)
3073 int i;
3074 const int addrlen = sizeof (in_addr_t) * 8;
3076 if ((network & netmask) == network)
3078 for (i = 0; i <= addrlen; ++i)
3080 in_addr_t mask = netbits_to_netmask (i);
3081 if (mask == netmask)
3083 if (i == addrlen)
3084 *netbits = -1;
3085 else
3086 *netbits = i;
3087 return true;
3091 return false;
3095 * get_bypass_addresses() is used by the redirect-gateway bypass-x
3096 * functions to build a route bypass to selected DHCP/DNS servers,
3097 * so that outgoing packets to these servers don't end up in the tunnel.
3100 #if defined(WIN32)
3102 static void
3103 add_host_route_if_nonlocal (struct route_bypass *rb, const in_addr_t addr)
3105 if (test_local_addr(addr, NULL) == TLA_NONLOCAL && addr != 0 && addr != IPV4_NETMASK_HOST)
3106 add_bypass_address (rb, addr);
3109 static void
3110 add_host_route_array (struct route_bypass *rb, const IP_ADDR_STRING *iplist)
3112 while (iplist)
3114 bool succeed = false;
3115 const in_addr_t ip = getaddr (GETADDR_HOST_ORDER, iplist->IpAddress.String, 0, &succeed, NULL);
3116 if (succeed)
3118 add_host_route_if_nonlocal (rb, ip);
3120 iplist = iplist->Next;
3124 static void
3125 get_bypass_addresses (struct route_bypass *rb, const unsigned int flags)
3127 struct gc_arena gc = gc_new ();
3128 /*bool ret_bool = false;*/
3130 /* get full routing table */
3131 const MIB_IPFORWARDTABLE *routes = get_windows_routing_table (&gc);
3133 /* get the route which represents the default gateway */
3134 const MIB_IPFORWARDROW *row = get_default_gateway_row (routes);
3136 if (row)
3138 /* get the adapter which the default gateway is associated with */
3139 const IP_ADAPTER_INFO *dgi = get_adapter_info (row->dwForwardIfIndex, &gc);
3141 /* get extra adapter info, such as DNS addresses */
3142 const IP_PER_ADAPTER_INFO *pai = get_per_adapter_info (row->dwForwardIfIndex, &gc);
3144 /* Bypass DHCP server address */
3145 if ((flags & RG_BYPASS_DHCP) && dgi && dgi->DhcpEnabled)
3146 add_host_route_array (rb, &dgi->DhcpServer);
3148 /* Bypass DNS server addresses */
3149 if ((flags & RG_BYPASS_DNS) && pai)
3150 add_host_route_array (rb, &pai->DnsServerList);
3153 gc_free (&gc);
3156 #else
3158 static void
3159 get_bypass_addresses (struct route_bypass *rb, const unsigned int flags) /* PLATFORM-SPECIFIC */
3163 #endif
3166 * Test if addr is reachable via a local interface (return ILA_LOCAL),
3167 * or if it needs to be routed via the default gateway (return
3168 * ILA_NONLOCAL). If the target platform doesn't implement this
3169 * function, return ILA_NOT_IMPLEMENTED.
3171 * Used by redirect-gateway autolocal feature
3174 #if defined(WIN32)
3177 test_local_addr (const in_addr_t addr, const struct route_gateway_info *rgi)
3179 struct gc_arena gc = gc_new ();
3180 const in_addr_t nonlocal_netmask = 0x80000000L; /* routes with netmask <= to this are considered non-local */
3181 bool ret = TLA_NONLOCAL;
3183 /* get full routing table */
3184 const MIB_IPFORWARDTABLE *rt = get_windows_routing_table (&gc);
3185 if (rt)
3187 int i;
3188 for (i = 0; i < rt->dwNumEntries; ++i)
3190 const MIB_IPFORWARDROW *row = &rt->table[i];
3191 const in_addr_t net = ntohl (row->dwForwardDest);
3192 const in_addr_t mask = ntohl (row->dwForwardMask);
3193 if (mask > nonlocal_netmask && (addr & mask) == net)
3195 ret = TLA_LOCAL;
3196 break;
3201 gc_free (&gc);
3202 return ret;
3205 #else
3208 test_local_addr (const in_addr_t addr, const struct route_gateway_info *rgi) /* PLATFORM-SPECIFIC */
3210 if (rgi)
3212 if (local_route (addr, 0xFFFFFFFF, rgi->gateway.addr, rgi))
3213 return TLA_LOCAL;
3214 else
3215 return TLA_NONLOCAL;
3217 return TLA_NOT_IMPLEMENTED;
3220 #endif