gtp: fix handling of messages in the encap input path
* pass up to the stack if we don't know what to do. * drop packet if not well-formed or not found in our PDP ctx database.
This commit is contained in:
parent
d7cdbddebd
commit
d123a0c0f5
48
gtp.c
48
gtp.c
|
@ -217,10 +217,12 @@ static bool gtp_check_src_ms(struct sk_buff *skb, struct pdp_ctx *pctx)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 1 means pass up to the stack, -1 means drop and 0 means decapsulated */
|
||||||
static int gtp0_udp_encap_recv(struct gtp_instance *gti, struct sk_buff *skb)
|
static int gtp0_udp_encap_recv(struct gtp_instance *gti, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct gtp0_header *gtp0;
|
struct gtp0_header *gtp0;
|
||||||
struct pdp_ctx *pctx;
|
struct pdp_ctx *pctx;
|
||||||
|
int ret = 0;
|
||||||
u64 tid;
|
u64 tid;
|
||||||
|
|
||||||
pr_info("gtp0 udp received\n");
|
pr_info("gtp0 udp received\n");
|
||||||
|
@ -229,33 +231,31 @@ static int gtp0_udp_encap_recv(struct gtp_instance *gti, struct sk_buff *skb)
|
||||||
|
|
||||||
/* check for GTP Version 0 */
|
/* check for GTP Version 0 */
|
||||||
if ((gtp0->flags >> 5) != GTP_V0)
|
if ((gtp0->flags >> 5) != GTP_V0)
|
||||||
goto out;
|
return 1;
|
||||||
|
|
||||||
/* check if it is T-PDU. if not -> userspace */
|
/* check if it is T-PDU. if not -> userspace */
|
||||||
if (gtp0->type != GTP_TPDU)
|
if (gtp0->type != GTP_TPDU)
|
||||||
goto out;
|
return 1;
|
||||||
|
|
||||||
/* look-up the PDP context for the Tunnel ID */
|
/* look-up the PDP context for the Tunnel ID */
|
||||||
tid = be64_to_cpu(gtp0->tid);
|
tid = be64_to_cpu(gtp0->tid);
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
pctx = gtp0_pdp_find(gti, tid);
|
pctx = gtp0_pdp_find(gti, tid);
|
||||||
if (!pctx)
|
if (!pctx) {
|
||||||
|
ret = -1;
|
||||||
goto out_rcu;
|
goto out_rcu;
|
||||||
|
}
|
||||||
|
|
||||||
/* get rid of the GTP header */
|
/* get rid of the GTP header */
|
||||||
__skb_pull(skb, sizeof(*gtp0));
|
__skb_pull(skb, sizeof(*gtp0));
|
||||||
|
|
||||||
if (!gtp_check_src_ms(skb, pctx))
|
if (!gtp_check_src_ms(skb, pctx))
|
||||||
goto out_rcu;
|
ret = -1;
|
||||||
|
|
||||||
rcu_read_unlock();
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_rcu:
|
out_rcu:
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
out:
|
return ret;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 gtp1u_header_len[] = {
|
static u8 gtp1u_header_len[] = {
|
||||||
|
@ -274,35 +274,38 @@ static int gtp1u_udp_encap_recv(struct gtp_instance *gti, struct sk_buff *skb)
|
||||||
struct gtp1_header *gtp1;
|
struct gtp1_header *gtp1;
|
||||||
struct pdp_ctx *pctx;
|
struct pdp_ctx *pctx;
|
||||||
unsigned int gtp1_hdrlen = sizeof(*gtp1);
|
unsigned int gtp1_hdrlen = sizeof(*gtp1);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
pr_info("gtp1 udp received\n");
|
pr_info("gtp1 udp received\n");
|
||||||
|
|
||||||
/* check for sufficient header size */
|
/* check for sufficient header size */
|
||||||
if (!pskb_may_pull(skb, sizeof(*gtp1)))
|
if (!pskb_may_pull(skb, sizeof(*gtp1)))
|
||||||
goto out;
|
return -1;
|
||||||
|
|
||||||
gtp1 = (struct gtp1_header *)skb->data;
|
gtp1 = (struct gtp1_header *)skb->data;
|
||||||
|
|
||||||
/* check for GTP Version 1 */
|
/* check for GTP Version 1 */
|
||||||
if ((gtp1->flags >> 5) != GTP_V1)
|
if ((gtp1->flags >> 5) != GTP_V1)
|
||||||
goto out;
|
return 1;
|
||||||
|
|
||||||
/* check if it is T-PDU. */
|
/* check if it is T-PDU. */
|
||||||
if (gtp1->type != GTP_TPDU)
|
if (gtp1->type != GTP_TPDU)
|
||||||
goto out;
|
return 1;
|
||||||
|
|
||||||
/* look-up table for faster length computing */
|
/* look-up table for faster length computing */
|
||||||
gtp1_hdrlen = gtp1u_header_len[gtp1->flags & GTP1_F_MASK];
|
gtp1_hdrlen = gtp1u_header_len[gtp1->flags & GTP1_F_MASK];
|
||||||
|
|
||||||
/* check for sufficient header size */
|
/* check for sufficient header size */
|
||||||
if (gtp1_hdrlen && !pskb_may_pull(skb, gtp1_hdrlen))
|
if (gtp1_hdrlen && !pskb_may_pull(skb, gtp1_hdrlen))
|
||||||
goto out_rcu;
|
return -1;
|
||||||
|
|
||||||
/* look-up the PDP context for the Tunnel ID */
|
/* look-up the PDP context for the Tunnel ID */
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
pctx = gtp1_pdp_find(gti, ntohl(gtp1->tid));
|
pctx = gtp1_pdp_find(gti, ntohl(gtp1->tid));
|
||||||
if (!pctx)
|
if (!pctx) {
|
||||||
|
ret = -1;
|
||||||
goto out_rcu;
|
goto out_rcu;
|
||||||
|
}
|
||||||
|
|
||||||
/* get rid of the GTP header */
|
/* get rid of the GTP header */
|
||||||
__skb_pull(skb, sizeof(*gtp1) + gtp1_hdrlen);
|
__skb_pull(skb, sizeof(*gtp1) + gtp1_hdrlen);
|
||||||
|
@ -310,15 +313,11 @@ static int gtp1u_udp_encap_recv(struct gtp_instance *gti, struct sk_buff *skb)
|
||||||
/* FIXME: actually take care of extension header chain */
|
/* FIXME: actually take care of extension header chain */
|
||||||
|
|
||||||
if (!gtp_check_src_ms(skb, pctx))
|
if (!gtp_check_src_ms(skb, pctx))
|
||||||
goto out_rcu;
|
ret = -1;
|
||||||
|
|
||||||
rcu_read_unlock();
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_rcu:
|
out_rcu:
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
out:
|
return ret;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* UDP encapsulation receive handler. See net/ipv4/udp.c.
|
/* UDP encapsulation receive handler. See net/ipv4/udp.c.
|
||||||
|
@ -355,9 +354,14 @@ static int gtp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||||
ret = -1; /* shouldn't happen */
|
ret = -1; /* shouldn't happen */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not a valid GTP packet, drop it. */
|
switch (ret) {
|
||||||
if (unlikely(ret < 0))
|
case 1: /* pass up to the stack */
|
||||||
|
goto user_put;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
goto drop;
|
goto drop;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now that the UDP and the GTP header have been removed, set up the
|
/* Now that the UDP and the GTP header have been removed, set up the
|
||||||
* new network header. This is required by the upper later to
|
* new network header. This is required by the upper later to
|
||||||
|
|
Loading…
Reference in New Issue