]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Fix -EAGAIN on writing DTLS socket for PPP mainloop
authorDavid Woodhouse <dwmw2@infradead.org>
Thu, 15 Apr 2021 15:36:15 +0000 (16:36 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Fri, 16 Apr 2021 15:06:36 +0000 (16:06 +0100)
If the socket sndbuf is full, we fail to send a packet. This should
actually happen less often for UDP than it does for TCP because of the
lack of back pressure from the peer, but it's still a fairly normal
condition and needs to be handled properly.

The correct handling is basically to do nothing and wait for the jam to
clear, unless it's been *so* long that DPD has caused us to think the
peer is dead, or we need a rekey (which we do be reconnecting the
transport channel). The ka_stalled_action() function exists specifically
to handle this case, and returns one of KA_NONE, KA_DPD_DEAD or KA_REKEY.
There's no ponit in it returning KA_DPD or KA_KEEPALIVE like the normal
keepalive_action() does because the point here is that we *can't* send
anything at the moment anyway.

The problem here is that the PPP mainloop doesn't handle those three
cases correctly, and KA_REKEY and KA_NONE were just falling through to
end up at the fatal error condition for a *short* write, which should
never happen. I went too far when commenting out the cut and pasted
mainloop to create ppp_mainloop.

Fix KA_REKEY to do a reconnect, and KA_NONE to just return work_done
as it should.

Fixes: a47406b43 ("add support for PPP-based protocols")
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
ppp.c

diff --git a/ppp.c b/ppp.c
index 1377270f6de8bf88fa5984c82ca626edf6180ab1..a552f41a6b632e2b3058d7a38676a42f572395c8 100644 (file)
--- a/ppp.c
+++ b/ppp.c
@@ -1256,11 +1256,12 @@ int ppp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                        case KA_DPD_DEAD:
                                goto peer_dead;
                        case KA_REKEY:
-//                             goto do_rekey;
+                               goto do_reconnect;
                        case KA_NONE:
-//                             return work_done;
+                               return work_done;
                        default:
-                               /* This should never happen */
+                               /* This can never happen because ka_stalled_action()
+                                * always returns one of the above. */
                                ;
                        }
                }