]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
For Pulse, send ESP only of the same IP protocol as we're connected over
authorDavid Woodhouse <dwmw2@infradead.org>
Tue, 16 Jul 2019 10:37:59 +0000 (11:37 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Tue, 16 Jul 2019 10:37:59 +0000 (11:37 +0100)
It really seems that when we're connected over Legacy IP, it only accepts
Legacy IP packets in ESP. And when we're connected over IPv6, it only
accepts IPv6 packets in ESP.

This matches the behaviour of the Windows client too.

If you connect to a NC server over IPv6 it doesn't even offer the ESP
config (since NC doesn't support IPv6 within the tunnel).

Someone really ought to report this bug to Pulse. For IPv6 VPN traffic
to be forced into TCP-over-TCP mode when you happen to be connected to
the VPN over Legacy IP is very bad.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
esp.c
mainloop.c
oncp.c

diff --git a/esp.c b/esp.c
index 0b34c2ebc271bb2086ecbfe142ef4925b6038204..2f2c0da307fb2d6a9d0264e5d8530b7aaab1882e 100644 (file)
--- a/esp.c
+++ b/esp.c
@@ -302,10 +302,27 @@ int esp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                        this = vpninfo->deflate_pkt;
                        len = this->len;
                } else {
+                       uint8_t dontsend;
+
                        this = dequeue_packet(&vpninfo->outgoing_queue);
                        if (!this)
                                break;
 
+                       /* Pulse can only accept ESP of the same protocol as the one you
+                        * connected to it with. The other has to go over IF-T/TLS. */
+                       if (vpninfo->dtls_addr->sa_family == AF_INET6)
+                               dontsend = 0x40;
+                       else
+                               dontsend = 0x60;
+
+                       if ( (this->data[0] & 0xf0) == dontsend) {
+                               store_be32(&this->pulse.vendor, 0xa4c);
+                               store_be32(&this->pulse.type, 4);
+                               store_be32(&this->pulse.len, this->len + 16);
+                               queue_packet(&vpninfo->oncp_control_queue, this);
+                               work_done = 1;
+                               continue;
+                       }
                        len = construct_esp_packet(vpninfo, this, 0);
                        if (len < 0) {
                                /* Should we disable ESP? */
index b21ff70c779e6d3cfbd2535b2a6d295c2470ab2c..af283fb47277627fdb69265340ef2b321f38409d 100644 (file)
@@ -79,8 +79,8 @@ int tun_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                        vpninfo->stats.tx_bytes += out_pkt->len;
                        work_done = 1;
 
-                       if (queue_packet(&vpninfo->outgoing_queue, out_pkt) ==
-                           vpninfo->max_qlen) {
+                       if (queue_packet(&vpninfo->outgoing_queue, out_pkt) +
+                           vpninfo->oncp_control_queue.count >= vpninfo->max_qlen) {
                                out_pkt = NULL;
                                unmonitor_read_fd(vpninfo, tun);
                                break;
@@ -88,7 +88,7 @@ int tun_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
                        out_pkt = NULL;
                }
                vpninfo->tun_pkt = out_pkt;
-       } else if (vpninfo->outgoing_queue.count < vpninfo->max_qlen) {
+       } else if (vpninfo->outgoing_queue.count + vpninfo->oncp_control_queue.count < vpninfo->max_qlen) {
                monitor_read_fd(vpninfo, tun);
        }
 
diff --git a/oncp.c b/oncp.c
index ebb82481c3c2e2a8a2de5854275209d6f382882c..8a3e178e2beb1a19388271cbb66065d7e0406171 100644 (file)
--- a/oncp.c
+++ b/oncp.c
@@ -1305,7 +1305,8 @@ int oncp_esp_send_probes(struct openconnect_info *vpninfo)
        for (seq=1; seq <= (vpninfo->dtls_state==DTLS_CONNECTED ? 1 : 2); seq++) {
                pkt->len = 1;
                pkt->data[0] = 0;
-               pktlen = construct_esp_packet(vpninfo, pkt, IPPROTO_IPIP);
+               pktlen = construct_esp_packet(vpninfo, pkt,
+                                             vpninfo->dtls_addr->sa_family == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IPIP);
                if (pktlen >= 0)
                        send(vpninfo->dtls_fd, (void *)&pkt->esp, pktlen, 0);
        }