From 2cbf0a14830ef97ed97a61da4d669c0be03f5ddb Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 18 Mar 2014 17:27:32 +0100 Subject: [PATCH] gtp: fix wrong handling of option header fields in GTPv1 TS 29.060 expresses thing is a quite complicated way just to say that if any of the optional fields is there, then all optional fields become mandatory :-). "This field shall be present if and only if any one or more of the S, PN and E flags are set.". So, if any flag is set, we *always* have 4 extra bytes. --- gtp.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/gtp.c b/gtp.c index f7244ac..35d7e87 100644 --- a/gtp.c +++ b/gtp.c @@ -260,17 +260,6 @@ out_rcu: return ret; } -static u8 gtp1u_header_len[] = { - [0] = 0, /* 0 */ - [GTP1_F_SEQ] = 2, /* 2 */ - [GTP1_F_NPDU] = 1, /* 1 */ - [GTP1_F_SEQ|GTP1_F_NPDU] = 3, /* 2 + 1 */ - [GTP1_F_EXTHDR] = 1, /* 1 */ - [GTP1_F_EXTHDR|GTP1_F_SEQ] = 3, /* 1 + 2 */ - [GTP1_F_EXTHDR|GTP1_F_NPDU] = 2, /* 1 + 1 */ - [GTP1_F_EXTHDR|GTP1_F_NPDU|GTP1_F_SEQ] = 4, /* 1 + 1 + 2 */ -}; - static int gtp1u_udp_encap_recv(struct gtp_instance *gti, struct sk_buff *skb) { struct gtp1_header *gtp1; @@ -294,8 +283,14 @@ static int gtp1u_udp_encap_recv(struct gtp_instance *gti, struct sk_buff *skb) if (gtp1->type != GTP_TPDU) return 1; - /* look-up table for faster length computing */ - hdrlen += gtp1u_header_len[gtp1->flags & GTP1_F_MASK]; + /* From 29.060: "This field shall be present if and only if any one or + * more of the S, PN and E flags are set.". + * + * If any of the bit is set, then the remaining ones also have to be + * set. + */ + if (gtp1->flags & GTP1_F_MASK) + hdrlen += 4; /* check for sufficient header size for extension */ if (!pskb_may_pull(skb, hdrlen))