]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Need to handle case where rejected protocol was sent as only 1 byte
authorDaniel Lenski <dlenski@gmail.com>
Sun, 17 May 2020 23:27:52 +0000 (16:27 -0700)
committerDaniel Lenski <dlenski@gmail.com>
Mon, 18 May 2020 02:32:52 +0000 (19:32 -0700)
… as well as the admittedly-unlikely case where the rejected protocol is
larger than peer's MRU (which we've already accepted as our MTU).

Signed-off-by: Daniel Lenski <dlenski@gmail.com>
ppp.c

diff --git a/ppp.c b/ppp.c
index 1a2a6b4ff9ee2b0b69b56a17aa3bf1d68d29782d..c1846aa2ad08a3c828173e84559ad332f5e2038a 100644 (file)
--- a/ppp.c
+++ b/ppp.c
@@ -1084,12 +1084,23 @@ int ppp_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
 
                default:
                        vpn_progress(vpninfo, PRG_ERR,
-                                    _("PPP packet with unknown protocol 0x%04x. Payload:\n"),
+                                    _("Sending Protocol-Reject for unknown protocol 0x%04x. Payload:\n"),
                                     proto);
                        dump_buf_hex(vpninfo, PRG_ERR, '<', pp, payload_len);
-                       if (queue_config_packet(vpninfo, PPP_LCP, ++ppp->lcp.id, PROTREJ, payload_len + (pp - ph), ph))
-                               vpn_progress(vpninfo, PRG_ERR,
-                                            _("Failed queuing Protocol-Reject for unknown protocol 0x%04x.\n"), proto);
+
+                       /* The rejected protocol MUST occupy 2 bytes prior to the rejected packet contents.
+                        * (https://tools.ietf.org/html/rfc1661#section-5.7). We can clobber these bytes
+                        * because we are throwing out this packet anyway.
+                        *
+                        * The rejected packet body is fully included, unless it must be truncated to the
+                        * peer's MRU (taking into account the preceding 4 bytes for PPP header, 4 for LCP
+                        * config header, and 2 for rejected proto.
+                        */
+                       store_be16(pp - 2, proto);
+                       if ((ret = queue_config_packet(vpninfo, PPP_LCP, ++ppp->lcp.id, PROTREJ,
+                                                      MIN(payload_len + 2, vpninfo->ip_info.mtu - 10),
+                                                      pp - 2)) < 0)
+                               return ret;
                }
 
                if (next_len) {