aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWANG Cong <xiyou.wangcong@gmail.com>2015-04-10 15:00:30 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-12 21:25:13 -0400
commit7a6c8c34e5b71ac50e39588e20b39494a9e1d8e5 (patch)
tree3593ce71a5a16427c35823a073072292a0d2a704
parent02d793c5bbebf2c750da03df4c950fc4e8e8a5a7 (diff)
fou: implement FOU_CMD_GET
Cc: Tom Herbert <tom@herbertland.com> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/uapi/linux/fou.h1
-rw-r--r--net/ipv4/fou.c109
2 files changed, 110 insertions, 0 deletions
diff --git a/include/uapi/linux/fou.h b/include/uapi/linux/fou.h
index c303588bb767..d2947c52dc67 100644
--- a/include/uapi/linux/fou.h
+++ b/include/uapi/linux/fou.h
@@ -25,6 +25,7 @@ enum {
25 FOU_CMD_UNSPEC, 25 FOU_CMD_UNSPEC,
26 FOU_CMD_ADD, 26 FOU_CMD_ADD,
27 FOU_CMD_DEL, 27 FOU_CMD_DEL,
28 FOU_CMD_GET,
28 29
29 __FOU_CMD_MAX, 30 __FOU_CMD_MAX,
30}; 31};
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index c244b1a65787..263710259774 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -21,6 +21,7 @@ struct fou {
21 u8 protocol; 21 u8 protocol;
22 u8 flags; 22 u8 flags;
23 __be16 port; 23 __be16 port;
24 u16 type;
24 struct udp_offload udp_offloads; 25 struct udp_offload udp_offloads;
25 struct list_head list; 26 struct list_head list;
26}; 27};
@@ -487,6 +488,8 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
487 goto error; 488 goto error;
488 } 489 }
489 490
491 fou->type = cfg->type;
492
490 udp_sk(sk)->encap_type = 1; 493 udp_sk(sk)->encap_type = 1;
491 udp_encap_enable(); 494 udp_encap_enable();
492 495
@@ -617,6 +620,106 @@ static int fou_nl_cmd_rm_port(struct sk_buff *skb, struct genl_info *info)
617 return fou_destroy(net, &cfg); 620 return fou_destroy(net, &cfg);
618} 621}
619 622
623static int fou_fill_info(struct fou *fou, struct sk_buff *msg)
624{
625 if (nla_put_u8(msg, FOU_ATTR_AF, fou->sock->sk->sk_family) ||
626 nla_put_be16(msg, FOU_ATTR_PORT, fou->port) ||
627 nla_put_u8(msg, FOU_ATTR_IPPROTO, fou->protocol) ||
628 nla_put_u8(msg, FOU_ATTR_TYPE, fou->type))
629 return -1;
630
631 if (fou->flags & FOU_F_REMCSUM_NOPARTIAL)
632 if (nla_put_flag(msg, FOU_ATTR_REMCSUM_NOPARTIAL))
633 return -1;
634 return 0;
635}
636
637static int fou_dump_info(struct fou *fou, u32 portid, u32 seq,
638 u32 flags, struct sk_buff *skb, u8 cmd)
639{
640 void *hdr;
641
642 hdr = genlmsg_put(skb, portid, seq, &fou_nl_family, flags, cmd);
643 if (!hdr)
644 return -ENOMEM;
645
646 if (fou_fill_info(fou, skb) < 0)
647 goto nla_put_failure;
648
649 genlmsg_end(skb, hdr);
650 return 0;
651
652nla_put_failure:
653 genlmsg_cancel(skb, hdr);
654 return -EMSGSIZE;
655}
656
657static int fou_nl_cmd_get_port(struct sk_buff *skb, struct genl_info *info)
658{
659 struct net *net = genl_info_net(info);
660 struct fou_net *fn = net_generic(net, fou_net_id);
661 struct sk_buff *msg;
662 struct fou_cfg cfg;
663 struct fou *fout;
664 __be16 port;
665 int ret;
666
667 ret = parse_nl_config(info, &cfg);
668 if (ret)
669 return ret;
670 port = cfg.udp_config.local_udp_port;
671 if (port == 0)
672 return -EINVAL;
673
674 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
675 if (!msg)
676 return -ENOMEM;
677
678 ret = -ESRCH;
679 mutex_lock(&fn->fou_lock);
680 list_for_each_entry(fout, &fn->fou_list, list) {
681 if (port == fout->port) {
682 ret = fou_dump_info(fout, info->snd_portid,
683 info->snd_seq, 0, msg,
684 info->genlhdr->cmd);
685 break;
686 }
687 }
688 mutex_unlock(&fn->fou_lock);
689 if (ret < 0)
690 goto out_free;
691
692 return genlmsg_reply(msg, info);
693
694out_free:
695 nlmsg_free(msg);
696 return ret;
697}
698
699static int fou_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
700{
701 struct net *net = sock_net(skb->sk);
702 struct fou_net *fn = net_generic(net, fou_net_id);
703 struct fou *fout;
704 int idx = 0, ret;
705
706 mutex_lock(&fn->fou_lock);
707 list_for_each_entry(fout, &fn->fou_list, list) {
708 if (idx++ < cb->args[0])
709 continue;
710 ret = fou_dump_info(fout, NETLINK_CB(cb->skb).portid,
711 cb->nlh->nlmsg_seq, NLM_F_MULTI,
712 skb, FOU_CMD_GET);
713 if (ret)
714 goto done;
715 }
716 mutex_unlock(&fn->fou_lock);
717
718done:
719 cb->args[0] = idx;
720 return skb->len;
721}
722
620static const struct genl_ops fou_nl_ops[] = { 723static const struct genl_ops fou_nl_ops[] = {
621 { 724 {
622 .cmd = FOU_CMD_ADD, 725 .cmd = FOU_CMD_ADD,
@@ -630,6 +733,12 @@ static const struct genl_ops fou_nl_ops[] = {
630 .policy = fou_nl_policy, 733 .policy = fou_nl_policy,
631 .flags = GENL_ADMIN_PERM, 734 .flags = GENL_ADMIN_PERM,
632 }, 735 },
736 {
737 .cmd = FOU_CMD_GET,
738 .doit = fou_nl_cmd_get_port,
739 .dumpit = fou_nl_dump,
740 .policy = fou_nl_policy,
741 },
633}; 742};
634 743
635size_t fou_encap_hlen(struct ip_tunnel_encap *e) 744size_t fou_encap_hlen(struct ip_tunnel_encap *e)