aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/net.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/net.c')
-rw-r--r--net/tipc/net.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 93b9944a6a8b..cf13df3cde8f 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -42,6 +42,11 @@
42#include "node.h" 42#include "node.h"
43#include "config.h" 43#include "config.h"
44 44
45static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = {
46 [TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC },
47 [TIPC_NLA_NET_ID] = { .type = NLA_U32 }
48};
49
45/* 50/*
46 * The TIPC locking policy is designed to ensure a very fine locking 51 * The TIPC locking policy is designed to ensure a very fine locking
47 * granularity, permitting complete parallel access to individual 52 * granularity, permitting complete parallel access to individual
@@ -138,3 +143,104 @@ void tipc_net_stop(void)
138 143
139 pr_info("Left network mode\n"); 144 pr_info("Left network mode\n");
140} 145}
146
147static int __tipc_nl_add_net(struct tipc_nl_msg *msg)
148{
149 void *hdr;
150 struct nlattr *attrs;
151
152 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_v2_family,
153 NLM_F_MULTI, TIPC_NL_NET_GET);
154 if (!hdr)
155 return -EMSGSIZE;
156
157 attrs = nla_nest_start(msg->skb, TIPC_NLA_NET);
158 if (!attrs)
159 goto msg_full;
160
161 if (nla_put_u32(msg->skb, TIPC_NLA_NET_ID, tipc_net_id))
162 goto attr_msg_full;
163
164 nla_nest_end(msg->skb, attrs);
165 genlmsg_end(msg->skb, hdr);
166
167 return 0;
168
169attr_msg_full:
170 nla_nest_cancel(msg->skb, attrs);
171msg_full:
172 genlmsg_cancel(msg->skb, hdr);
173
174 return -EMSGSIZE;
175}
176
177int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb)
178{
179 int err;
180 int done = cb->args[0];
181 struct tipc_nl_msg msg;
182
183 if (done)
184 return 0;
185
186 msg.skb = skb;
187 msg.portid = NETLINK_CB(cb->skb).portid;
188 msg.seq = cb->nlh->nlmsg_seq;
189
190 err = __tipc_nl_add_net(&msg);
191 if (err)
192 goto out;
193
194 done = 1;
195out:
196 cb->args[0] = done;
197
198 return skb->len;
199}
200
201int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)
202{
203 int err;
204 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1];
205
206 if (!info->attrs[TIPC_NLA_NET])
207 return -EINVAL;
208
209 err = nla_parse_nested(attrs, TIPC_NLA_NET_MAX,
210 info->attrs[TIPC_NLA_NET],
211 tipc_nl_net_policy);
212 if (err)
213 return err;
214
215 if (attrs[TIPC_NLA_NET_ID]) {
216 u32 val;
217
218 /* Can't change net id once TIPC has joined a network */
219 if (tipc_own_addr)
220 return -EPERM;
221
222 val = nla_get_u32(attrs[TIPC_NLA_NET_ID]);
223 if (val < 1 || val > 9999)
224 return -EINVAL;
225
226 tipc_net_id = val;
227 }
228
229 if (attrs[TIPC_NLA_NET_ADDR]) {
230 u32 addr;
231
232 /* Can't change net addr once TIPC has joined a network */
233 if (tipc_own_addr)
234 return -EPERM;
235
236 addr = nla_get_u32(attrs[TIPC_NLA_NET_ADDR]);
237 if (!tipc_addr_node_valid(addr))
238 return -EINVAL;
239
240 rtnl_lock();
241 tipc_net_start(addr);
242 rtnl_unlock();
243 }
244
245 return 0;
246}