Skip to content

Commit 750771d

Browse files
committed
gtp: prepare for IPv6 support
Use union artifact to prepare for IPv6 support. Add and use GTP_{IPV4,TH}_MAXLEN. Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent b6fc095 commit 750771d

File tree

1 file changed

+96
-55
lines changed

1 file changed

+96
-55
lines changed

drivers/net/gtp.c

Lines changed: 96 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@ struct pdp_ctx {
5050
u8 gtp_version;
5151
u16 af;
5252

53-
struct in_addr ms_addr_ip4;
54-
struct in_addr peer_addr_ip4;
53+
union {
54+
struct in_addr addr;
55+
} ms;
56+
union {
57+
struct in_addr addr;
58+
} peer;
5559

5660
struct sock *sk;
5761
struct net_device *dev;
@@ -80,9 +84,15 @@ struct gtp_dev {
8084
};
8185

8286
struct echo_info {
83-
struct in_addr ms_addr_ip4;
84-
struct in_addr peer_addr_ip4;
87+
u16 af;
8588
u8 gtp_version;
89+
90+
union {
91+
struct in_addr addr;
92+
} ms;
93+
union {
94+
struct in_addr addr;
95+
} peer;
8696
};
8797

8898
static unsigned int gtp_net_id __read_mostly;
@@ -163,7 +173,7 @@ static struct pdp_ctx *ipv4_pdp_find(struct gtp_dev *gtp, __be32 ms_addr)
163173

164174
hlist_for_each_entry_rcu(pdp, head, hlist_addr) {
165175
if (pdp->af == AF_INET &&
166-
pdp->ms_addr_ip4.s_addr == ms_addr)
176+
pdp->ms.addr.s_addr == ms_addr)
167177
return pdp;
168178
}
169179

@@ -181,9 +191,9 @@ static bool gtp_check_ms_ipv4(struct sk_buff *skb, struct pdp_ctx *pctx,
181191
iph = (struct iphdr *)(skb->data + hdrlen);
182192

183193
if (role == GTP_ROLE_SGSN)
184-
return iph->daddr == pctx->ms_addr_ip4.s_addr;
194+
return iph->daddr == pctx->ms.addr.s_addr;
185195
else
186-
return iph->saddr == pctx->ms_addr_ip4.s_addr;
196+
return iph->saddr == pctx->ms.addr.s_addr;
187197
}
188198

189199
/* Check if the inner IP address in this packet is assigned to any
@@ -292,13 +302,39 @@ static void gtp0_build_echo_msg(struct gtp0_header *hdr, __u8 msg_type)
292302
hdr->length = 0;
293303
}
294304

305+
static int gtp0_send_echo_resp_ip(struct gtp_dev *gtp, struct sk_buff *skb)
306+
{
307+
struct iphdr *iph = ip_hdr(skb);
308+
struct flowi4 fl4;
309+
struct rtable *rt;
310+
311+
/* find route to the sender,
312+
* src address becomes dst address and vice versa.
313+
*/
314+
rt = ip4_route_output_gtp(&fl4, gtp->sk0, iph->saddr, iph->daddr);
315+
if (IS_ERR(rt)) {
316+
netdev_dbg(gtp->dev, "no route for echo response from %pI4\n",
317+
&iph->saddr);
318+
return -1;
319+
}
320+
321+
udp_tunnel_xmit_skb(rt, gtp->sk0, skb,
322+
fl4.saddr, fl4.daddr,
323+
iph->tos,
324+
ip4_dst_hoplimit(&rt->dst),
325+
0,
326+
htons(GTP0_PORT), htons(GTP0_PORT),
327+
!net_eq(sock_net(gtp->sk1u),
328+
dev_net(gtp->dev)),
329+
false);
330+
331+
return 0;
332+
}
333+
295334
static int gtp0_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb)
296335
{
297336
struct gtp0_packet *gtp_pkt;
298337
struct gtp0_header *gtp0;
299-
struct rtable *rt;
300-
struct flowi4 fl4;
301-
struct iphdr *iph;
302338
__be16 seq;
303339

304340
gtp0 = (struct gtp0_header *)(skb->data + sizeof(struct udphdr));
@@ -325,27 +361,15 @@ static int gtp0_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb)
325361
gtp_pkt->ie.tag = GTPIE_RECOVERY;
326362
gtp_pkt->ie.val = gtp->restart_count;
327363

