gtp: fix receival path of version 0
After this patch, it already forwards a (yet malformed) packet to the real device. GTPv1 receival path yet untested but similar changes that were done to GTPv0 has been done.
This commit is contained in:
parent
e01b17c8eb
commit
b968ddf47f
46
gtp.c
46
gtp.c
|
@ -242,21 +242,28 @@ static inline struct gtp_instance *sk_to_gti(struct sock *sk)
|
|||
* Return codes: 0: succes, <0: error, >0: passed up to userspace UDP */
|
||||
static int gtp0_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct gtp0_header *gtp0 = (struct gtp0_header *) skb_transport_header(skb);
|
||||
struct gtp0_header *gtp0;
|
||||
struct gtp_instance *gti;
|
||||
struct pdp_ctx *pctx;
|
||||
uint64_t tid;
|
||||
int rc;
|
||||
|
||||
pr_info("gtp0 udp received\n");
|
||||
|
||||
/* resolve the GTP instance to which the socket belongs */
|
||||
gti = sk_to_gti(sk);
|
||||
if (!gti)
|
||||
goto user;
|
||||
|
||||
/* UDP always verifies the packet length. */
|
||||
__skb_pull(skb, sizeof(struct udphdr));
|
||||
|
||||
/* check for sufficient header size */
|
||||
if (!pskb_may_pull(skb, sizeof(struct udphdr) + sizeof(*gtp0)))
|
||||
if (!pskb_may_pull(skb, sizeof(*gtp0)))
|
||||
goto drop_put;
|
||||
|
||||
gtp0 = (struct gtp0_header *)skb->data;
|
||||
|
||||
/* check for GTP Version 0 */
|
||||
if ((gtp0->flags >> 5) != 0)
|
||||
goto drop_put;
|
||||
|
@ -273,8 +280,13 @@ static int gtp0_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
|||
if (!pctx)
|
||||
goto drop_put_rcu;
|
||||
|
||||
/* get rid of the UDP and GTP header */
|
||||
__skb_pull(skb, sizeof(struct udphdr) + sizeof(*gtp0));
|
||||
/* get rid of the GTP header */
|
||||
__skb_pull(skb, sizeof(*gtp0));
|
||||
|
||||
/* We're about to requeue the skb, so return resources
|
||||
* to its current owner (a socket receive buffer).
|
||||
*/
|
||||
skb_orphan(skb);
|
||||
|
||||
/* FIXME: check if the inner IP header has the source address
|
||||
* assigned to the current MS */
|
||||
|
@ -303,24 +315,31 @@ user:
|
|||
* Return codes: 0: succes, <0: error, >0: passed up to userspace UDP */
|
||||
static int gtp1u_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct gtp1_header_short *gtp1 =
|
||||
(struct gtp1_header_short *) skb_transport_header(skb);
|
||||
struct gtp0_header *gtp0 = (struct gtp0_header *) gtp1;
|
||||
struct gtp1_header_short *gtp1;
|
||||
struct gtp0_header *gtp0;
|
||||
struct gtp_instance *gti;
|
||||
struct pdp_ctx *pctx;
|
||||
unsigned int min_len = sizeof(*gtp1);
|
||||
uint64_t tid;
|
||||
int rc;
|
||||
|
||||
pr_info("gtp1 udp received\n");
|
||||
|
||||
/* resolve the GTP instance to which the socket belongs */
|
||||
gti = sk_to_gti(sk);
|
||||
if (!gti)
|
||||
goto user;
|
||||
|
||||
/* UDP always verifies the packet length. */
|
||||
__skb_pull(skb, sizeof(struct udphdr));
|
||||
|
||||
/* check for sufficient header size */
|
||||
if (!pskb_may_pull(skb, sizeof(struct udphdr) + sizeof(*gtp1)))
|
||||
if (!pskb_may_pull(skb, sizeof(*gtp1)))
|
||||
goto drop_put;
|
||||
|
||||
gtp1 = (struct gtp1_header_short *)skb->data;
|
||||
gtp0 = (struct gtp0_header *)gtp1;
|
||||
|
||||
/* check for GTP Version 1 */
|
||||
if ((gtp0->flags >> 5) != 1)
|
||||
goto drop_put;
|
||||
|
@ -357,12 +376,17 @@ static int gtp1u_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
|||
if (!pctx)
|
||||
goto drop_put_rcu;
|
||||
|
||||
/* get rid of the UDP and GTP header */
|
||||
__skb_pull(skb, sizeof(struct udphdr) + sizeof(*gtp1));
|
||||
/* get rid of the GTP header */
|
||||
__skb_pull(skb, sizeof(*gtp1));
|
||||
|
||||
/* FIXME: check if the inner IP header has the source address
|
||||
* assigned to the current MS */
|
||||
|
||||
/* We're about to requeue the skb, so return resources
|
||||
* to its current owner (a socket receive buffer).
|
||||
*/
|
||||
skb_orphan(skb);
|
||||
|
||||
/* re-submit via virtual tunnel device into regular network
|
||||
* stack */
|
||||
secpath_reset(skb);
|
||||
|
@ -731,6 +755,7 @@ static int gtp_create_bind_sock(struct gtp_instance *gti)
|
|||
sk = gti->sock0->sk;
|
||||
udp_sk(sk)->encap_type = UDP_ENCAP_GTP0;
|
||||
udp_sk(sk)->encap_rcv = gtp0_udp_encap_recv;
|
||||
sk->sk_user_data = gti;
|
||||
udp_encap_enable();
|
||||
|
||||
/* Create and bind the socket for GTP1 user-plane */
|
||||
|
@ -748,6 +773,7 @@ static int gtp_create_bind_sock(struct gtp_instance *gti)
|
|||
sk = gti->sock1u->sk;
|
||||
udp_sk(sk)->encap_type = UDP_ENCAP_GTP1U;
|
||||
udp_sk(sk)->encap_rcv = gtp1u_udp_encap_recv;
|
||||
sk->sk_user_data = gti;
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue