l2tp: remove configurable payload offset
authorJames Chapman <jchapman@katalix.com>
Wed, 3 Jan 2018 22:48:06 +0000 (22:48 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 5 Jan 2018 16:03:19 +0000 (11:03 -0500)
If L2TP_ATTR_OFFSET is set to a non-zero value in L2TPv3 tunnels, it
results in L2TPv3 packets being transmitted which might not be
compliant with the L2TPv3 RFC. This patch has l2tp ignore the offset
setting and send all packets with no offset.

In more detail:

L2TPv2 supports a variable offset from the L2TPv2 header to the
payload. The offset value is indicated by an optional field in the
L2TP header.  Our L2TP implementation already detects the presence of
the optional offset and skips that many bytes when handling data
received packets. All transmitted packets are always transmitted with
no offset.

L2TPv3 has no optional offset field in the L2TPv3 packet
header. Instead, L2TPv3 defines optional fields in a "Layer-2 Specific
Sublayer". At the time when the original L2TP code was written, there
was talk at IETF of offset being implemented in a new Layer-2 Specific
Sublayer. A L2TP_ATTR_OFFSET netlink attribute was added so that this
offset could be configured and the intention was to allow it to be
also used to set the tx offset for L2TPv2. However, no L2TPv3 offset
was ever specified and the L2TP_ATTR_OFFSET parameter was forgotten
about.

Setting L2TP_ATTR_OFFSET results in L2TPv3 packets being transmitted
with the specified number of bytes padding between L2TPv3 header and
payload. This is not compliant with L2TPv3 RFC3931. This change
removes the configurable offset altogether while retaining
L2TP_ATTR_OFFSET for backwards compatibility. Any L2TP_ATTR_OFFSET
value is ignored.

Signed-off-by: James Chapman <jchapman@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_debugfs.c
net/l2tp/l2tp_netlink.c

index 115918ad8eca5ac27925d94aa17a91b9b2c17659..786cd7f6a5e836460d0ad079616f3b63c94cbf7d 100644 (file)
@@ -780,10 +780,8 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
                }
        }
 
-       /* Session data offset is handled differently for L2TPv2 and
-        * L2TPv3. For L2TPv2, there is an optional 16-bit value in
-        * the header. For L2TPv3, the offset is negotiated using AVPs
-        * in the session setup control protocol.
+       /* Session data offset is defined only for L2TPv2 and is
+        * indicated by an optional 16-bit value in the header.
         */
        if (tunnel->version == L2TP_HDR_VER_2) {
                /* If offset bit set, skip it. */
@@ -791,8 +789,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
                        offset = ntohs(*(__be16 *)ptr);
                        ptr += 2 + offset;
                }
-       } else
-               ptr += session->offset;
+       }
 
        offset = ptr - optr;
        if (!pskb_may_pull(skb, offset))
@@ -1068,8 +1065,6 @@ static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf)
                }
                bufp += session->l2specific_len;
        }
-       if (session->offset)
-               bufp += session->offset;
 
        return bufp - optr;
 }
@@ -1734,7 +1729,7 @@ void l2tp_session_set_header_len(struct l2tp_session *session, int version)
                if (session->send_seq)
                        session->hdr_len += 4;
        } else {
-               session->hdr_len = 4 + session->cookie_len + session->l2specific_len + session->offset;
+               session->hdr_len = 4 + session->cookie_len + session->l2specific_len;
                if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP)
                        session->hdr_len += 4;
        }
@@ -1784,7 +1779,6 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn
                        session->recv_seq = cfg->recv_seq;
                        session->lns_mode = cfg->lns_mode;
                        session->reorder_timeout = cfg->reorder_timeout;
-                       session->offset = cfg->offset;
                        session->l2specific_type = cfg->l2specific_type;
                        session->l2specific_len = cfg->l2specific_len;
                        session->cookie_len = cfg->cookie_len;
index 9534e16965ccbd87a4e8245df7dc079bdb7931eb..c2e9bbd79b35eaae0299ec60ced3c4ca3c6f871e 100644 (file)
@@ -59,7 +59,6 @@ struct l2tp_session_cfg {
        int                     debug;          /* bitmask of debug message
                                                 * categories */
        u16                     vlan_id;        /* VLAN pseudowire only */
-       u16                     offset;         /* offset to payload */
        u16                     l2specific_len; /* Layer 2 specific length */
        u16                     l2specific_type; /* Layer 2 specific type */
        u8                      cookie[8];      /* optional cookie */
@@ -86,8 +85,6 @@ struct l2tp_session {
        int                     cookie_len;
        u8                      peer_cookie[8];
        int                     peer_cookie_len;
-       u16                     offset;         /* offset from end of L2TP header
-                                                  to beginning of data */
        u16                     l2specific_len;
        u16                     l2specific_type;
        u16                     hdr_len;
index eb69411bcb47a99040256536ff4684aac98d35b4..2c30587d1a149811082442fc24357d554f330b01 100644 (file)
@@ -180,8 +180,8 @@ static void l2tp_dfs_seq_session_show(struct seq_file *m, void *v)
                   session->lns_mode ? "LNS" : "LAC",
                   session->debug,
                   jiffies_to_msecs(session->reorder_timeout));
-       seq_printf(m, "   offset %hu l2specific %hu/%hu\n",
-                  session->offset, session->l2specific_type, session->l2specific_len);
+       seq_printf(m, "   offset 0 l2specific %hu/%hu\n",
+                  session->l2specific_type, session->l2specific_len);
        if (session->cookie_len) {
                seq_printf(m, "   cookie %02x%02x%02x%02x",
                           session->cookie[0], session->cookie[1],
index a1f24fb2be980b204f83de977c452f3027d1cfa8..e1ca29f79821cc464c3846c0edd82ef546698edd 100644 (file)
@@ -547,9 +547,6 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
        }
 
        if (tunnel->version > 2) {
-               if (info->attrs[L2TP_ATTR_OFFSET])
-                       cfg.offset = nla_get_u16(info->attrs[L2TP_ATTR_OFFSET]);
-
                if (info->attrs[L2TP_ATTR_DATA_SEQ])
                        cfg.data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]);