328-
iph = ip_hdr(skb);
329-
330-
/* find route to the sender,
331-
* src address becomes dst address and vice versa.
332-
*/
333-
rt = ip4_route_output_gtp(&fl4, gtp->sk0, iph->saddr, iph->daddr);
334-
if (IS_ERR(rt)) {
335-
netdev_dbg(gtp->dev, "no route for echo response from %pI4\n",
336-
&iph->saddr);
364+
switch (gtp->sk0->sk_family) {
365+
case AF_INET:
366+
if (gtp0_send_echo_resp_ip(gtp, skb) < 0)
367+
return -1;
368+
break;
369+
case AF_INET6:
337370
return -1;
338371
}
339372

340-
udp_tunnel_xmit_skb(rt, gtp->sk0, skb,
341-
fl4.saddr, fl4.daddr,
342-
iph->tos,
343-
ip4_dst_hoplimit(&rt->dst),
344-
0,
345-
htons(GTP0_PORT), htons(GTP0_PORT),
346-
!net_eq(sock_net(gtp->sk1u),
347-
dev_net(gtp->dev)),
348-
false);
349373
return 0;
350374
}
351375

@@ -360,8 +384,8 @@ static int gtp_genl_fill_echo(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
360384
goto failure;
361385

362386
if (nla_put_u32(skb, GTPA_VERSION, echo.gtp_version) ||
363-
nla_put_be32(skb, GTPA_PEER_ADDRESS, echo.peer_addr_ip4.s_addr) ||
364-
nla_put_be32(skb, GTPA_MS_ADDRESS, echo.ms_addr_ip4.s_addr))
387+
nla_put_be32(skb, GTPA_PEER_ADDRESS, echo.peer.addr.s_addr) ||
388+
nla_put_be32(skb, GTPA_MS_ADDRESS, echo.ms.addr.s_addr))
365389
goto failure;
366390

367391
genlmsg_end(skb, genlh);
@@ -372,23 +396,34 @@ static int gtp_genl_fill_echo(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
372396
return -EMSGSIZE;
373397
}
374398

399+
static void gtp0_handle_echo_resp_ip(struct sk_buff *skb, struct echo_info *echo)
400+
{
401+
struct iphdr *iph = ip_hdr(skb);
402+
403+
echo->ms.addr.s_addr = iph->daddr;
404+
echo->peer.addr.s_addr = iph->saddr;
405+
echo->gtp_version = GTP_V0;
406+
}
407+
375408
static int gtp0_handle_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb)
376409
{
377410
struct gtp0_header *gtp0;
378411
struct echo_info echo;
379412
struct sk_buff *msg;
380-
struct iphdr *iph;
381413
int ret;
382414

383415
gtp0 = (struct gtp0_header *)(skb->data + sizeof(struct udphdr));
384416

385417
if (!gtp0_validate_echo_hdr(gtp0))
386418
return -1;
387419

388-
iph = ip_hdr(skb);
389-
echo.ms_addr_ip4.s_addr = iph->daddr;
390-
echo.peer_addr_ip4.s_addr = iph->saddr;
391-
echo.gtp_version = GTP_V0;
420+
switch (gtp->sk0->sk_family) {
421+
case AF_INET:
422+
gtp0_handle_echo_resp_ip(skb, &echo);
423+
break;
424+
case AF_INET6:
425+
return -1;
426+
}
392427

393428
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
394429
if (!msg)
@@ -549,8 +584,8 @@ static int gtp1u_handle_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb)
549584
return -1;
550585

551586
iph = ip_hdr(skb);
552-
echo.ms_addr_ip4.s_addr = iph->daddr;
553-
echo.peer_addr_ip4.s_addr = iph->saddr;
587+
echo.ms.addr.s_addr = iph->daddr;
588+
echo.peer.addr.s_addr = iph->saddr;
554589
echo.gtp_version = GTP_V1;
555590

556591
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
@@ -801,9 +836,15 @@ static inline void gtp1_push_header(struct sk_buff *skb, struct pdp_ctx *pctx)
801836

802837
struct gtp_pktinfo {
803838
struct sock *sk;
804-
struct iphdr *iph;
805-
struct flowi4 fl4;
806-
struct rtable *rt;
839+
union {
840+
struct iphdr *iph;
841+
};
842+
union {
843+
struct flowi4 fl4;
844+
};
845+
union {
846+
struct rtable *rt;
847+
};
807848
struct pdp_ctx *pctx;
808849
struct net_device *dev;
809850
__be16 gtph_port;
@@ -864,18 +905,18 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
864905
}
865906
netdev_dbg(dev, "found PDP context %p\n", pctx);
866907

