Also introduce x_gc_addspeical function that allows to add objects with a
custom free function to the gc.
Some additional addrinfo cleanup
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <1395576786-17507-1-git-send-email-arne@rfc2549.org>
URL: http://article.gmane.org/gmane.network.openvpn.devel/8386
Signed-off-by: Gert Doering <gert@greenie.muc.de>
... | ... |
@@ -372,6 +372,44 @@ x_gc_free (struct gc_arena *a) |
372 | 372 |
} |
373 | 373 |
|
374 | 374 |
/* |
375 |
+ * Functions to handle special objects in gc_entries |
|
376 |
+ */ |
|
377 |
+ |
|
378 |
+void |
|
379 |
+x_gc_freespecial (struct gc_arena *a) |
|
380 |
+{ |
|
381 |
+ struct gc_entry_special *e; |
|
382 |
+ e = a->list_special; |
|
383 |
+ a->list_special = NULL; |
|
384 |
+ |
|
385 |
+ while (e != NULL) |
|
386 |
+ { |
|
387 |
+ struct gc_entry_special *next = e->next; |
|
388 |
+ e->free_fnc (e->addr); |
|
389 |
+ free(e); |
|
390 |
+ e = next; |
|
391 |
+ } |
|
392 |
+} |
|
393 |
+ |
|
394 |
+void gc_addspecial (void *addr, void (free_function)(void*), struct gc_arena *a) |
|
395 |
+{ |
|
396 |
+ ASSERT(a); |
|
397 |
+ struct gc_entry_special *e; |
|
398 |
+#ifdef DMALLOC |
|
399 |
+ e = (struct gc_entry_special *) openvpn_dmalloc (file, line, sizeof (struct gc_entry_special)); |
|
400 |
+#else |
|
401 |
+ e = (struct gc_entry_special *) malloc (sizeof (struct gc_entry_special)); |
|
402 |
+#endif |
|
403 |
+ check_malloc_return (e); |
|
404 |
+ e->free_fnc = free_function; |
|
405 |
+ e->addr = addr; |
|
406 |
+ |
|
407 |
+ e->next = a->list_special; |
|
408 |
+ a->list_special = e; |
|
409 |
+} |
|
410 |
+ |
|
411 |
+ |
|
412 |
+/* |
|
375 | 413 |
* Transfer src arena to dest, resetting src to an empty arena. |
376 | 414 |
*/ |
377 | 415 |
void |
... | ... |
@@ -91,6 +91,18 @@ struct gc_entry |
91 | 91 |
* linked list. */ |
92 | 92 |
}; |
93 | 93 |
|
94 |
+/** |
|
95 |
+ * Gargabe collection entry for a specially allocated structure that needs |
|
96 |
+ * a custom free function to be freed like struct addrinfo |
|
97 |
+ * |
|
98 |
+ */ |
|
99 |
+struct gc_entry_special |
|
100 |
+{ |
|
101 |
+ struct gc_entry_special *next; |
|
102 |
+ void (*free_fnc)(void*); |
|
103 |
+ void *addr; |
|
104 |
+}; |
|
105 |
+ |
|
94 | 106 |
|
95 | 107 |
/** |
96 | 108 |
* Garbage collection arena used to keep track of dynamically allocated |
... | ... |
@@ -106,6 +118,7 @@ struct gc_arena |
106 | 106 |
{ |
107 | 107 |
struct gc_entry *list; /**< First element of the linked list of |
108 | 108 |
* \c gc_entry structures. */ |
109 |
+ struct gc_entry_special *list_special; |
|
109 | 110 |
}; |
110 | 111 |
|
111 | 112 |
|
... | ... |
@@ -163,6 +176,9 @@ struct buffer string_alloc_buf (const char *str, struct gc_arena *gc); |
163 | 163 |
|
164 | 164 |
#endif |
165 | 165 |
|
166 |
+void gc_addspecial (void *addr, void (*free_function)(void*), struct gc_arena *a); |
|
167 |
+ |
|
168 |
+ |
|
166 | 169 |
#ifdef BUF_INIT_TRACKING |
167 | 170 |
#define buf_init(buf, offset) buf_init_debug (buf, offset, __FILE__, __LINE__) |
168 | 171 |
bool buf_init_debug (struct buffer *buf, int offset, const char *file, int line); |
... | ... |
@@ -172,6 +188,11 @@ bool buf_init_debug (struct buffer *buf, int offset, const char *file, int line) |
172 | 172 |
|
173 | 173 |
|
174 | 174 |
/* inline functions */ |
175 |
+inline static void |
|
176 |
+gc_freeaddrinfo_callback (void *addr) |
|
177 |
+{ |
|
178 |
+ freeaddrinfo((struct addrinfo*) addr); |
|
179 |
+} |
|
175 | 180 |
|
176 | 181 |
static inline bool |
177 | 182 |
buf_defined (const struct buffer *buf) |
... | ... |
@@ -778,6 +799,7 @@ void character_class_debug (void); |
778 | 778 |
void gc_transfer (struct gc_arena *dest, struct gc_arena *src); |
779 | 779 |
|
780 | 780 |
void x_gc_free (struct gc_arena *a); |
781 |
+void x_gc_freespecial (struct gc_arena *a); |
|
781 | 782 |
|
782 | 783 |
static inline bool |
783 | 784 |
gc_defined (struct gc_arena *a) |
... | ... |
@@ -789,6 +811,7 @@ static inline void |
789 | 789 |
gc_init (struct gc_arena *a) |
790 | 790 |
{ |
791 | 791 |
a->list = NULL; |
792 |
+ a->list_special = NULL; |
|
792 | 793 |
} |
793 | 794 |
|
794 | 795 |
static inline void |
... | ... |
@@ -801,7 +824,7 @@ static inline struct gc_arena |
801 | 801 |
gc_new (void) |
802 | 802 |
{ |
803 | 803 |
struct gc_arena ret; |
804 |
- ret.list = NULL; |
|
804 |
+ gc_init (&ret); |
|
805 | 805 |
return ret; |
806 | 806 |
} |
807 | 807 |
|
... | ... |
@@ -810,6 +833,8 @@ gc_free (struct gc_arena *a) |
810 | 810 |
{ |
811 | 811 |
if (a->list) |
812 | 812 |
x_gc_free (a); |
813 |
+ if (a->list_special) |
|
814 |
+ x_gc_freespecial(a); |
|
813 | 815 |
} |
814 | 816 |
|
815 | 817 |
static inline void |
... | ... |
@@ -131,7 +131,8 @@ management_callback_proxy_cmd (void *arg, const char **p) |
131 | 131 |
msg (M_WARN, "HTTP proxy support is not available"); |
132 | 132 |
#else |
133 | 133 |
struct http_proxy_options *ho; |
134 |
- if (ce->proto != PROTO_TCP && ce->proto != PROTO_TCP_CLIENT ) { |
|
134 |
+ if (ce->proto != PROTO_TCP && ce->proto != PROTO_TCP_CLIENT ) |
|
135 |
+ { |
|
135 | 136 |
msg (M_WARN, "HTTP proxy support only works for TCP based connections"); |
136 | 137 |
return false; |
137 | 138 |
} |
... | ... |
@@ -306,11 +307,10 @@ init_connection_list (struct context *c) |
306 | 306 |
/* |
307 | 307 |
* Clear the remote address list |
308 | 308 |
*/ |
309 |
-static void clear_remote_addrlist (struct link_socket_addr *lsa) |
|
309 |
+static void clear_remote_addrlist (struct link_socket_addr *lsa, bool free) |
|
310 | 310 |
{ |
311 |
- if (lsa->remote_list) { |
|
312 |
- freeaddrinfo(lsa->remote_list); |
|
313 |
- } |
|
311 |
+ if (lsa->remote_list && free) |
|
312 |
+ freeaddrinfo(lsa->remote_list); |
|
314 | 313 |
lsa->remote_list = NULL; |
315 | 314 |
lsa->current_remote = NULL; |
316 | 315 |
} |
... | ... |
@@ -348,9 +348,12 @@ next_connection_entry (struct context *c) |
348 | 348 |
* this is broken probably ever since connection lists and multiple |
349 | 349 |
* remote existed |
350 | 350 |
*/ |
351 |
- |
|
352 | 351 |
if (!c->options.persist_remote_ip) |
353 |
- clear_remote_addrlist (&c->c1.link_socket_addr); |
|
352 |
+ { |
|
353 |
+ /* close_instance should have cleared the addrinfo objects */ |
|
354 |
+ ASSERT (c->c1.link_socket_addr.current_remote == NULL); |
|
355 |
+ ASSERT (c->c1.link_socket_addr.remote_list == NULL); |
|
356 |
+ } |
|
354 | 357 |
else |
355 | 358 |
c->c1.link_socket_addr.current_remote = |
356 | 359 |
c->c1.link_socket_addr.remote_list; |
... | ... |
@@ -2688,6 +2691,7 @@ do_init_socket_1 (struct context *c, const int mode) |
2688 | 2688 |
c->options.ce.local_port, |
2689 | 2689 |
c->options.ce.remote, |
2690 | 2690 |
c->options.ce.remote_port, |
2691 |
+ c->c1.dns_cache, |
|
2691 | 2692 |
c->options.ce.proto, |
2692 | 2693 |
c->options.ce.af, |
2693 | 2694 |
c->options.ce.bind_ipv6_only, |
... | ... |
@@ -2908,7 +2912,7 @@ do_close_link_socket (struct context *c) |
2908 | 2908 |
|| c->options.no_advance)) |
2909 | 2909 |
))) |
2910 | 2910 |
{ |
2911 |
- clear_remote_addrlist(&c->c1.link_socket_addr); |
|
2911 |
+ clear_remote_addrlist(&c->c1.link_socket_addr, !c->options.resolve_in_advance); |
|
2912 | 2912 |
} |
2913 | 2913 |
|
2914 | 2914 |
/* Clear the remote actual address when persist_remote_ip is not in use */ |
... | ... |
@@ -2916,8 +2920,9 @@ do_close_link_socket (struct context *c) |
2916 | 2916 |
CLEAR (c->c1.link_socket_addr.actual); |
2917 | 2917 |
|
2918 | 2918 |
if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_local_ip)) { |
2919 |
- if (c->c1.link_socket_addr.bind_local) |
|
2920 |
- freeaddrinfo(c->c1.link_socket_addr.bind_local); |
|
2919 |
+ if (c->c1.link_socket_addr.bind_local && !c->options.resolve_in_advance) |
|
2920 |
+ freeaddrinfo(c->c1.link_socket_addr.bind_local); |
|
2921 |
+ |
|
2921 | 2922 |
c->c1.link_socket_addr.bind_local=NULL; |
2922 | 2923 |
} |
2923 | 2924 |
} |
... | ... |
@@ -3359,6 +3364,13 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int |
3359 | 3359 |
goto sig; |
3360 | 3360 |
} |
3361 | 3361 |
|
3362 |
+ if (c->options.resolve_in_advance) |
|
3363 |
+ { |
|
3364 |
+ do_preresolve (c); |
|
3365 |
+ if (IS_SIG (c)) |
|
3366 |
+ goto sig; |
|
3367 |
+ } |
|
3368 |
+ |
|
3362 | 3369 |
/* map in current connection entry */ |
3363 | 3370 |
next_connection_entry (c); |
3364 | 3371 |
|
... | ... |
@@ -1568,9 +1568,9 @@ man_listen (struct management *man) |
1568 | 1568 |
else |
1569 | 1569 |
#endif |
1570 | 1570 |
{ |
1571 |
- man->connection.sd_top = create_socket_tcp (AF_INET); |
|
1571 |
+ man->connection.sd_top = create_socket_tcp (man->settings.local->ai_family); |
|
1572 | 1572 |
socket_bind (man->connection.sd_top, man->settings.local, |
1573 |
- AF_INET, "MANAGEMENT", true); |
|
1573 |
+ man->settings.local->ai_family, "MANAGEMENT", false); |
|
1574 | 1574 |
} |
1575 | 1575 |
|
1576 | 1576 |
/* |
... | ... |
@@ -2151,8 +2151,14 @@ man_settings_init (struct man_settings *ms, |
2151 | 2151 |
} |
2152 | 2152 |
else |
2153 | 2153 |
{ |
2154 |
- int status = openvpn_getaddrinfo(GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, |
|
2155 |
- addr, port, 0, NULL, AF_INET, &ms->local); |
|
2154 |
+ int status; |
|
2155 |
+ int resolve_flags = GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL; |
|
2156 |
+ |
|
2157 |
+ if (! (flags & MF_CONNECT_AS_CLIENT)) |
|
2158 |
+ resolve_flags |= GETADDR_PASSIVE; |
|
2159 |
+ |
|
2160 |
+ status = openvpn_getaddrinfo (resolve_flags, addr, port, 0, |
|
2161 |
+ NULL, AF_UNSPEC, &ms->local); |
|
2156 | 2162 |
ASSERT(status==0); |
2157 | 2163 |
} |
2158 | 2164 |
} |
... | ... |
@@ -2179,6 +2185,8 @@ man_settings_init (struct man_settings *ms, |
2179 | 2179 |
static void |
2180 | 2180 |
man_settings_close (struct man_settings *ms) |
2181 | 2181 |
{ |
2182 |
+ if (ms->local) |
|
2183 |
+ freeaddrinfo(ms->local); |
|
2182 | 2184 |
free (ms->write_peer_info_file); |
2183 | 2185 |
CLEAR (*ms); |
2184 | 2186 |
} |
... | ... |
@@ -2616,7 +2624,7 @@ management_post_tunnel_open (struct management *man, const in_addr_t tun_local_i |
2616 | 2616 |
int ret; |
2617 | 2617 |
|
2618 | 2618 |
ia.s_addr = htonl(tun_local_ip); |
2619 |
- ret = openvpn_getaddrinfo(0, inet_ntoa(ia), NULL, 0, NULL, |
|
2619 |
+ ret = openvpn_getaddrinfo(GETADDR_PASSIVE, inet_ntoa(ia), NULL, 0, NULL, |
|
2620 | 2620 |
AF_INET, &man->settings.local); |
2621 | 2621 |
ASSERT (ret==0); |
2622 | 2622 |
man_connection_init (man); |
... | ... |
@@ -166,6 +166,9 @@ struct context_1 |
166 | 166 |
/* tunnel session keys */ |
167 | 167 |
struct key_schedule ks; |
168 | 168 |
|
169 |
+ /* preresolved and cached host names */ |
|
170 |
+ struct cached_dns_entry *dns_cache; |
|
171 |
+ |
|
169 | 172 |
/* persist crypto sequence number to/from file */ |
170 | 173 |
struct packet_id_persist pid_persist; |
171 | 174 |
|
... | ... |
@@ -796,6 +796,7 @@ init_options (struct options *o, const bool init_gc) |
796 | 796 |
o->ce.mssfix = MSSFIX_DEFAULT; |
797 | 797 |
o->route_delay_window = 30; |
798 | 798 |
o->resolve_retry_seconds = RESOLV_RETRY_INFINITE; |
799 |
+ o->resolve_in_advance = false; |
|
799 | 800 |
o->proto_force = -1; |
800 | 801 |
#ifdef ENABLE_OCC |
801 | 802 |
o->occ = true; |
... | ... |
@@ -1369,6 +1370,7 @@ show_connection_entry (const struct connection_entry *o) |
1369 | 1369 |
SHOW_BOOL (remote_float); |
1370 | 1370 |
SHOW_BOOL (bind_defined); |
1371 | 1371 |
SHOW_BOOL (bind_local); |
1372 |
+ SHOW_BOOL (bind_ipv6_only); |
|
1372 | 1373 |
SHOW_INT (connect_retry_seconds); |
1373 | 1374 |
SHOW_INT (connect_timeout); |
1374 | 1375 |
|
... | ... |
@@ -1494,6 +1496,7 @@ show_settings (const struct options *o) |
1494 | 1494 |
#endif |
1495 | 1495 |
|
1496 | 1496 |
SHOW_INT (resolve_retry_seconds); |
1497 |
+ SHOW_BOOL (resolve_in_advance); |
|
1497 | 1498 |
|
1498 | 1499 |
SHOW_STR (username); |
1499 | 1500 |
SHOW_STR (groupname); |
... | ... |
@@ -4540,6 +4543,15 @@ add_option (struct options *options, |
4540 | 4540 |
else |
4541 | 4541 |
options->resolve_retry_seconds = positive_atoi (p[1]); |
4542 | 4542 |
} |
4543 |
+ else if (streq (p[0], "preresolve") || streq (p[0], "ip-remote-hint")) |
|
4544 |
+ { |
|
4545 |
+ VERIFY_PERMISSION (OPT_P_GENERAL); |
|
4546 |
+ options->resolve_in_advance = true; |
|
4547 |
+ /* Note the ip-remote-hint and the argument p[1] are for |
|
4548 |
+ backward compatibility */ |
|
4549 |
+ if (p[1]) |
|
4550 |
+ options->ip_remote_hint=p[1]; |
|
4551 |
+ } |
|
4543 | 4552 |
else if (streq (p[0], "connect-retry") && p[1]) |
4544 | 4553 |
{ |
4545 | 4554 |
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION); |
... | ... |
@@ -90,7 +90,7 @@ struct connection_entry |
90 | 90 |
sa_family_t af; |
91 | 91 |
const char* local_port; |
92 | 92 |
bool local_port_defined; |
93 |
- const char* remote_port; |
|
93 |
+ const char *remote_port; |
|
94 | 94 |
const char *local; |
95 | 95 |
const char *remote; |
96 | 96 |
bool remote_float; |
... | ... |
@@ -278,6 +278,8 @@ struct options |
278 | 278 |
#endif |
279 | 279 |
|
280 | 280 |
int resolve_retry_seconds; /* If hostname resolve fails, retry for n seconds */ |
281 |
+ bool resolve_in_advance; |
|
282 |
+ const char *ip_remote_hint; |
|
281 | 283 |
|
282 | 284 |
struct tuntap_options tuntap_options; |
283 | 285 |
|
... | ... |
@@ -638,6 +638,7 @@ init_route_list (struct route_list *rl, |
638 | 638 |
else |
639 | 639 |
{ |
640 | 640 |
struct addrinfo* curele; |
641 |
+ gc_addspecial(netlist, &gc_freeaddrinfo_callback, &gc); |
|
641 | 642 |
for (curele = netlist; curele; curele = curele->ai_next) |
642 | 643 |
{ |
643 | 644 |
struct route_ipv4 *new; |
... | ... |
@@ -647,7 +648,6 @@ init_route_list (struct route_list *rl, |
647 | 647 |
new->next = rl->routes; |
648 | 648 |
rl->routes = new; |
649 | 649 |
} |
650 |
- freeaddrinfo(netlist); |
|
651 | 650 |
} |
652 | 651 |
} |
653 | 652 |
} |
... | ... |
@@ -39,6 +39,7 @@ |
39 | 39 |
#include "manage.h" |
40 | 40 |
#include "misc.h" |
41 | 41 |
#include "manage.h" |
42 |
+#include "openvpn.h" |
|
42 | 43 |
|
43 | 44 |
#include "memdbg.h" |
44 | 45 |
|
... | ... |
@@ -117,6 +118,178 @@ getaddr (unsigned int flags, |
117 | 117 |
} |
118 | 118 |
} |
119 | 119 |
|
120 |
+static inline bool |
|
121 |
+streqnull (const char* a, const char* b) |
|
122 |
+{ |
|
123 |
+ if (a == NULL && b == NULL) |
|
124 |
+ return true; |
|
125 |
+ else if (a == NULL || b == NULL) |
|
126 |
+ return false; |
|
127 |
+ else |
|
128 |
+ return streq (a, b); |
|
129 |
+} |
|
130 |
+ |
|
131 |
+/* |
|
132 |
+ get_cached_dns_entry return 0 on success and -1 |
|
133 |
+ otherwise. (like getaddrinfo) |
|
134 |
+ */ |
|
135 |
+static int |
|
136 |
+get_cached_dns_entry (struct cached_dns_entry* dns_cache, |
|
137 |
+ const char* hostname, |
|
138 |
+ const char* servname, |
|
139 |
+ int ai_family, |
|
140 |
+ int resolve_flags, |
|
141 |
+ struct addrinfo **ai) |
|
142 |
+{ |
|
143 |
+ struct cached_dns_entry *ph; |
|
144 |
+ int flags; |
|
145 |
+ |
|
146 |
+ /* Only use flags that are relevant for the structure */ |
|
147 |
+ flags = resolve_flags & GETADDR_CACHE_MASK; |
|
148 |
+ |
|
149 |
+ for (ph = dns_cache; ph ; ph = ph->next) |
|
150 |
+ { |
|
151 |
+ if (streqnull (ph->hostname, hostname) && |
|
152 |
+ streqnull (ph->servname, servname) && |
|
153 |
+ ph->ai_family == ai_family && |
|
154 |
+ ph->flags == flags) |
|
155 |
+ { |
|
156 |
+ *ai = ph->ai; |
|
157 |
+ return 0; |
|
158 |
+ } |
|
159 |
+ } |
|
160 |
+ return -1; |
|
161 |
+} |
|
162 |
+ |
|
163 |
+ |
|
164 |
+static int |
|
165 |
+do_preresolve_host (struct context *c, |
|
166 |
+ const char *hostname, |
|
167 |
+ const char *servname, |
|
168 |
+ const int af, |
|
169 |
+ const int flags) |
|
170 |
+{ |
|
171 |
+ struct addrinfo *ai; |
|
172 |
+ int status; |
|
173 |
+ |
|
174 |
+ if (get_cached_dns_entry(c->c1.dns_cache, |
|
175 |
+ hostname, |
|
176 |
+ servname, |
|
177 |
+ af, |
|
178 |
+ flags, |
|
179 |
+ &ai) == 0 ) |
|
180 |
+ { |
|
181 |
+ /* entry already cached, return success */ |
|
182 |
+ return 0; |
|
183 |
+ } |
|
184 |
+ |
|
185 |
+ status = openvpn_getaddrinfo (flags, hostname, servname, |
|
186 |
+ c->options.resolve_retry_seconds, NULL, |
|
187 |
+ af, &ai); |
|
188 |
+ if (status == 0) |
|
189 |
+ { |
|
190 |
+ struct cached_dns_entry *ph; |
|
191 |
+ |
|
192 |
+ ALLOC_OBJ_CLEAR_GC (ph, struct cached_dns_entry, &c->gc); |
|
193 |
+ ph->ai = ai; |
|
194 |
+ ph->hostname = hostname; |
|
195 |
+ ph->servname = servname; |
|
196 |
+ ph->flags = flags & GETADDR_CACHE_MASK; |
|
197 |
+ |
|
198 |
+ if (!c->c1.dns_cache) |
|
199 |
+ c->c1.dns_cache = ph; |
|
200 |
+ else |
|
201 |
+ { |
|
202 |
+ struct cached_dns_entry *prev = c->c1.dns_cache; |
|
203 |
+ while (prev->next) |
|
204 |
+ prev = prev->next; |
|
205 |
+ prev->next = ph; |
|
206 |
+ } |
|
207 |
+ |
|
208 |
+ gc_addspecial (ai, &gc_freeaddrinfo_callback, &c->gc); |
|
209 |
+ |
|
210 |
+ } |
|
211 |
+ return status; |
|
212 |
+} |
|
213 |
+ |
|
214 |
+void |
|
215 |
+do_preresolve (struct context *c) |
|
216 |
+{ |
|
217 |
+ int i; |
|
218 |
+ struct connection_list *l = c->options.connection_list; |
|
219 |
+ const unsigned int preresolve_flags = GETADDR_RESOLVE| |
|
220 |
+ GETADDR_UPDATE_MANAGEMENT_STATE| |
|
221 |
+ GETADDR_MENTION_RESOLVE_RETRY| |
|
222 |
+ GETADDR_FATAL; |
|
223 |
+ |
|
224 |
+ |
|
225 |
+ for (i = 0; i < l->len; ++i) |
|
226 |
+ { |
|
227 |
+ int status; |
|
228 |
+ const char *remote; |
|
229 |
+ int flags = preresolve_flags; |
|
230 |
+ |
|
231 |
+ struct connection_entry* ce = c->options.connection_list->array[i]; |
|
232 |
+ |
|
233 |
+ if (proto_is_dgram(ce->proto)) |
|
234 |
+ flags |= GETADDR_DATAGRAM; |
|
235 |
+ |
|
236 |
+ if (c->options.sockflags & SF_HOST_RANDOMIZE) |
|
237 |
+ flags |= GETADDR_RANDOMIZE; |
|
238 |
+ |
|
239 |
+ if (c->options.ip_remote_hint) |
|
240 |
+ remote = c->options.ip_remote_hint; |
|
241 |
+ else |
|
242 |
+ remote = ce->remote; |
|
243 |
+ |
|
244 |
+ /* HTTP remote hostname does not need to be resolved */ |
|
245 |
+ if (! ce->http_proxy_options) |
|
246 |
+ { |
|
247 |
+ status = do_preresolve_host (c, remote, ce->remote_port, ce->af, flags); |
|
248 |
+ if (status != 0) |
|
249 |
+ goto err; |
|
250 |
+ } |
|
251 |
+ |
|
252 |
+ /* Preresolve proxy */ |
|
253 |
+ if (ce->http_proxy_options) |
|
254 |
+ { |
|
255 |
+ status = do_preresolve_host (c, |
|
256 |
+ ce->http_proxy_options->server, |
|
257 |
+ ce->http_proxy_options->port, |
|
258 |
+ ce->af, |
|
259 |
+ preresolve_flags); |
|
260 |
+ |
|
261 |
+ if (status != 0) |
|
262 |
+ goto err; |
|
263 |
+ } |
|
264 |
+ |
|
265 |
+ if (ce->socks_proxy_server) |
|
266 |
+ { |
|
267 |
+ status = do_preresolve_host (c, |
|
268 |
+ ce->socks_proxy_server, |
|
269 |
+ ce->socks_proxy_port, |
|
270 |
+ ce->af, |
|
271 |
+ flags); |
|
272 |
+ if (status != 0) |
|
273 |
+ goto err; |
|
274 |
+ } |
|
275 |
+ |
|
276 |
+ if (ce->bind_local) |
|
277 |
+ { |
|
278 |
+ flags |= GETADDR_PASSIVE; |
|
279 |
+ flags &= ~GETADDR_RANDOMIZE; |
|
280 |
+ status = do_preresolve_host (c, ce->local, ce->local_port, ce->af, flags); |
|
281 |
+ if (status != 0) |
|
282 |
+ goto err; |
|
283 |
+ |
|
284 |
+ } |
|
285 |
+ |
|
286 |
+ } |
|
287 |
+ return; |
|
288 |
+ |
|
289 |
+ err: |
|
290 |
+ throw_signal_soft (SIGHUP, "Preresolving failed"); |
|
291 |
+} |
|
120 | 292 |
|
121 | 293 |
/* |
122 | 294 |
* Translate IPv4/IPv6 addr or hostname into struct addrinfo |
... | ... |
@@ -1155,7 +1328,15 @@ resolve_bind_local (struct link_socket *sock, const sa_family_t af) |
1155 | 1155 |
flags |= GETADDR_DATAGRAM; |
1156 | 1156 |
|
1157 | 1157 |
/* will return AF_{INET|INET6}from local_host */ |
1158 |
- status = openvpn_getaddrinfo(flags, sock->local_host, sock->local_port, 0, |
|
1158 |
+ status = get_cached_dns_entry (sock->dns_cache, |
|
1159 |
+ sock->local_host, |
|
1160 |
+ sock->local_port, |
|
1161 |
+ af, |
|
1162 |
+ flags, |
|
1163 |
+ &sock->info.lsa->bind_local); |
|
1164 |
+ |
|
1165 |
+ if (status) |
|
1166 |
+ status = openvpn_getaddrinfo(flags, sock->local_host, sock->local_port, 0, |
|
1159 | 1167 |
NULL, af, &sock->info.lsa->bind_local); |
1160 | 1168 |
|
1161 | 1169 |
if(status !=0) { |
... | ... |
@@ -1193,103 +1374,104 @@ resolve_remote (struct link_socket *sock, |
1193 | 1193 |
{ |
1194 | 1194 |
struct gc_arena gc = gc_new (); |
1195 | 1195 |
|
1196 |
- if (!sock->did_resolve_remote) |
|
1196 |
+ /* resolve remote address if undefined */ |
|
1197 |
+ if (!sock->info.lsa->remote_list) |
|
1197 | 1198 |
{ |
1198 |
- /* resolve remote address if undefined */ |
|
1199 |
- if (!sock->info.lsa->remote_list) |
|
1199 |
+ if (sock->remote_host) |
|
1200 | 1200 |
{ |
1201 |
- if (sock->remote_host) |
|
1201 |
+ unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags); |
|
1202 |
+ int retry = 0; |
|
1203 |
+ int status = -1; |
|
1204 |
+ struct addrinfo* ai; |
|
1205 |
+ if (proto_is_dgram(sock->info.proto)) |
|
1206 |
+ flags |= GETADDR_DATAGRAM; |
|
1207 |
+ |
|
1208 |
+ if (sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE) |
|
1209 |
+ { |
|
1210 |
+ if (phase == 2) |
|
1211 |
+ flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL); |
|
1212 |
+ retry = 0; |
|
1213 |
+ } |
|
1214 |
+ else if (phase == 1) |
|
1202 | 1215 |
{ |
1203 |
- unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags); |
|
1204 |
- int retry = 0; |
|
1205 |
- int status = -1; |
|
1206 |
- struct addrinfo* ai; |
|
1207 |
- if (proto_is_dgram(sock->info.proto)) |
|
1208 |
- flags |= GETADDR_DATAGRAM; |
|
1209 |
- |
|
1210 |
- if (sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE) |
|
1216 |
+ if (sock->resolve_retry_seconds) |
|
1211 | 1217 |
{ |
1212 |
- if (phase == 2) |
|
1213 |
- flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL); |
|
1214 | 1218 |
retry = 0; |
1215 | 1219 |
} |
1216 |
- else if (phase == 1) |
|
1220 |
+ else |
|
1217 | 1221 |
{ |
1218 |
- if (sock->resolve_retry_seconds) |
|
1219 |
- { |
|
1220 |
- retry = 0; |
|
1221 |
- } |
|
1222 |
- else |
|
1223 |
- { |
|
1224 |
- flags |= (GETADDR_FATAL | GETADDR_MENTION_RESOLVE_RETRY); |
|
1225 |
- retry = 0; |
|
1226 |
- } |
|
1222 |
+ flags |= (GETADDR_FATAL | GETADDR_MENTION_RESOLVE_RETRY); |
|
1223 |
+ retry = 0; |
|
1227 | 1224 |
} |
1228 |
- else if (phase == 2) |
|
1225 |
+ } |
|
1226 |
+ else if (phase == 2) |
|
1227 |
+ { |
|
1228 |
+ if (sock->resolve_retry_seconds) |
|
1229 | 1229 |
{ |
1230 |
- if (sock->resolve_retry_seconds) |
|
1231 |
- { |
|
1232 |
- flags |= GETADDR_FATAL; |
|
1233 |
- retry = sock->resolve_retry_seconds; |
|
1234 |
- } |
|
1235 |
- else |
|
1236 |
- { |
|
1237 |
- ASSERT (0); |
|
1238 |
- } |
|
1230 |
+ flags |= GETADDR_FATAL; |
|
1231 |
+ retry = sock->resolve_retry_seconds; |
|
1239 | 1232 |
} |
1240 | 1233 |
else |
1241 | 1234 |
{ |
1242 | 1235 |
ASSERT (0); |
1243 | 1236 |
} |
1237 |
+ } |
|
1238 |
+ else |
|
1239 |
+ { |
|
1240 |
+ ASSERT (0); |
|
1241 |
+ } |
|
1244 | 1242 |
|
1245 |
- status = openvpn_getaddrinfo (flags, sock->remote_host, sock->remote_port, |
|
1246 |
- retry, signal_received, sock->info.af, &ai); |
|
1247 |
- |
|
1248 |
- if(status == 0) { |
|
1249 |
- sock->info.lsa->remote_list = ai; |
|
1250 |
- sock->info.lsa->current_remote = ai; |
|
1251 |
- |
|
1252 |
- dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", |
|
1253 |
- flags, |
|
1254 |
- phase, |
|
1255 |
- retry, |
|
1256 |
- signal_received ? *signal_received : -1, |
|
1257 |
- status); |
|
1258 |
- } |
|
1259 |
- if (signal_received) |
|
1260 |
- { |
|
1261 |
- if (*signal_received) |
|
1262 |
- goto done; |
|
1263 |
- } |
|
1243 |
+ |
|
1244 |
+ status = get_cached_dns_entry (sock->dns_cache, |
|
1245 |
+ sock->remote_host, |
|
1246 |
+ sock->remote_port, |
|
1247 |
+ sock->info.af, |
|
1248 |
+ flags, &ai); |
|
1249 |
+ if (status) |
|
1250 |
+ status = openvpn_getaddrinfo (flags, sock->remote_host, sock->remote_port, |
|
1251 |
+ retry, signal_received, sock->info.af, &ai); |
|
1252 |
+ |
|
1253 |
+ if(status == 0) { |
|
1254 |
+ sock->info.lsa->remote_list = ai; |
|
1255 |
+ sock->info.lsa->current_remote = ai; |
|
1256 |
+ |
|
1257 |
+ dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", |
|
1258 |
+ flags, |
|
1259 |
+ phase, |
|
1260 |
+ retry, |
|
1261 |
+ signal_received ? *signal_received : -1, |
|
1262 |
+ status); |
|
1263 |
+ } |
|
1264 |
+ if (signal_received) |
|
1265 |
+ { |
|
1266 |
+ if (*signal_received) |
|
1267 |
+ goto done; |
|
1268 |
+ } |
|
1264 | 1269 |
if (status!=0) |
1265 | 1270 |
{ |
1266 | 1271 |
if (signal_received) |
1267 | 1272 |
*signal_received = SIGUSR1; |
1268 | 1273 |
goto done; |
1269 | 1274 |
} |
1270 |
- } |
|
1271 | 1275 |
} |
1276 |
+ } |
|
1272 | 1277 |
|
1273 |
- /* should we re-use previous active remote address? */ |
|
1274 |
- if (link_socket_actual_defined (&sock->info.lsa->actual)) |
|
1275 |
- { |
|
1276 |
- msg (M_INFO, "TCP/UDP: Preserving recently used remote address: %s", |
|
1277 |
- print_link_socket_actual (&sock->info.lsa->actual, &gc)); |
|
1278 |
- if (remote_dynamic) |
|
1279 |
- *remote_dynamic = NULL; |
|
1280 |
- } |
|
1281 |
- else |
|
1278 |
+ /* should we re-use previous active remote address? */ |
|
1279 |
+ if (link_socket_actual_defined (&sock->info.lsa->actual)) |
|
1280 |
+ { |
|
1281 |
+ msg (M_INFO, "TCP/UDP: Preserving recently used remote address: %s", |
|
1282 |
+ print_link_socket_actual (&sock->info.lsa->actual, &gc)); |
|
1283 |
+ if (remote_dynamic) |
|
1284 |
+ *remote_dynamic = NULL; |
|
1285 |
+ } |
|
1286 |
+ else |
|
1287 |
+ { |
|
1288 |
+ CLEAR (sock->info.lsa->actual); |
|
1289 |
+ if(sock->info.lsa->current_remote) |
|
1282 | 1290 |
{ |
1283 |
- CLEAR (sock->info.lsa->actual); |
|
1284 |
- if(sock->info.lsa->current_remote) |
|
1285 |
- { |
|
1286 |
- set_actual_address (&sock->info.lsa->actual, |
|
1287 |
- sock->info.lsa->current_remote); |
|
1288 |
- } |
|
1291 |
+ set_actual_address (&sock->info.lsa->actual, |
|
1292 |
+ sock->info.lsa->current_remote); |
|
1289 | 1293 |
} |
1290 |
- |
|
1291 |
- /* remember that we finished */ |
|
1292 |
- sock->did_resolve_remote = true; |
|
1293 | 1294 |
} |
1294 | 1295 |
|
1295 | 1296 |
done: |
... | ... |
@@ -1341,6 +1523,7 @@ create_new_socket (struct link_socket* sock) |
1341 | 1341 |
if (sock->bind_local) |
1342 | 1342 |
bind_local(sock); |
1343 | 1343 |
} |
1344 |
+ |
|
1344 | 1345 |
} |
1345 | 1346 |
|
1346 | 1347 |
|
... | ... |
@@ -1351,6 +1534,7 @@ link_socket_init_phase1 (struct link_socket *sock, |
1351 | 1351 |
const char *local_port, |
1352 | 1352 |
const char *remote_host, |
1353 | 1353 |
const char *remote_port, |
1354 |
+ struct cached_dns_entry *dns_cache, |
|
1354 | 1355 |
int proto, |
1355 | 1356 |
sa_family_t af, |
1356 | 1357 |
bool bind_ipv6_only, |
... | ... |
@@ -1385,6 +1569,7 @@ link_socket_init_phase1 (struct link_socket *sock, |
1385 | 1385 |
sock->local_port = local_port; |
1386 | 1386 |
sock->remote_host = remote_host; |
1387 | 1387 |
sock->remote_port = remote_port; |
1388 |
+ sock->dns_cache = dns_cache; |
|
1388 | 1389 |
|
1389 | 1390 |
#ifdef ENABLE_HTTP_PROXY |
1390 | 1391 |
sock->http_proxy = http_proxy; |
... | ... |
@@ -1564,33 +1749,33 @@ linksock_print_addr (struct link_socket *sock) |
1564 | 1564 |
const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? D_INIT_MEDIUM : M_INFO; |
1565 | 1565 |
|
1566 | 1566 |
/* print local address */ |
1567 |
- if (sock->inetd) |
|
1567 |
+ if (sock->inetd) |
|
1568 | 1568 |
msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, sock->info.af, true)); |
1569 |
- else if (sock->bind_local) |
|
1570 |
- { |
|
1571 |
- /* Socket is always bound on the first matching address */ |
|
1572 |
- struct addrinfo *cur; |
|
1573 |
- for (cur = sock->info.lsa->bind_local; cur; cur=cur->ai_next) |
|
1574 |
- { |
|
1575 |
- if(cur->ai_family == sock->info.lsa->actual.ai_family) |
|
1576 |
- break; |
|
1577 |
- } |
|
1578 |
- ASSERT (cur); |
|
1579 |
- msg (msglevel, "%s link local (bound): %s", |
|
1569 |
+ else if (sock->bind_local) |
|
1570 |
+ { |
|
1571 |
+ /* Socket is always bound on the first matching address */ |
|
1572 |
+ struct addrinfo *cur; |
|
1573 |
+ for (cur = sock->info.lsa->bind_local; cur; cur=cur->ai_next) |
|
1574 |
+ { |
|
1575 |
+ if(cur->ai_family == sock->info.lsa->actual.ai_family) |
|
1576 |
+ break; |
|
1577 |
+ } |
|
1578 |
+ ASSERT (cur); |
|
1579 |
+ msg (msglevel, "%s link local (bound): %s", |
|
1580 | 1580 |
proto2ascii (sock->info.proto, sock->info.af, true), |
1581 | 1581 |
print_sockaddr(cur->ai_addr,&gc)); |
1582 |
- } |
|
1583 |
- else |
|
1584 |
- msg (msglevel, "%s link local: (not bound)", |
|
1585 |
- proto2ascii (sock->info.proto, sock->info.af, true)); |
|
1582 |
+ } |
|
1583 |
+ else |
|
1584 |
+ msg (msglevel, "%s link local: (not bound)", |
|
1585 |
+ proto2ascii (sock->info.proto, sock->info.af, true)); |
|
1586 | 1586 |
|
1587 | 1587 |
/* print active remote address */ |
1588 | 1588 |
msg (msglevel, "%s link remote: %s", |
1589 |
- proto2ascii (sock->info.proto, sock->info.af, true), |
|
1590 |
- print_link_socket_actual_ex (&sock->info.lsa->actual, |
|
1591 |
- ":", |
|
1592 |
- PS_SHOW_PORT_IF_DEFINED, |
|
1593 |
- &gc)); |
|
1589 |
+ proto2ascii (sock->info.proto, sock->info.af, true), |
|
1590 |
+ print_link_socket_actual_ex (&sock->info.lsa->actual, |
|
1591 |
+ ":", |
|
1592 |
+ PS_SHOW_PORT_IF_DEFINED, |
|
1593 |
+ &gc)); |
|
1594 | 1594 |
gc_free(&gc); |
1595 | 1595 |
} |
1596 | 1596 |
|
... | ... |
@@ -1707,7 +1892,6 @@ phase2_socks_client (struct link_socket *sock, struct signal_info *sig_info) |
1707 | 1707 |
|
1708 | 1708 |
sock->remote_host = sock->proxy_dest_host; |
1709 | 1709 |
sock->remote_port = sock->proxy_dest_port; |
1710 |
- sock->did_resolve_remote = false; |
|
1711 | 1710 |
|
1712 | 1711 |
addr_zero_host(&sock->info.lsa->actual.dest); |
1713 | 1712 |
if (sock->info.lsa->remote_list) |
... | ... |
@@ -2579,30 +2763,6 @@ proto2ascii_all (struct gc_arena *gc) |
2579 | 2579 |
return BSTR (&out); |
2580 | 2580 |
} |
2581 | 2581 |
|
2582 |
-int |
|
2583 |
-addr_guess_family(sa_family_t af, const char *name) |
|
2584 |
-{ |
|
2585 |
- unsigned short ret; |
|
2586 |
- if (af) |
|
2587 |
- { |
|
2588 |
- return af; /* already stamped */ |
|
2589 |
- } |
|
2590 |
- else |
|
2591 |
- { |
|
2592 |
- struct addrinfo hints , *ai; |
|
2593 |
- int err; |
|
2594 |
- CLEAR(hints); |
|
2595 |
- hints.ai_flags = AI_NUMERICHOST; |
|
2596 |
- err = getaddrinfo(name, NULL, &hints, &ai); |
|
2597 |
- if ( 0 == err ) |
|
2598 |
- { |
|
2599 |
- ret=ai->ai_family; |
|
2600 |
- freeaddrinfo(ai); |
|
2601 |
- return ret; |
|
2602 |
- } |
|
2603 |
- } |
|
2604 |
- return AF_INET; /* default */ |
|
2605 |
-} |
|
2606 | 2582 |
const char * |
2607 | 2583 |
addr_family_name (int af) |
2608 | 2584 |
{ |
... | ... |
@@ -77,6 +77,16 @@ struct openvpn_sockaddr |
77 | 77 |
} addr; |
78 | 78 |
}; |
79 | 79 |
|
80 |
+/* struct to hold preresolved host names */ |
|
81 |
+struct cached_dns_entry { |
|
82 |
+ const char *hostname; |
|
83 |
+ const char *servname; |
|
84 |
+ int ai_family; |
|
85 |
+ int flags; |
|
86 |
+ struct addrinfo *ai; |
|
87 |
+ struct cached_dns_entry *next; |
|
88 |
+}; |
|
89 |
+ |
|
80 | 90 |
/* actual address of remote, based on source address of received packets */ |
81 | 91 |
struct link_socket_actual |
82 | 92 |
{ |
... | ... |
@@ -188,6 +198,7 @@ struct link_socket |
188 | 188 |
const char *remote_port; |
189 | 189 |
const char *local_host; |
190 | 190 |
const char *local_port; |
191 |
+ struct cached_dns_entry *dns_cache; |
|
191 | 192 |
bool bind_local; |
192 | 193 |
|
193 | 194 |
# define INETD_NONE 0 |
... | ... |
@@ -208,8 +219,6 @@ struct link_socket |
208 | 208 |
|
209 | 209 |
int mtu; /* OS discovered MTU, or 0 if unknown */ |
210 | 210 |
|
211 |
- bool did_resolve_remote; |
|
212 |
- |
|
213 | 211 |
# define SF_USE_IP_PKTINFO (1<<0) |
214 | 212 |
# define SF_TCP_NODELAY (1<<1) |
215 | 213 |
# define SF_PORT_SHARE (1<<2) |
... | ... |
@@ -298,6 +307,8 @@ int openvpn_connect (socket_descriptor_t sd, |
298 | 298 |
int connect_timeout, |
299 | 299 |
volatile int *signal_received); |
300 | 300 |
|
301 |
+ |
|
302 |
+ |
|
301 | 303 |
/* |
302 | 304 |
* Initialize link_socket object. |
303 | 305 |
*/ |
... | ... |
@@ -308,6 +319,7 @@ link_socket_init_phase1 (struct link_socket *sock, |
308 | 308 |
const char *local_port, |
309 | 309 |
const char *remote_host, |
310 | 310 |
const char *remote_port, |
311 |
+ struct cached_dns_entry *dns_cache, |
|
311 | 312 |
int proto, |
312 | 313 |
sa_family_t af, |
313 | 314 |
bool bind_ipv6_only, |
... | ... |
@@ -340,6 +352,8 @@ void link_socket_init_phase2 (struct link_socket *sock, |
340 | 340 |
const struct frame *frame, |
341 | 341 |
struct signal_info *sig_info); |
342 | 342 |
|
343 |
+void do_preresolve(struct context *c); |
|
344 |
+ |
|
343 | 345 |
void socket_adjust_frame_parameters (struct frame *frame, int proto); |
344 | 346 |
|
345 | 347 |
void frame_adjust_path_mtu (struct frame *frame, int pmtu, int proto); |
... | ... |
@@ -514,6 +528,8 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int * |
514 | 514 |
#define GETADDR_PASSIVE (1<<10) |
515 | 515 |
#define GETADDR_DATAGRAM (1<<11) |
516 | 516 |
|
517 |
+#define GETADDR_CACHE_MASK GETADDR_DATAGRAM|GETADDR_PASSIVE |
|
518 |
+ |
|
517 | 519 |
in_addr_t getaddr (unsigned int flags, |
518 | 520 |
const char *hostname, |
519 | 521 |
int resolve_retry_seconds, |