summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@gnumonks.org>2014-03-18 17:27:32 +0100
committerPablo Neira Ayuso <pablo@gnumonks.org>2014-03-18 18:30:05 +0100
commit2cbf0a14830ef97ed97a61da4d669c0be03f5ddb (patch)
treeda27a1550d6c2b9e2b4b7273e8ddb7fa616304c2
parent151652cc809a57f3ef57654ad3cba0c1f006b109 (diff)
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.
-rw-r--r--gtp.c21
1 files 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))