867-
rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->peer_addr_ip4.s_addr,
908+
rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->peer.addr.s_addr,
868909
inet_sk(pctx->sk)->inet_saddr);
869910
if (IS_ERR(rt)) {
870911
netdev_dbg(dev, "no route to SSGN %pI4\n",
871-
&pctx->peer_addr_ip4.s_addr);
912+
&pctx->peer.addr.s_addr);
872913
dev->stats.tx_carrier_errors++;
873914
goto err;
874915
}
875916

876917
if (rt->dst.dev == dev) {
877918
netdev_dbg(dev, "circular route to SSGN %pI4\n",
878-
&pctx->peer_addr_ip4.s_addr);
919+
&pctx->peer.addr.s_addr);
879920
dev->stats.collisions++;
880921
goto err_rt;
881922
}
@@ -977,11 +1018,11 @@ static const struct device_type gtp_type = {
9771018
.name = "gtp",
9781019
};
9791020

1021+
#define GTP_TH_MAXLEN (sizeof(struct udphdr) + sizeof(struct gtp0_header))
1022+
#define GTP_IPV4_MAXLEN (sizeof(struct iphdr) + GTP_TH_MAXLEN)
1023+
9801024
static void gtp_link_setup(struct net_device *dev)
9811025
{
982-
unsigned int max_gtp_header_len = sizeof(struct iphdr) +
983-
sizeof(struct udphdr) +
984-
sizeof(struct gtp0_header);
9851026
struct gtp_dev *gtp = netdev_priv(dev);
9861027

9871028
dev->netdev_ops = &gtp_netdev_ops;
@@ -990,7 +1031,7 @@ static void gtp_link_setup(struct net_device *dev)
9901031

9911032
dev->hard_header_len = 0;
9921033
dev->addr_len = 0;
993-
dev->mtu = ETH_DATA_LEN - max_gtp_header_len;
1034+
dev->mtu = ETH_DATA_LEN - GTP_IPV4_MAXLEN;
9941035

9951036
/* Zero header length. */
9961037
dev->type = ARPHRD_NONE;
@@ -1001,7 +1042,7 @@ static void gtp_link_setup(struct net_device *dev)
10011042
dev->features |= NETIF_F_LLTX;
10021043
netif_keep_dst(dev);
10031044

1004-
dev->needed_headroom = LL_MAX_HEADER + max_gtp_header_len;
1045+
dev->needed_headroom = LL_MAX_HEADER + GTP_IPV4_MAXLEN;
10051046
gtp->dev = dev;
10061047
}
10071048

@@ -1341,9 +1382,9 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info)
13411382
{
13421383
pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]);
13431384
pctx->af = AF_INET;
1344-
pctx->peer_addr_ip4.s_addr =
1385+
pctx->peer.addr.s_addr =
13451386
nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]);
1346-
pctx->ms_addr_ip4.s_addr =
1387+
pctx->ms.addr.s_addr =
13471388
nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
13481389

13491390
switch (pctx->gtp_version) {
@@ -1444,13 +1485,13 @@ static struct pdp_ctx *gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
14441485
switch (pctx->gtp_version) {
14451486
case GTP_V0:
14461487
netdev_dbg(dev, "GTPv0-U: new PDP ctx id=%llx ssgn=%pI4 ms=%pI4 (pdp=%p)\n",
1447-
pctx->u.v0.tid, &pctx->peer_addr_ip4,
1448-
&pctx->ms_addr_ip4, pctx);
1488+
pctx->u.v0.tid, &pctx->peer.addr,
1489+
&pctx->ms.addr, pctx);
14491490
break;
14501491
case GTP_V1:
14511492
netdev_dbg(dev, "GTPv1-U: new PDP ctx id=%x/%x ssgn=%pI4 ms=%pI4 (pdp=%p)\n",
14521493
pctx->u.v1.i_tei, pctx->u.v1.o_tei,
1453-
&pctx->peer_addr_ip4, &pctx->ms_addr_ip4, pctx);
1494+
&pctx->peer.addr, &pctx->ms.addr, pctx);
14541495
break;
14551496
}
14561497

@@ -1622,8 +1663,8 @@ static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
16221663

16231664
if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) ||
16241665
nla_put_u32(skb, GTPA_LINK, pctx->dev->ifindex) ||
1625-
nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr) ||
1626-
nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms_addr_ip4.s_addr))
1666+
nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer.addr.s_addr) ||
1667+
nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms.addr.s_addr))
16271668
goto nla_put_failure;
16281669

16291670
switch (pctx->gtp_version) {

0 commit comments

Comments
 (0)