From f5b64019421396f59654984838b567afd19b01cf Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Sun, 8 Dec 2013 15:06:24 +0100 Subject: Update pre resolve patch --- openvpn/src/openvpn/buffer.c | 38 ++++++++++++++++++++++++++++++ openvpn/src/openvpn/buffer.h | 28 ++++++++++++++++++++-- openvpn/src/openvpn/init.c | 18 +++++++++------ openvpn/src/openvpn/manage.c | 18 +++++++++++---- openvpn/src/openvpn/route.c | 2 +- openvpn/src/openvpn/socket.c | 55 ++++++++++++++------------------------------ 6 files changed, 106 insertions(+), 53 deletions(-) (limited to 'openvpn/src') diff --git a/openvpn/src/openvpn/buffer.c b/openvpn/src/openvpn/buffer.c index fb3b52d1..36611415 100644 --- a/openvpn/src/openvpn/buffer.c +++ b/openvpn/src/openvpn/buffer.c @@ -371,6 +371,44 @@ x_gc_free (struct gc_arena *a) } } +/* + * Functions to handle special objects in gc_entries + */ + +void +x_gc_freespecial (struct gc_arena *a) +{ + struct gc_entry_special *e; + e = a->list_special; + a->list_special = NULL; + + while (e != NULL) + { + struct gc_entry_special *next = e->next; + e->free_fnc (e->addr); + free(e); + e = next; + } +} + +void gc_addspecial (void *addr, void (free_function)(void*), struct gc_arena *a) +{ + ASSERT(a); + struct gc_entry_special *e; +#ifdef DMALLOC + e = (struct gc_entry_special *) openvpn_dmalloc (file, line, sizeof (struct gc_entry_special)); +#else + e = (struct gc_entry_special *) malloc (sizeof (struct gc_entry_special)); +#endif + check_malloc_return (e); + e->free_fnc = free_function; + e->addr = addr; + + e->next = a->list_special; + a->list_special = e; +} + + /* * Transfer src arena to dest, resetting src to an empty arena. */ diff --git a/openvpn/src/openvpn/buffer.h b/openvpn/src/openvpn/buffer.h index 93efb096..425d0eb6 100644 --- a/openvpn/src/openvpn/buffer.h +++ b/openvpn/src/openvpn/buffer.h @@ -91,6 +91,18 @@ struct gc_entry * linked list. */ }; +/** + * Gargabe collection entry for a specially allocated structure that needs + * a custom free function to be freed like struct addrinfo + * + */ +struct gc_entry_special +{ + struct gc_entry_special *next; + void (*free_fnc)(void*); + void *addr; +}; + /** * Garbage collection arena used to keep track of dynamically allocated @@ -106,6 +118,7 @@ struct gc_arena { struct gc_entry *list; /**< First element of the linked list of * \c gc_entry structures. */ + struct gc_entry_special *list_special; }; @@ -153,7 +166,6 @@ char *string_alloc_debug (const char *str, struct gc_arena *gc, const char *file struct buffer string_alloc_buf_debug (const char *str, struct gc_arena *gc, const char *file, int line); #else - struct buffer alloc_buf (size_t size); struct buffer alloc_buf_gc (size_t size, struct gc_arena *gc); /* allocate buffer with garbage collection */ struct buffer clone_buf (const struct buffer* buf); @@ -163,6 +175,9 @@ struct buffer string_alloc_buf (const char *str, struct gc_arena *gc); #endif +void gc_addspecial (void *addr, void (*free_function)(void*), struct gc_arena *a); + + #ifdef BUF_INIT_TRACKING #define buf_init(buf, offset) buf_init_debug (buf, offset, __FILE__, __LINE__) bool buf_init_debug (struct buffer *buf, int offset, const char *file, int line); @@ -172,6 +187,11 @@ bool buf_init_debug (struct buffer *buf, int offset, const char *file, int line) /* inline functions */ +inline static void +gc_freeaddrinfo_callback (void *addr) +{ + freeaddrinfo((struct addrinfo*) addr); +} static inline bool buf_defined (const struct buffer *buf) @@ -778,6 +798,7 @@ void character_class_debug (void); void gc_transfer (struct gc_arena *dest, struct gc_arena *src); void x_gc_free (struct gc_arena *a); +void x_gc_freespecial (struct gc_arena *a); static inline bool gc_defined (struct gc_arena *a) @@ -789,6 +810,7 @@ static inline void gc_init (struct gc_arena *a) { a->list = NULL; + a->list_special = NULL; } static inline void @@ -801,7 +823,7 @@ static inline struct gc_arena gc_new (void) { struct gc_arena ret; - ret.list = NULL; + gc_init (&ret); return ret; } @@ -810,6 +832,8 @@ gc_free (struct gc_arena *a) { if (a->list) x_gc_free (a); + if (a->list_special) + x_gc_freespecial(a); } static inline void diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c index 5979e0bb..0f76b2cc 100644 --- a/openvpn/src/openvpn/init.c +++ b/openvpn/src/openvpn/init.c @@ -306,11 +306,10 @@ init_connection_list (struct context *c) /* * Clear the remote address list */ -static void clear_remote_addrlist (struct link_socket_addr *lsa, bool freeaddr) +static void clear_remote_addrlist (struct link_socket_addr *lsa, bool free) { - if (lsa->remote_list && freeaddr) { - freeaddrinfo(lsa->remote_list); - } + if (lsa->remote_list && free) + freeaddrinfo(lsa->remote_list); lsa->remote_list = NULL; lsa->current_remote = NULL; } @@ -349,11 +348,15 @@ next_connection_entry (struct context *c) * remote existed */ if (!c->options.persist_remote_ip) - clear_remote_addrlist (&c->c1.link_socket_addr, !c->options.resolve_in_advance); + { + /* close_instance should have cleared the addrinfo objects */ + ASSERT (c->c1.link_socket_addr.current_remote == NULL); + ASSERT (c->c1.link_socket_addr.remote_list == NULL); + } else c->c1.link_socket_addr.current_remote = c->c1.link_socket_addr.remote_list; - + /* * Increase the number of connection attempts * If this is connect-retry-max * size(l) @@ -2920,7 +2923,8 @@ do_close_link_socket (struct context *c) if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_local_ip)) { if (c->c1.link_socket_addr.bind_local && !c->options.resolve_in_advance) - freeaddrinfo(c->c1.link_socket_addr.bind_local); + freeaddrinfo(c->c1.link_socket_addr.bind_local); + c->c1.link_socket_addr.bind_local=NULL; } } diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c index 352021bd..06965ad2 100644 --- a/openvpn/src/openvpn/manage.c +++ b/openvpn/src/openvpn/manage.c @@ -1568,9 +1568,9 @@ man_listen (struct management *man) else #endif { - man->connection.sd_top = create_socket_tcp (AF_INET); + man->connection.sd_top = create_socket_tcp (man->settings.local->ai_family); socket_bind (man->connection.sd_top, man->settings.local, - AF_INET, "MANAGEMENT", true); + man->settings.local->ai_family, "MANAGEMENT", false); } /* @@ -2148,8 +2148,14 @@ man_settings_init (struct man_settings *ms, } else { - int status = openvpn_getaddrinfo(GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, - addr, port, 0, NULL, AF_INET, &ms->local); + int status; + int resolve_flags = GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL; + + if (! (flags & MF_CONNECT_AS_CLIENT)) + resolve_flags |= GETADDR_PASSIVE; + + status = openvpn_getaddrinfo (resolve_flags, addr, port, 0, + NULL, AF_UNSPEC, &ms->local); ASSERT(status==0); } } @@ -2176,6 +2182,8 @@ man_settings_init (struct man_settings *ms, static void man_settings_close (struct man_settings *ms) { + if (ms->local) + freeaddrinfo(ms->local); free (ms->write_peer_info_file); CLEAR (*ms); } @@ -2613,7 +2621,7 @@ management_post_tunnel_open (struct management *man, const in_addr_t tun_local_i int ret; ia.s_addr = htonl(tun_local_ip); - ret = openvpn_getaddrinfo(0, inet_ntoa(ia), NULL, 0, NULL, + ret = openvpn_getaddrinfo(GETADDR_PASSIVE, inet_ntoa(ia), NULL, 0, NULL, AF_INET, &man->settings.local); ASSERT (ret==0); man_connection_init (man); diff --git a/openvpn/src/openvpn/route.c b/openvpn/src/openvpn/route.c index f051dd3c..81ffa876 100644 --- a/openvpn/src/openvpn/route.c +++ b/openvpn/src/openvpn/route.c @@ -659,6 +659,7 @@ init_route_list (struct route_list *rl, else { struct addrinfo* curele; + gc_addspecial(netlist, &gc_freeaddrinfo_callback, &gc); for (curele = netlist; curele; curele = curele->ai_next) { if (j < rl->capacity) @@ -675,7 +676,6 @@ init_route_list (struct route_list *rl, } } } - freeaddrinfo(netlist); } } rl->n = j; diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 05ae9e91..26ef14c3 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -146,30 +146,33 @@ do_preresolve(struct context *c) if (! ce->preresolved_remote) { - status = openvpn_getaddrinfo (flags, remote, ce->remote_port, - c->options.resolve_retry_seconds, NULL, - ce->af, &ce->preresolved_remote); + status = openvpn_getaddrinfo (flags, remote, ce->remote_port, + c->options.resolve_retry_seconds, NULL, + ce->af, &ce->preresolved_remote); - if (status != 0) - goto err; + if (status != 0) + goto err; + gc_addspecial (ce->preresolved_remote, &gc_freeaddrinfo_callback, &c->gc); } flags |= GETADDR_PASSIVE; - if (ce->bind_local && !ce->preresolved_local) - { - status = openvpn_getaddrinfo (flags, ce->local, ce->local_port, - c->options.resolve_retry_seconds, NULL, - ce->af, &ce->preresolved_local); + if (ce->bind_local && !ce->preresolved_local) + { + status = openvpn_getaddrinfo (flags, ce->local, ce->local_port, + c->options.resolve_retry_seconds, NULL, + ce->af, &ce->preresolved_local); + + if (status != 0) + goto err; + gc_addspecial (ce->preresolved_local, &gc_freeaddrinfo_callback, &c->gc); - if (status != 0) - goto err; } } return; - err: - throw_signal_soft (SIGUSR1, "Preresolving failed"); + err: + throw_signal_soft (SIGHUP, "Preresolving failed"); } /* @@ -2640,30 +2643,6 @@ proto2ascii_all (struct gc_arena *gc) return BSTR (&out); } -int -addr_guess_family(sa_family_t af, const char *name) -{ - unsigned short ret; - if (af) - { - return af; /* already stamped */ - } - else - { - struct addrinfo hints , *ai; - int err; - CLEAR(hints); - hints.ai_flags = AI_NUMERICHOST; - err = getaddrinfo(name, NULL, &hints, &ai); - if ( 0 == err ) - { - ret=ai->ai_family; - freeaddrinfo(ai); - return ret; - } - } - return AF_INET; /* default */ -} const char * addr_family_name (int af) { -- cgit v1.2.3