Opened 8 years ago

Closed 8 years ago

#523 closed Bug / Defect (fixed)

OpenVPN doesn't pickup changes to /etc/resolv.conf

Reported by: ngharo Owned by:
Priority: minor Milestone: release 2.3.7
Component: Generic / unclassified Version: OpenVPN git master branch (Community Ed)
Severity: Not set (select this one, unless your'e a OpenVPN developer) Keywords: dns resolv res_init glibc
Cc: plaisthos


OpenVPN appears to only call res_init() once per entry of function call openvpn_getaddrinfo().

When resolv-retry is infinite, it appears that the loop in openvpn_getaddrinfo() is never broken and thus any changes to /etc/resolv.conf to correct the problem is never picked up.

This is a well documented bug across other OSS projects:

To reproduce:
Prereq: Make sure no glibc (nscd) or other DNS caching is enabled
1) Stop openvpn
2) Insert bogus nameservers into /etc/resolv.conf
3) Start openvpn with resolv-retry infinite
4) Observe repeating name resolution failures in openvpn logs
5) Insert legitimate nameservers into /etc/resolv.conf
6) Verify name resolution now works by pinging remote hostname
7) Observe how OpenVPN never recovers from name resolution failures

Attachments (1)

0001-Fix-autotools-check-for-res_init.patch (1.7 KB) - added by ngharo 8 years ago.

Download all attachments as: .zip

Change History (10)

comment:1 Changed 8 years ago by ngharo

Upon further investigation, x64 ./configure against Debian 8 and LFS 7.4 fail to find support for res_init. I think the symbol is called __res_init and a macro defines res_init in libresolve... Possibly the autotools check for res_init is suspect.

Changed 8 years ago by ngharo

comment:2 in reply to:  1 Changed 8 years ago by ngharo

This patch fixes the autotools check for res_init support.

This fixes the original problem described. I think it looks good but I'm a novice at autotools so there's that :)

comment:3 Changed 8 years ago by Gert Döring

I'm truly not an autotools expert, but decided to google around and use something similar to what the cups people do - just find the different variants (_ _res_init, res_9_init, res_init) in the usual places (nothing, -lresolv, -lbind) and link that - and the code now assumes "it is always there!" so if configure fails to find it, we'll notice, instead of silently assuming "this platform doesn't have it".

Patch on

Last edited 8 years ago by Gert Döring (previous) (diff)

comment:4 Changed 8 years ago by Gert Döring

#303 is likely a duplicate of this one ("getaddrinfo() not picking up new resolvers after network change, on Linux"). Closing the other one, keeping this one until the patch is merged.

comment:5 Changed 8 years ago by Gert Döring

Milestone: release 2.3.7

Uh. If I read this right, it's actually two bugs - res_init() not being found by configure, and openvpn_getaddrinfo() looping forever without calling res_init(), even *if* it was found?

How annoying, and needs to be fixed for 2.3.7

comment:6 Changed 8 years ago by Gert Döring

Cc: plaisthos added

Arne, can you have a quick look at openvpn_getaddrinfo() in 2.3 and git master, and tell me whether "just move the res_init() right after the "while(true) {" bit would be the right fix?

comment:7 Changed 8 years ago by Gert Döring

So, the first bit (configure not finding res_init()) has been merged into git master and release/2.3, per

commit 0d4091298f3644ff4187aa1ec54d1c440a056875 (master)
commit b230eef98a2cc571d725fc19ff5f2d5093d643ca (release/2.3)

Author: Gert Doering
Date: Mon Apr 27 21:27:21 2015 +0200

assume res_init() is always there.

now we just need to move the res_init() to the right place. Arne?

comment:8 Changed 8 years ago by Gert Döring

OK, testing this was more complicated than expected, because master has changed the interpretation of --resolv-retry infinite (leading to "exactly one retry inside openvpn_getaddrinfo()") *and* Linux has changed glibc to always call stat("/etc/resolv.conf")...

So, tested on FreeBSD 9.1, and using "--resolv-retry 50" to give me 10 retries in the inner loop, and a resolver that really wants us to call res_init() to re-read stuff.

With that, the problem manifests (read: if I break resolv.conf, then call openvpn, and while running, fix resolv.conf, it will not pick up the changes) - and the assumed fix "move res_init() just inside the while(true) { ...} loop" also works.

Totally trivial patch sent to list:

comment:9 Changed 8 years ago by Gert Döring

Resolution: fixed
Status: newclosed

Patch has been applied to the master and release/2.3 branch.

commit 288a819af7d3a6fab9e0b69ae8dbaac74b36307b (master)
commit 4e7eb95e43f0daed79e25e0ad6a9a20705b57376 (release/2.3)

Author: Gert Doering
Date: Sun May 31 15:59:09 2015 +0200

Move res_init() call to inner openvpn_getaddrinfo() loop

Signed-off-by: Gert Doering <gert@…>
Acked-by: Arne Schwabe <arne@…>
Message-Id: <1433080749-6892-1-git-send-email-gert@…>

Note: See TracTickets for help on using tickets.