56 |
56 |
u16 af;
|
57 |
57 |
|
58 |
58 |
struct in_addr ms_addr_ip4;
|
59 |
|
struct in_addr sgsn_addr_ip4;
|
|
59 |
|
|
60 |
union {
|
|
61 |
struct in6_addr ip6;
|
|
62 |
struct in_addr ip4;
|
|
63 |
} sgsn_addr;
|
60 |
64 |
|
61 |
65 |
struct sock *sk;
|
62 |
66 |
struct net_device *dev;
|
... | ... | |
411 |
415 |
return ip_route_output_key(sock_net(sk), fl4);
|
412 |
416 |
}
|
413 |
417 |
|
|
418 |
static struct dst_entry *ip6_route_output_gtp(struct flowi6 *fl6,
|
|
419 |
const struct sock *sk,
|
|
420 |
struct in6_addr *daddr)
|
|
421 |
{
|
|
422 |
memset(fl6, 0, sizeof(*fl6));
|
|
423 |
fl6->flowi6_oif = sk->sk_bound_dev_if;
|
|
424 |
fl6->daddr = *daddr;
|
|
425 |
fl6->saddr = inet6_sk(sk)->saddr;
|
|
426 |
fl6->flowi6_proto = sk->sk_protocol;
|
|
427 |
|
|
428 |
return ip6_route_output(sock_net(sk), NULL, fl6);
|
|
429 |
}
|
|
430 |
|
414 |
431 |
static inline void gtp0_push_header(struct sk_buff *skb, struct pdp_ctx *pctx)
|
415 |
432 |
{
|
416 |
433 |
int payload_len = skb->len;
|
... | ... | |
515 |
532 |
__u8 tos;
|
516 |
533 |
|
517 |
534 |
/* Prepend PDP header with TEI/TID from PDP ctx. */
|
518 |
|
rt = dst_cache_get_ip4(&pctx->dst_cache, &pctx->sgsn_addr_ip4.s_addr);
|
|
535 |
rt = dst_cache_get_ip4(&pctx->dst_cache, &pctx->sgsn_addr.ip4.s_addr);
|
519 |
536 |
if (!rt) {
|
520 |
|
rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->sgsn_addr_ip4.s_addr);
|
|
537 |
rt = ip4_route_output_gtp(&fl4, pctx->sk, pctx->sgsn_addr.ip4.s_addr);
|
521 |
538 |
if (IS_ERR(rt)) {
|
522 |
539 |
netdev_dbg(dev, "no route to SSGN %pI4\n",
|
523 |
|
&pctx->sgsn_addr_ip4.s_addr);
|
|
540 |
&pctx->sgsn_addr.ip4.s_addr);
|
524 |
541 |
dev->stats.tx_carrier_errors++;
|
525 |
542 |
goto err;
|
526 |
543 |
}
|
527 |
544 |
|
528 |
545 |
dst_cache_set_ip4(&pctx->dst_cache, &rt->dst,
|
529 |
|
pctx->sgsn_addr_ip4.s_addr);
|
|
546 |
pctx->sgsn_addr.ip4.s_addr);
|
530 |
547 |
}
|
531 |
548 |
|
532 |
549 |
if (rt->dst.dev == dev) {
|
533 |
550 |
netdev_dbg(dev, "circular route to SSGN %pI4\n",
|
534 |
|
&pctx->sgsn_addr_ip4.s_addr);
|
|
551 |
&pctx->sgsn_addr.ip4.s_addr);
|
535 |
552 |
dev->stats.collisions++;
|
536 |
553 |
goto err_rt;
|
537 |
554 |
}
|
... | ... | |
557 |
574 |
return -EBADMSG;
|
558 |
575 |
}
|
559 |
576 |
|
|
577 |
static int gtp_dev_xmit_ip6(struct pdp_ctx *pctx, struct sk_buff *skb,
|
|
578 |
struct net_device *dev)
|
|
579 |
{
|
|
580 |
const struct iphdr *iph = ip_hdr(skb);
|
|
581 |
struct dst_entry *ndst;
|
|
582 |
struct flowi6 fl6;
|
|
583 |
__be16 gtph_port;
|
|
584 |
|
|
585 |
/*
|
|
586 |
* Prepend PDP header with TEI/TID from PDP ctx.
|
|
587 |
*/
|
|
588 |
ndst = ip6_route_output_gtp(&fl6, pctx->sk, &pctx->sgsn_addr.ip6);
|
|
589 |
if (ndst->error) {
|
|
590 |
netdev_dbg(dev, "no route to SSGN %pI6\n",
|
|
591 |
&pctx->sgsn_addr.ip6.s6_addr);
|
|
592 |
dev->stats.tx_carrier_errors++;
|
|
593 |
goto err;
|
|
594 |
}
|
|
595 |
|
|
596 |
/* There is a routing loop. */
|
|
597 |
if (ndst->dev == dev) {
|
|
598 |
netdev_dbg(dev, "circular route to SSGN %pI6\n",
|
|
599 |
&pctx->sgsn_addr.ip6);
|
|
600 |
dev->stats.collisions++;
|
|
601 |
goto err_dst;
|
|
602 |
}
|
|
603 |
|
|
604 |
if (gtp_update_pmtu(pctx, skb, dev, ndst, iph->frag_off,
|
|
605 |
sizeof(struct ipv6hdr) + sizeof(struct udphdr), iph))
|
|
606 |
goto err_dst;
|
|
607 |
|
|
608 |
skb_dst_drop(skb);
|
|
609 |
gtp_push_header(skb, pctx);
|
|
610 |
|
|
611 |
gtph_port = get_dst_port(pctx);
|
|
612 |
|
|
613 |
udp_tunnel6_xmit_skb(ndst, pctx->sk, skb, ndst->dev, &fl6.saddr,
|
|
614 |
&fl6.daddr, 0, ip6_dst_hoplimit(ndst), 0,
|
|
615 |
gtph_port, gtph_port, false);
|
|
616 |
|
|
617 |
return 0;
|
|
618 |
|
|
619 |
err_dst:
|
|
620 |
dst_release(ndst);
|
|
621 |
err:
|
|
622 |
return -EBADMSG;
|
|
623 |
}
|
|
624 |
|
560 |
625 |
static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev)
|
561 |
626 |
{
|
562 |
627 |
struct pdp_ctx *pctx;
|
... | ... | |
578 |
643 |
case AF_INET:
|
579 |
644 |
err = gtp_dev_xmit_ip4(pctx, skb, dev);
|
580 |
645 |
break;
|
|
646 |
case AF_INET6:
|
|
647 |
err = gtp_dev_xmit_ip6(pctx, skb, dev);
|
|
648 |
break;
|
581 |
649 |
default:
|
582 |
650 |
err = -EOPNOTSUPP;
|
583 |
651 |
break;
|
... | ... | |
871 |
939 |
{
|
872 |
940 |
pctx->gtp_version = nla_get_u32(info->attrs[GTPA_VERSION]);
|
873 |
941 |
pctx->af = AF_INET;
|
874 |
|
pctx->sgsn_addr_ip4.s_addr =
|
875 |
|
nla_get_be32(info->attrs[GTPA_SGSN_ADDRESS]);
|
|
942 |
|
|
943 |
if (info->attrs[GTPA_SGSN_ADDRESS]) {
|
|
944 |
pctx->sgsn_addr.ip4.s_addr =
|
|
945 |
nla_get_be32(info->attrs[GTPA_SGSN_ADDRESS]);
|
|
946 |
} else if (info->attrs[GTPA_SGSN_ADDRESS6]) {
|
|
947 |
pctx->sgsn_addr.ip6 =
|
|
948 |
nla_get_in6_addr(info->attrs[GTPA_SGSN_ADDRESS6]);
|
|
949 |
}
|
|
950 |
|
876 |
951 |
pctx->ms_addr_ip4.s_addr =
|
877 |
952 |
nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
|
878 |
953 |
|
... | ... | |
911 |
986 |
if (!gsk)
|
912 |
987 |
return -ENODEV;
|
913 |
988 |
|
|
989 |
switch (sk->sk_family) {
|
|
990 |
case AF_INET:
|
|
991 |
if (!info->attrs[GTPA_SGSN_ADDRESS])
|
|
992 |
return -EINVAL;
|
|
993 |
|
|
994 |
break;
|
|
995 |
case AF_INET6:
|
|
996 |
if (!info->attrs[GTPA_SGSN_ADDRESS6])
|
|
997 |
return -EINVAL;
|
|
998 |
|
|
999 |
break;
|
|
1000 |
|
|
1001 |
default:
|
|
1002 |
return -EINVAL;
|
|
1003 |
}
|
|
1004 |
|
914 |
1005 |
ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
|
915 |
1006 |
hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size;
|
916 |
1007 |
|
... | ... | |
976 |
1067 |
switch (pctx->gtp_version) {
|
977 |
1068 |
case GTP_V0:
|
978 |
1069 |
netdev_dbg(dev, "GTPv0-U: new PDP ctx id=%llx ssgn=%pI4 ms=%pI4 (pdp=%p)\n",
|
979 |
|
pctx->u.v0.tid, &pctx->sgsn_addr_ip4,
|
|
1070 |
pctx->u.v0.tid, &pctx->sgsn_addr.ip4,
|
980 |
1071 |
&pctx->ms_addr_ip4, pctx);
|
981 |
1072 |
break;
|
982 |
1073 |
case GTP_V1:
|
983 |
1074 |
netdev_dbg(dev, "GTPv1-U: new PDP ctx id=%x/%x ssgn=%pI4 ms=%pI4 (pdp=%p)\n",
|
984 |
1075 |
pctx->u.v1.i_tei, pctx->u.v1.o_tei,
|
985 |
|
&pctx->sgsn_addr_ip4, &pctx->ms_addr_ip4, pctx);
|
|
1076 |
&pctx->sgsn_addr.ip4, &pctx->ms_addr_ip4, pctx);
|
986 |
1077 |
break;
|
987 |
1078 |
}
|
988 |
1079 |
|
... | ... | |
1013 |
1104 |
struct gtp_dev *gtp;
|
1014 |
1105 |
int err;
|
1015 |
1106 |
|
|
1107 |
|
|
1108 |
if (info->attrs[GTPA_SGSN_ADDRESS] && info->attrs[GTPA_SGSN_ADDRESS6])
|
|
1109 |
return -EINVAL;
|
|
1110 |
|
1016 |
1111 |
if (!info->attrs[GTPA_VERSION] ||
|
1017 |
1112 |
!info->attrs[GTPA_LINK] ||
|
1018 |
1113 |
!info->attrs[GTPA_SGSN_ADDRESS] ||
|
... | ... | |
1196 |
1291 |
goto nlmsg_failure;
|
1197 |
1292 |
|
1198 |
1293 |
if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) ||
|
1199 |
|
nla_put_be32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr_ip4.s_addr) ||
|
|
1294 |
nla_put_be32(skb, GTPA_SGSN_ADDRESS, pctx->sgsn_addr.ip4.s_addr) ||
|
1200 |
1295 |
nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms_addr_ip4.s_addr))
|
1201 |
1296 |
goto nla_put_failure;
|
1202 |
1297 |
|
... | ... | |
1367 |
1462 |
[GTPA_VERSION] = { .type = NLA_U32, },
|
1368 |
1463 |
[GTPA_TID] = { .type = NLA_U64, },
|
1369 |
1464 |
[GTPA_SGSN_ADDRESS] = { .type = NLA_U32, },
|
|
1465 |
[GTPA_SGSN_ADDRESS6] = { .len = sizeof(struct in6_addr) },
|
1370 |
1466 |
[GTPA_MS_ADDRESS] = { .type = NLA_U32, },
|
1371 |
1467 |
[GTPA_FLOW] = { .type = NLA_U16, },
|
1372 |
1468 |
[GTPA_NET_NS_FD] = { .type = NLA_U32, },
|