Merge branch 'l2tp-set-l2specific_len-based-on-l2specific_type'
Lorenzo Bianconi says: ==================== l2tp: set l2specific_len based on l2specific_type Do not rely on l2specific_len value provided by userspace but set sublayer length according to l2specific_type. Mark L2TP_ATTR_L2SPEC_LEN attribute as not used Changes since v2: - drop the patch related to a fix in the switch default case in l2tp_nl_cmd_session_create() - use L2SPECTYPE_NONE as default case in l2tp_get_l2specific_len() Changes since v1: - remove l2specific_len parameter - add sanity check on l2specific_type provided by userspace ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
bfd072df10
|
@ -97,7 +97,7 @@ enum {
|
||||||
L2TP_ATTR_OFFSET, /* u16 (not used) */
|
L2TP_ATTR_OFFSET, /* u16 (not used) */
|
||||||
L2TP_ATTR_DATA_SEQ, /* u16 */
|
L2TP_ATTR_DATA_SEQ, /* u16 */
|
||||||
L2TP_ATTR_L2SPEC_TYPE, /* u8, enum l2tp_l2spec_type */
|
L2TP_ATTR_L2SPEC_TYPE, /* u8, enum l2tp_l2spec_type */
|
||||||
L2TP_ATTR_L2SPEC_LEN, /* u8, enum l2tp_l2spec_type */
|
L2TP_ATTR_L2SPEC_LEN, /* u8 (not used) */
|
||||||
L2TP_ATTR_PROTO_VERSION, /* u8 */
|
L2TP_ATTR_PROTO_VERSION, /* u8 */
|
||||||
L2TP_ATTR_IFNAME, /* string */
|
L2TP_ATTR_IFNAME, /* string */
|
||||||
L2TP_ATTR_CONN_ID, /* u32 */
|
L2TP_ATTR_CONN_ID, /* u32 */
|
||||||
|
|
|
@ -730,11 +730,9 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
|
||||||
"%s: recv data ns=%u, session nr=%u\n",
|
"%s: recv data ns=%u, session nr=%u\n",
|
||||||
session->name, ns, session->nr);
|
session->name, ns, session->nr);
|
||||||
}
|
}
|
||||||
|
ptr += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Advance past L2-specific header, if present */
|
|
||||||
ptr += session->l2specific_len;
|
|
||||||
|
|
||||||
if (L2TP_SKB_CB(skb)->has_seq) {
|
if (L2TP_SKB_CB(skb)->has_seq) {
|
||||||
/* Received a packet with sequence numbers. If we're the LNS,
|
/* Received a packet with sequence numbers. If we're the LNS,
|
||||||
* check if we sre sending sequence numbers and if not,
|
* check if we sre sending sequence numbers and if not,
|
||||||
|
@ -1048,21 +1046,20 @@ static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf)
|
||||||
memcpy(bufp, &session->cookie[0], session->cookie_len);
|
memcpy(bufp, &session->cookie[0], session->cookie_len);
|
||||||
bufp += session->cookie_len;
|
bufp += session->cookie_len;
|
||||||
}
|
}
|
||||||
if (session->l2specific_len) {
|
if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
|
||||||
if (session->l2specific_type == L2TP_L2SPECTYPE_DEFAULT) {
|
u32 l2h = 0;
|
||||||
u32 l2h = 0;
|
|
||||||
if (session->send_seq) {
|
|
||||||
l2h = 0x40000000 | session->ns;
|
|
||||||
session->ns++;
|
|
||||||
session->ns &= 0xffffff;
|
|
||||||
l2tp_dbg(session, L2TP_MSG_SEQ,
|
|
||||||
"%s: updated ns to %u\n",
|
|
||||||
session->name, session->ns);
|
|
||||||
}
|
|
||||||
|
|
||||||
*((__be32 *) bufp) = htonl(l2h);
|
if (session->send_seq) {
|
||||||
|
l2h = 0x40000000 | session->ns;
|
||||||
|
session->ns++;
|
||||||
|
session->ns &= 0xffffff;
|
||||||
|
l2tp_dbg(session, L2TP_MSG_SEQ,
|
||||||
|
"%s: updated ns to %u\n",
|
||||||
|
session->name, session->ns);
|
||||||
}
|
}
|
||||||
bufp += session->l2specific_len;
|
|
||||||
|
*((__be32 *)bufp) = htonl(l2h);
|
||||||
|
bufp += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bufp - optr;
|
return bufp - optr;
|
||||||
|
@ -1719,7 +1716,7 @@ int l2tp_session_delete(struct l2tp_session *session)
|
||||||
EXPORT_SYMBOL_GPL(l2tp_session_delete);
|
EXPORT_SYMBOL_GPL(l2tp_session_delete);
|
||||||
|
|
||||||
/* We come here whenever a session's send_seq, cookie_len or
|
/* We come here whenever a session's send_seq, cookie_len or
|
||||||
* l2specific_len parameters are set.
|
* l2specific_type parameters are set.
|
||||||
*/
|
*/
|
||||||
void l2tp_session_set_header_len(struct l2tp_session *session, int version)
|
void l2tp_session_set_header_len(struct l2tp_session *session, int version)
|
||||||
{
|
{
|
||||||
|
@ -1728,7 +1725,8 @@ void l2tp_session_set_header_len(struct l2tp_session *session, int version)
|
||||||
if (session->send_seq)
|
if (session->send_seq)
|
||||||
session->hdr_len += 4;
|
session->hdr_len += 4;
|
||||||
} else {
|
} else {
|
||||||
session->hdr_len = 4 + session->cookie_len + session->l2specific_len;
|
session->hdr_len = 4 + session->cookie_len;
|
||||||
|
session->hdr_len += l2tp_get_l2specific_len(session);
|
||||||
if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP)
|
if (session->tunnel->encap == L2TP_ENCAPTYPE_UDP)
|
||||||
session->hdr_len += 4;
|
session->hdr_len += 4;
|
||||||
}
|
}
|
||||||
|
@ -1779,7 +1777,6 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn
|
||||||
session->lns_mode = cfg->lns_mode;
|
session->lns_mode = cfg->lns_mode;
|
||||||
session->reorder_timeout = cfg->reorder_timeout;
|
session->reorder_timeout = cfg->reorder_timeout;
|
||||||
session->l2specific_type = cfg->l2specific_type;
|
session->l2specific_type = cfg->l2specific_type;
|
||||||
session->l2specific_len = cfg->l2specific_len;
|
|
||||||
session->cookie_len = cfg->cookie_len;
|
session->cookie_len = cfg->cookie_len;
|
||||||
memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len);
|
memcpy(&session->cookie[0], &cfg->cookie[0], cfg->cookie_len);
|
||||||
session->peer_cookie_len = cfg->peer_cookie_len;
|
session->peer_cookie_len = cfg->peer_cookie_len;
|
||||||
|
|
|
@ -59,7 +59,6 @@ struct l2tp_session_cfg {
|
||||||
int debug; /* bitmask of debug message
|
int debug; /* bitmask of debug message
|
||||||
* categories */
|
* categories */
|
||||||
u16 vlan_id; /* VLAN pseudowire only */
|
u16 vlan_id; /* VLAN pseudowire only */
|
||||||
u16 l2specific_len; /* Layer 2 specific length */
|
|
||||||
u16 l2specific_type; /* Layer 2 specific type */
|
u16 l2specific_type; /* Layer 2 specific type */
|
||||||
u8 cookie[8]; /* optional cookie */
|
u8 cookie[8]; /* optional cookie */
|
||||||
int cookie_len; /* 0, 4 or 8 bytes */
|
int cookie_len; /* 0, 4 or 8 bytes */
|
||||||
|
@ -85,7 +84,6 @@ struct l2tp_session {
|
||||||
int cookie_len;
|
int cookie_len;
|
||||||
u8 peer_cookie[8];
|
u8 peer_cookie[8];
|
||||||
int peer_cookie_len;
|
int peer_cookie_len;
|
||||||
u16 l2specific_len;
|
|
||||||
u16 l2specific_type;
|
u16 l2specific_type;
|
||||||
u16 hdr_len;
|
u16 hdr_len;
|
||||||
u32 nr; /* session NR state (receive) */
|
u32 nr; /* session NR state (receive) */
|
||||||
|
@ -302,6 +300,17 @@ static inline void l2tp_session_dec_refcount(struct l2tp_session *session)
|
||||||
l2tp_session_free(session);
|
l2tp_session_free(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int l2tp_get_l2specific_len(struct l2tp_session *session)
|
||||||
|
{
|
||||||
|
switch (session->l2specific_type) {
|
||||||
|
case L2TP_L2SPECTYPE_DEFAULT:
|
||||||
|
return 4;
|
||||||
|
case L2TP_L2SPECTYPE_NONE:
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define l2tp_printk(ptr, type, func, fmt, ...) \
|
#define l2tp_printk(ptr, type, func, fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (((ptr)->debug) & (type)) \
|
if (((ptr)->debug) & (type)) \
|
||||||
|
|
|
@ -181,7 +181,7 @@ static void l2tp_dfs_seq_session_show(struct seq_file *m, void *v)
|
||||||
session->debug,
|
session->debug,
|
||||||
jiffies_to_msecs(session->reorder_timeout));
|
jiffies_to_msecs(session->reorder_timeout));
|
||||||
seq_printf(m, " offset 0 l2specific %hu/%hu\n",
|
seq_printf(m, " offset 0 l2specific %hu/%hu\n",
|
||||||
session->l2specific_type, session->l2specific_len);
|
session->l2specific_type, l2tp_get_l2specific_len(session));
|
||||||
if (session->cookie_len) {
|
if (session->cookie_len) {
|
||||||
seq_printf(m, " cookie %02x%02x%02x%02x",
|
seq_printf(m, " cookie %02x%02x%02x%02x",
|
||||||
session->cookie[0], session->cookie[1],
|
session->cookie[0], session->cookie[1],
|
||||||
|
|
|
@ -550,13 +550,16 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
|
||||||
if (info->attrs[L2TP_ATTR_DATA_SEQ])
|
if (info->attrs[L2TP_ATTR_DATA_SEQ])
|
||||||
cfg.data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]);
|
cfg.data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]);
|
||||||
|
|
||||||
cfg.l2specific_type = L2TP_L2SPECTYPE_DEFAULT;
|
if (info->attrs[L2TP_ATTR_L2SPEC_TYPE]) {
|
||||||
if (info->attrs[L2TP_ATTR_L2SPEC_TYPE])
|
|
||||||
cfg.l2specific_type = nla_get_u8(info->attrs[L2TP_ATTR_L2SPEC_TYPE]);
|
cfg.l2specific_type = nla_get_u8(info->attrs[L2TP_ATTR_L2SPEC_TYPE]);
|
||||||
|
if (cfg.l2specific_type != L2TP_L2SPECTYPE_DEFAULT &&
|
||||||
cfg.l2specific_len = 4;
|
cfg.l2specific_type != L2TP_L2SPECTYPE_NONE) {
|
||||||
if (info->attrs[L2TP_ATTR_L2SPEC_LEN])
|
ret = -EINVAL;
|
||||||
cfg.l2specific_len = nla_get_u8(info->attrs[L2TP_ATTR_L2SPEC_LEN]);
|
goto out_tunnel;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cfg.l2specific_type = L2TP_L2SPECTYPE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->attrs[L2TP_ATTR_COOKIE]) {
|
if (info->attrs[L2TP_ATTR_COOKIE]) {
|
||||||
u16 len = nla_len(info->attrs[L2TP_ATTR_COOKIE]);
|
u16 len = nla_len(info->attrs[L2TP_ATTR_COOKIE]);
|
||||||
|
|
Loading…
Reference in New Issue