|
@@ -55,6 +55,7 @@ struct tipc_nl_compat_msg {
|
|
|
int rep_type;
|
|
|
int rep_size;
|
|
|
int req_type;
|
|
|
+ struct net *net;
|
|
|
struct sk_buff *rep;
|
|
|
struct tlv_desc *req;
|
|
|
struct sock *dst_sk;
|
|
@@ -68,7 +69,8 @@ struct tipc_nl_compat_cmd_dump {
|
|
|
|
|
|
struct tipc_nl_compat_cmd_doit {
|
|
|
int (*doit)(struct sk_buff *skb, struct genl_info *info);
|
|
|
- int (*transcode)(struct sk_buff *skb, struct tipc_nl_compat_msg *msg);
|
|
|
+ int (*transcode)(struct tipc_nl_compat_cmd_doit *cmd,
|
|
|
+ struct sk_buff *skb, struct tipc_nl_compat_msg *msg);
|
|
|
};
|
|
|
|
|
|
static 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,
|
|
|
if (!trans_buf)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- err = (*cmd->transcode)(trans_buf, msg);
|
|
|
+ err = (*cmd->transcode)(cmd, trans_buf, msg);
|
|
|
if (err)
|
|
|
goto trans_out;
|
|
|
|
|
@@ -353,7 +355,8 @@ static int tipc_nl_compat_bearer_dump(struct tipc_nl_compat_msg *msg,
|
|
|
nla_len(bearer[TIPC_NLA_BEARER_NAME]));
|
|
|
}
|
|
|
|
|
|
-static int tipc_nl_compat_bearer_enable(struct sk_buff *skb,
|
|
|
+static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
|
|
|
+ struct sk_buff *skb,
|
|
|
struct tipc_nl_compat_msg *msg)
|
|
|
{
|
|
|
struct nlattr *prop;
|
|
@@ -385,7 +388,8 @@ static int tipc_nl_compat_bearer_enable(struct sk_buff *skb,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int tipc_nl_compat_bearer_disable(struct sk_buff *skb,
|
|
|
+static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
|
|
|
+ struct sk_buff *skb,
|
|
|
struct tipc_nl_compat_msg *msg)
|
|
|
{
|
|
|
char *name;
|
|
@@ -576,11 +580,81 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg,
|
|
|
&link_info, sizeof(link_info));
|
|
|
}
|
|
|
|
|
|
-static int tipc_nl_compat_link_set(struct sk_buff *skb,
|
|
|
- struct tipc_nl_compat_msg *msg)
|
|
|
+static int __tipc_add_link_prop(struct sk_buff *skb,
|
|
|
+ struct tipc_nl_compat_msg *msg,
|
|
|
+ struct tipc_link_config *lc)
|
|
|
+{
|
|
|
+ switch (msg->cmd) {
|
|
|
+ case TIPC_CMD_SET_LINK_PRI:
|
|
|
+ return nla_put_u32(skb, TIPC_NLA_PROP_PRIO, ntohl(lc->value));
|
|
|
+ case TIPC_CMD_SET_LINK_TOL:
|
|
|
+ return nla_put_u32(skb, TIPC_NLA_PROP_TOL, ntohl(lc->value));
|
|
|
+ case TIPC_CMD_SET_LINK_WINDOW:
|
|
|
+ return nla_put_u32(skb, TIPC_NLA_PROP_WIN, ntohl(lc->value));
|
|
|
+ }
|
|
|
+
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
+static int tipc_nl_compat_media_set(struct sk_buff *skb,
|
|
|
+ struct tipc_nl_compat_msg *msg)
|
|
|
{
|
|
|
- struct nlattr *link;
|
|
|
struct nlattr *prop;
|
|
|
+ struct nlattr *media;
|
|
|
+ struct tipc_link_config *lc;
|
|
|
+
|
|
|
+ lc = (struct tipc_link_config *)TLV_DATA(msg->req);
|
|
|
+
|
|
|
+ media = nla_nest_start(skb, TIPC_NLA_MEDIA);
|
|
|
+ if (!media)
|
|
|
+ return -EMSGSIZE;
|
|
|
+
|
|
|
+ if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name))
|
|
|
+ return -EMSGSIZE;
|
|
|
+
|
|
|
+ prop = nla_nest_start(skb, TIPC_NLA_MEDIA_PROP);
|
|
|
+ if (!prop)
|
|
|
+ return -EMSGSIZE;
|
|
|
+
|
|
|
+ __tipc_add_link_prop(skb, msg, lc);
|
|
|
+ nla_nest_end(skb, prop);
|
|
|
+ nla_nest_end(skb, media);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
|
|
|
+ struct tipc_nl_compat_msg *msg)
|
|
|
+{
|
|
|
+ struct nlattr *prop;
|
|
|
+ struct nlattr *bearer;
|
|
|
+ struct tipc_link_config *lc;
|
|
|
+
|
|
|
+ lc = (struct tipc_link_config *)TLV_DATA(msg->req);
|
|
|
+
|
|
|
+ bearer = nla_nest_start(skb, TIPC_NLA_BEARER);
|
|
|
+ if (!bearer)
|
|
|
+ return -EMSGSIZE;
|
|
|
+
|
|
|
+ if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name))
|
|
|
+ return -EMSGSIZE;
|
|
|
+
|
|
|
+ prop = nla_nest_start(skb, TIPC_NLA_BEARER_PROP);
|
|
|
+ if (!prop)
|
|
|
+ return -EMSGSIZE;
|
|
|
+
|
|
|
+ __tipc_add_link_prop(skb, msg, lc);
|
|
|
+ nla_nest_end(skb, prop);
|
|
|
+ nla_nest_end(skb, bearer);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int __tipc_nl_compat_link_set(struct sk_buff *skb,
|
|
|
+ struct tipc_nl_compat_msg *msg)
|
|
|
+{
|
|
|
+ struct nlattr *prop;
|
|
|
+ struct nlattr *link;
|
|
|
struct tipc_link_config *lc;
|
|
|
|
|
|
lc = (struct tipc_link_config *)TLV_DATA(msg->req);
|
|
@@ -596,24 +670,40 @@ static int tipc_nl_compat_link_set(struct sk_buff *skb,
|
|
|
if (!prop)
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
- if (msg->cmd == TIPC_CMD_SET_LINK_PRI) {
|
|
|
- if (nla_put_u32(skb, TIPC_NLA_PROP_PRIO, ntohl(lc->value)))
|
|
|
- return -EMSGSIZE;
|
|
|
- } else if (msg->cmd == TIPC_CMD_SET_LINK_TOL) {
|
|
|
- if (nla_put_u32(skb, TIPC_NLA_PROP_TOL, ntohl(lc->value)))
|
|
|
- return -EMSGSIZE;
|
|
|
- } else if (msg->cmd == TIPC_CMD_SET_LINK_WINDOW) {
|
|
|
- if (nla_put_u32(skb, TIPC_NLA_PROP_WIN, ntohl(lc->value)))
|
|
|
- return -EMSGSIZE;
|
|
|
- }
|
|
|
-
|
|
|
+ __tipc_add_link_prop(skb, msg, lc);
|
|
|
nla_nest_end(skb, prop);
|
|
|
nla_nest_end(skb, link);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int tipc_nl_compat_link_reset_stats(struct sk_buff *skb,
|
|
|
+static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd,
|
|
|
+ struct sk_buff *skb,
|
|
|
+ struct tipc_nl_compat_msg *msg)
|
|
|
+{
|
|
|
+ struct tipc_link_config *lc;
|
|
|
+ struct tipc_bearer *bearer;
|
|
|
+ struct tipc_media *media;
|
|
|
+
|
|
|
+ lc = (struct tipc_link_config *)TLV_DATA(msg->req);
|
|
|
+
|
|
|
+ media = tipc_media_find(lc->name);
|
|
|
+ if (media) {
|
|
|
+ cmd->doit = &tipc_nl_media_set;
|
|
|
+ return tipc_nl_compat_media_set(skb, msg);
|
|
|
+ }
|
|
|
+
|
|
|
+ bearer = tipc_bearer_find(msg->net, lc->name);
|
|
|
+ if (bearer) {
|
|
|
+ cmd->doit = &tipc_nl_bearer_set;
|
|
|
+ return tipc_nl_compat_bearer_set(skb, msg);
|
|
|
+ }
|
|
|
+
|
|
|
+ return __tipc_nl_compat_link_set(skb, msg);
|
|
|
+}
|
|
|
+
|
|
|
+static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
|
|
|
+ struct sk_buff *skb,
|
|
|
struct tipc_nl_compat_msg *msg)
|
|
|
{
|
|
|
char *name;
|
|
@@ -851,7 +941,8 @@ static int tipc_nl_compat_node_dump(struct tipc_nl_compat_msg *msg,
|
|
|
sizeof(node_info));
|
|
|
}
|
|
|
|
|
|
-static int tipc_nl_compat_net_set(struct sk_buff *skb,
|
|
|
+static int tipc_nl_compat_net_set(struct tipc_nl_compat_cmd_doit *cmd,
|
|
|
+ struct sk_buff *skb,
|
|
|
struct tipc_nl_compat_msg *msg)
|
|
|
{
|
|
|
u32 val;
|
|
@@ -1007,7 +1098,6 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
|
|
|
struct nlmsghdr *req_nlh;
|
|
|
struct nlmsghdr *rep_nlh;
|
|
|
struct tipc_genlmsghdr *req_userhdr = info->userhdr;
|
|
|
- struct net *net = genl_info_net(info);
|
|
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
|
|
@@ -1015,6 +1105,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
|
|
|
msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN;
|
|
|
msg.cmd = req_userhdr->cmd;
|
|
|
msg.dst_sk = info->dst_sk;
|
|
|
+ msg.net = genl_info_net(info);
|
|
|
|
|
|
if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) {
|
|
|
msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN);
|
|
@@ -1043,7 +1134,7 @@ send:
|
|
|
rep_nlh = nlmsg_hdr(msg.rep);
|
|
|
memcpy(rep_nlh, info->nlhdr, len);
|
|
|
rep_nlh->nlmsg_len = msg.rep->len;
|
|
|
- genlmsg_unicast(net, msg.rep, NETLINK_CB(skb).portid);
|
|
|
+ genlmsg_unicast(msg.net, msg.rep, NETLINK_CB(skb).portid);
|
|
|
|
|
|
return err;
|
|
|
}
|