From: David Woodhouse Date: Tue, 16 Jul 2019 10:37:59 +0000 (+0100) Subject: For Pulse, send ESP only of the same IP protocol as we're connected over X-Git-Tag: v8.04~10 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=b4f50f8bd5da7e6ac926ddd5095501edbc204cd0;p=users%2Fdwmw2%2Fopenconnect.git For Pulse, send ESP only of the same IP protocol as we're connected over 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 --- diff --git a/esp.c b/esp.c index 0b34c2eb..2f2c0da3 100644 --- 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? */ diff --git a/mainloop.c b/mainloop.c index b21ff70c..af283fb4 100644 --- a/mainloop.c +++ b/mainloop.c @@ -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 ebb82481..8a3e178e 100644 --- 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); }