aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/netlink_compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/netlink_compat.c')
-rw-r--r--net/tipc/netlink_compat.c137
1 files changed, 114 insertions, 23 deletions
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index ce9121e8e990..53e0fee80086 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -55,6 +55,7 @@ struct tipc_nl_compat_msg {
55 int rep_type; 55 int rep_type;
56 int rep_size; 56 int rep_size;
57 int req_type; 57 int req_type;
58 struct net *net;
58 struct sk_buff *rep; 59 struct sk_buff *rep;
59 struct tlv_desc *req; 60 struct tlv_desc *req;
60 struct sock *dst_sk; 61 struct sock *dst_sk;
@@ -68,7 +69,8 @@ struct tipc_nl_compat_cmd_dump {
68 69
69struct tipc_nl_compat_cmd_doit { 70struct tipc_nl_compat_cmd_doit {
70 int (*doit)(struct sk_buff *skb, struct genl_info *info); 71 int (*doit)(struct sk_buff *skb, struct genl_info *info);
71 int (*transcode)(struct sk_buff *skb, struct tipc_nl_compat_msg *msg); 72 int (*transcode)(struct tipc_nl_compat_cmd_doit *cmd,
73 struct sk_buff *skb, struct tipc_nl_compat_msg *msg);
72}; 74};
73 75
74static int tipc_skb_tailroom(struct sk_buff *skb) 76static int tipc_skb_tailroom(struct sk_buff *skb)
@@ -281,7 +283,7 @@ static int __tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd,
281 if (!trans_buf) 283 if (!trans_buf)
282 return -ENOMEM; 284 return -ENOMEM;
283 285
284 err = (*cmd->transcode)(trans_buf, msg); 286 err = (*cmd->transcode)(cmd, trans_buf, msg);
285 if (err) 287 if (err)
286 goto trans_out; 288 goto trans_out;
287 289
@@ -353,7 +355,8 @@ static int tipc_nl_compat_bearer_dump(struct tipc_nl_compat_msg *msg,
353 nla_len(bearer[TIPC_NLA_BEARER_NAME])); 355 nla_len(bearer[TIPC_NLA_BEARER_NAME]));
354} 356}
355 357
356static int tipc_nl_compat_bearer_enable(struct sk_buff *skb, 358static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
359 struct sk_buff *skb,
357 struct tipc_nl_compat_msg *msg) 360 struct tipc_nl_compat_msg *msg)
358{ 361{
359 struct nlattr *prop; 362 struct nlattr *prop;
@@ -385,7 +388,8 @@ static int tipc_nl_compat_bearer_enable(struct sk_buff *skb,
385 return 0; 388 return 0;
386} 389}
387 390
388static int tipc_nl_compat_bearer_disable(struct sk_buff *skb, 391static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
392 struct sk_buff *skb,
389 struct tipc_nl_compat_msg *msg) 393 struct tipc_nl_compat_msg *msg)
390{ 394{
391 char *name; 395 char *name;
@@ -576,11 +580,81 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg,
576 &link_info, sizeof(link_info)); 580 &link_info, sizeof(link_info));
577} 581}
578 582
579static int tipc_nl_compat_link_set(struct sk_buff *skb, 583static int __tipc_add_link_prop(struct sk_buff *skb,
580 struct tipc_nl_compat_msg *msg) 584 struct tipc_nl_compat_msg *msg,
585 struct tipc_link_config *lc)
586{
587 switch (msg->cmd) {
588 case TIPC_CMD_SET_LINK_PRI:
589 return nla_put_u32(skb, TIPC_NLA_PROP_PRIO, ntohl(lc->value));
590 case TIPC_CMD_SET_LINK_TOL:
591 return nla_put_u32(skb, TIPC_NLA_PROP_TOL, ntohl(lc->value));
592 case TIPC_CMD_SET_LINK_WINDOW:
593 return nla_put_u32(skb, TIPC_NLA_PROP_WIN, ntohl(lc->value));
594 }
595
596 return -EINVAL;
597}
598
599static int tipc_nl_compat_media_set(struct sk_buff *skb,
600 struct tipc_nl_compat_msg *msg)
581{ 601{
582 struct nlattr *link;
583 struct nlattr *prop; 602 struct nlattr *prop;
603 struct nlattr *media;
604 struct tipc_link_config *lc;
605
606 lc = (struct tipc_link_config *)TLV_DATA(msg->req);
607
608 media = nla_nest_start(skb, TIPC_NLA_MEDIA);
609 if (!media)
610 return -EMSGSIZE;
611
612 if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name))
613 return -EMSGSIZE;
614
615 prop = nla_nest_start(skb, TIPC_NLA_MEDIA_PROP);
616 if (!prop)
617 return -EMSGSIZE;
618
619 __tipc_add_link_prop(skb, msg, lc);
620 nla_nest_end(skb, prop);
621 nla_nest_end(skb, media);
622
623 return 0;
624}
625
626static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
627 struct tipc_nl_compat_msg *msg)
628{
629 struct nlattr *prop;
630 struct nlattr *bearer;
631 struct tipc_link_config *lc;
632
633 lc = (struct tipc_link_config *)TLV_DATA(msg->req);
634
635 bearer = nla_nest_start(skb, TIPC_NLA_BEARER);
636 if (!bearer)
637 return -EMSGSIZE;
638
639 if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name))
640 return -EMSGSIZE;
641
642 prop = nla_nest_start(skb, TIPC_NLA_BEARER_PROP);
643 if (!prop)
644 return -EMSGSIZE;
645
646 __tipc_add_link_prop(skb, msg, lc);
647 nla_nest_end(skb, prop);
648 nla_nest_end(skb, bearer);
649
650 return 0;
651}
652
653static int __tipc_nl_compat_link_set(struct sk_buff *skb,
654 struct tipc_nl_compat_msg *msg)
655{
656 struct nlattr *prop;
657 struct nlattr *link;
584 struct tipc_link_config *lc; 658 struct tipc_link_config *lc;
585 659
586 lc = (struct tipc_link_config *)TLV_DATA(msg->req); 660 lc = (struct tipc_link_config *)TLV_DATA(msg->req);
@@ -596,24 +670,40 @@ static int tipc_nl_compat_link_set(struct sk_buff *skb,
596 if (!prop) 670 if (!prop)
597 return -EMSGSIZE; 671 return -EMSGSIZE;
598 672
599 if (msg->cmd == TIPC_CMD_SET_LINK_PRI) { 673 __tipc_add_link_prop(skb, msg, lc);
600 if (nla_put_u32(skb, TIPC_NLA_PROP_PRIO, ntohl(lc->value)))
601 return -EMSGSIZE;
602 } else if (msg->cmd == TIPC_CMD_SET_LINK_TOL) {
603 if (nla_put_u32(skb, TIPC_NLA_PROP_TOL, ntohl(lc->value)))
604 return -EMSGSIZE;
605 } else if (msg->cmd == TIPC_CMD_SET_LINK_WINDOW) {
606 if (nla_put_u32(skb, TIPC_NLA_PROP_WIN, ntohl(lc->value)))
607 return -EMSGSIZE;
608 }
609
610 nla_nest_end(skb, prop); 674 nla_nest_end(skb, prop);
611 nla_nest_end(skb, link); 675 nla_nest_end(skb, link);
612 676
613 return 0; 677 return 0;
614} 678}
615 679
616static int tipc_nl_compat_link_reset_stats(struct sk_buff *skb, 680static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd,
681 struct sk_buff *skb,
682 struct tipc_nl_compat_msg *msg)
683{
684 struct tipc_link_config *lc;
685 struct tipc_bearer *bearer;
686 struct tipc_media *media;
687
688 lc = (struct tipc_link_config *)TLV_DATA(msg->req);
689
690 media = tipc_media_find(lc->name);
691 if (media) {
692 cmd->doit = &tipc_nl_media_set;
693 return tipc_nl_compat_media_set(skb, msg);
694 }
695
696 bearer = tipc_bearer_find(msg->net, lc->name);
697 if (bearer) {
698 cmd->doit = &tipc_nl_bearer_set;
699 return tipc_nl_compat_bearer_set(skb, msg);
700 }
701
702 return __tipc_nl_compat_link_set(skb, msg);
703}
704
705static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
706 struct sk_buff *skb,
617 struct tipc_nl_compat_msg *msg) 707 struct tipc_nl_compat_msg *msg)
618{ 708{
619 char *name; 709 char *name;
@@ -851,7 +941,8 @@ static int tipc_nl_compat_node_dump(struct tipc_nl_compat_msg *msg,
851 sizeof(node_info)); 941 sizeof(node_info));
852} 942}
853 943
854static int tipc_nl_compat_net_set(struct sk_buff *skb, 944static int tipc_nl_compat_net_set(struct tipc_nl_compat_cmd_doit *cmd,
945 struct sk_buff *skb,
855 struct tipc_nl_compat_msg *msg) 946 struct tipc_nl_compat_msg *msg)
856{ 947{
857 u32 val; 948 u32 val;
@@ -1007,7 +1098,6 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
1007 struct nlmsghdr *req_nlh; 1098 struct nlmsghdr *req_nlh;
1008 struct nlmsghdr *rep_nlh; 1099 struct nlmsghdr *rep_nlh;
1009 struct tipc_genlmsghdr *req_userhdr = info->userhdr; 1100 struct tipc_genlmsghdr *req_userhdr = info->userhdr;
1010 struct net *net = genl_info_net(info);
1011 1101
1012 memset(&msg, 0, sizeof(msg)); 1102 memset(&msg, 0, sizeof(msg));
1013 1103
@@ -1015,6 +1105,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
1015 msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN; 1105 msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN;
1016 msg.cmd = req_userhdr->cmd; 1106 msg.cmd = req_userhdr->cmd;
1017 msg.dst_sk = info->dst_sk; 1107 msg.dst_sk = info->dst_sk;
1108 msg.net = genl_info_net(info);
1018 1109
1019 if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) { 1110 if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) {
1020 msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN); 1111 msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN);
@@ -1030,7 +1121,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
1030 } 1121 }
1031 1122
1032 err = tipc_nl_compat_handle(&msg); 1123 err = tipc_nl_compat_handle(&msg);
1033 if (err == -EOPNOTSUPP) 1124 if ((err == -EOPNOTSUPP) || (err == -EPERM))
1034 msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); 1125 msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
1035 else if (err == -EINVAL) 1126 else if (err == -EINVAL)
1036 msg.rep = tipc_get_err_tlv(TIPC_CFG_TLV_ERROR); 1127 msg.rep = tipc_get_err_tlv(TIPC_CFG_TLV_ERROR);
@@ -1043,7 +1134,7 @@ send:
1043 rep_nlh = nlmsg_hdr(msg.rep); 1134 rep_nlh = nlmsg_hdr(msg.rep);
1044 memcpy(rep_nlh, info->nlhdr, len); 1135 memcpy(rep_nlh, info->nlhdr, len);
1045 rep_nlh->nlmsg_len = msg.rep->len; 1136 rep_nlh->nlmsg_len = msg.rep->len;
1046 genlmsg_unicast(net, msg.rep, NETLINK_CB(skb).portid); 1137 genlmsg_unicast(msg.net, msg.rep, NETLINK_CB(skb).portid);
1047 1138
1048 return err; 1139 return err;
1049} 1140}