linux returns EAGAIN for closed ocserv interfaces

Niels Peen niels at peen.ch
Fri Sep 19 05:54:22 PDT 2014


I ran into an issue where dnsmasq would become unresponsive on a very busy VPN server. Dnsmasq would be looping endlessly like this:

sendmsg(6, {msg_name(16)={sa_family=AF_INET, sin_port=htons(59990), sin_addr=inet_addr("10.255.232.69")}, msg_iov(1)=[{"F\253\201\200\0\1\0\3\0\0\0\0\5b-api\10facebook\3com\0\0\1\0\1\300\f\0\5\0\1\0\0\6r\0\6\3z-m\300\22\3000\0\5\0\1\0\0\6n\0\v\3z-m\4c10r\300\22\300B\0\1\0\1\0\0\0\3\0\4\37\rF\6", 93}], msg_controllen=0, msg_flags=0}, 0) = -1 EAGAIN (Resource temporarily unavailable)
nanosleep({0, 10000}, NULL)             = 0
sendmsg(6, {msg_name(16)={sa_family=AF_INET, sin_port=htons(59990), sin_addr=inet_addr("10.255.232.69")}, msg_iov(1)=[{"F\253\201\200\0\1\0\3\0\0\0\0\5b-api\10facebook\3com\0\0\1\0\1\300\f\0\5\0\1\0\0\6r\0\6\3z-m\300\22\3000\0\5\0\1\0\0\6n\0\v\3z-m\4c10r\300\22\300B\0\1\0\1\0\0\0\3\0\4\37\rF\6", 93}], msg_controllen=0, msg_flags=0}, 0) = -1 EAGAIN (Resource temporarily unavailable)
nanosleep({0, 10000}, NULL)       

10.255.232.69 is a client of ocserv that disconnected prior to dnsmasq returning the result. Removing ocserv from the server (but letting people connect with other VPN methods) prevents the problem from occurring. 

Simon Kelley of dnsmasq provided me a work-around which I’m testing at the moment. That doesn’t solve the underlying problem though. When I swap dnsmasq for BIND it runs into a similar problem: it fills up the send queue and becomes unresponsive.

I suspect the problem is with how ocserv closes the tun interfaces. Thomas Veerman suggested that closing the interfaces may simply be failing occasionally and provided me with the patch below, which I’m testing as well.

# diff main-misc.c.old main-misc.c
131,136c131,137
<       if (proc->tun_lease.name[0] != 0) {
<               if (proc->tun_lease.fd >= 0)
<                       close(proc->tun_lease.fd);
<               proc->tun_lease.fd = -1;
<       }
< 
---
>       while (proc->tun_lease.fd >= 0) {
>               int r = close(proc->tun_lease.fd);
>               if (r == 0 || errno == EBADF) {
>                       proc->tun_lease.fd = -1;
>                 }
>         }
>                     

Appreciate any comments you may have.

Cheers,
Niels




More information about the openconnect-devel mailing list