1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#include "core.h"
38#include "net.h"
39#include "name_distr.h"
40#include "subscr.h"
41#include "socket.h"
42#include "node.h"
43#include "bcast.h"
44#include "netlink.h"
45#include "monitor.h"
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108struct tipc_net_work {
109 struct work_struct work;
110 struct net *net;
111 u32 addr;
112};
113
114static void tipc_net_finalize(struct net *net, u32 addr);
115
116int tipc_net_init(struct net *net, u8 *node_id, u32 addr)
117{
118 if (tipc_own_id(net)) {
119 pr_info("Cannot configure node identity twice\n");
120 return -1;
121 }
122 pr_info("Started in network mode\n");
123
124 if (node_id)
125 tipc_set_node_id(net, node_id);
126 if (addr)
127 tipc_net_finalize(net, addr);
128 return 0;
129}
130
131static void tipc_net_finalize(struct net *net, u32 addr)
132{
133 struct tipc_net *tn = tipc_net(net);
134
135 if (cmpxchg(&tn->node_addr, 0, addr))
136 return;
137 tipc_set_node_addr(net, addr);
138 tipc_named_reinit(net);
139 tipc_sk_reinit(net);
140 tipc_mon_reinit_self(net);
141 tipc_nametbl_publish(net, TIPC_CFG_SRV, addr, addr,
142 TIPC_CLUSTER_SCOPE, 0, addr);
143}
144
145static void tipc_net_finalize_work(struct work_struct *work)
146{
147 struct tipc_net_work *fwork;
148
149 fwork = container_of(work, struct tipc_net_work, work);
150 tipc_net_finalize(fwork->net, fwork->addr);
151 kfree(fwork);
152}
153
154void tipc_sched_net_finalize(struct net *net, u32 addr)
155{
156 struct tipc_net_work *fwork = kzalloc(sizeof(*fwork), GFP_ATOMIC);
157
158 if (!fwork)
159 return;
160 INIT_WORK(&fwork->work, tipc_net_finalize_work);
161 fwork->net = net;
162 fwork->addr = addr;
163 schedule_work(&fwork->work);
164}
165
166void tipc_net_stop(struct net *net)
167{
168 if (!tipc_own_id(net))
169 return;
170
171 rtnl_lock();
172 tipc_bearer_stop(net);
173 tipc_node_stop(net);
174 rtnl_unlock();
175
176 pr_info("Left network mode\n");
177}
178
179static int __tipc_nl_add_net(struct net *net, struct tipc_nl_msg *msg)
180{
181 struct tipc_net *tn = net_generic(net, tipc_net_id);
182 u64 *w0 = (u64 *)&tn->node_id[0];
183 u64 *w1 = (u64 *)&tn->node_id[8];
184 struct nlattr *attrs;
185 void *hdr;
186
187 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
188 NLM_F_MULTI, TIPC_NL_NET_GET);
189 if (!hdr)
190 return -EMSGSIZE;
191
192 attrs = nla_nest_start_noflag(msg->skb, TIPC_NLA_NET);
193 if (!attrs)
194 goto msg_full;
195
196 if (nla_put_u32(msg->skb, TIPC_NLA_NET_ID, tn->net_id))
197 goto attr_msg_full;
198 if (nla_put_u64_64bit(msg->skb, TIPC_NLA_NET_NODEID, *w0, 0))
199 goto attr_msg_full;
200 if (nla_put_u64_64bit(msg->skb, TIPC_NLA_NET_NODEID_W1, *w1, 0))
201 goto attr_msg_full;
202 nla_nest_end(msg->skb, attrs);
203 genlmsg_end(msg->skb, hdr);
204
205 return 0;
206
207attr_msg_full:
208 nla_nest_cancel(msg->skb, attrs);
209msg_full:
210 genlmsg_cancel(msg->skb, hdr);
211
212 return -EMSGSIZE;
213}
214
215int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb)
216{
217 struct net *net = sock_net(skb->sk);
218 int err;
219 int done = cb->args[0];
220 struct tipc_nl_msg msg;
221
222 if (done)
223 return 0;
224
225 msg.skb = skb;
226 msg.portid = NETLINK_CB(cb->skb).portid;
227 msg.seq = cb->nlh->nlmsg_seq;
228
229 err = __tipc_nl_add_net(net, &msg);
230 if (err)
231 goto out;
232
233 done = 1;
234out:
235 cb->args[0] = done;
236
237 return skb->len;
238}
239
240int __tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)
241{
242 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1];
243 struct net *net = sock_net(skb->sk);
244 struct tipc_net *tn = tipc_net(net);
245 int err;
246
247 if (!info->attrs[TIPC_NLA_NET])
248 return -EINVAL;
249
250 err = nla_parse_nested_deprecated(attrs, TIPC_NLA_NET_MAX,
251 info->attrs[TIPC_NLA_NET],
252 tipc_nl_net_policy, info->extack);
253
254 if (err)
255 return err;
256
257
258 if (tipc_own_addr(net))
259 return -EPERM;
260
261 if (attrs[TIPC_NLA_NET_ID]) {
262 u32 val;
263
264 val = nla_get_u32(attrs[TIPC_NLA_NET_ID]);
265 if (val < 1 || val > 9999)
266 return -EINVAL;
267
268 tn->net_id = val;
269 }
270
271 if (attrs[TIPC_NLA_NET_ADDR]) {
272 u32 addr;
273
274 addr = nla_get_u32(attrs[TIPC_NLA_NET_ADDR]);
275 if (!addr)
276 return -EINVAL;
277 tn->legacy_addr_format = true;
278 tipc_net_init(net, NULL, addr);
279 }
280
281 if (attrs[TIPC_NLA_NET_NODEID]) {
282 u8 node_id[NODE_ID_LEN];
283 u64 *w0 = (u64 *)&node_id[0];
284 u64 *w1 = (u64 *)&node_id[8];
285
286 if (!attrs[TIPC_NLA_NET_NODEID_W1])
287 return -EINVAL;
288 *w0 = nla_get_u64(attrs[TIPC_NLA_NET_NODEID]);
289 *w1 = nla_get_u64(attrs[TIPC_NLA_NET_NODEID_W1]);
290 tipc_net_init(net, node_id, 0);
291 }
292 return 0;
293}
294
295int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)
296{
297 int err;
298
299 rtnl_lock();
300 err = __tipc_nl_net_set(skb, info);
301 rtnl_unlock();
302
303 return err;
304}
305
306static int __tipc_nl_addr_legacy_get(struct net *net, struct tipc_nl_msg *msg)
307{
308 struct tipc_net *tn = tipc_net(net);
309 struct nlattr *attrs;
310 void *hdr;
311
312 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
313 0, TIPC_NL_ADDR_LEGACY_GET);
314 if (!hdr)
315 return -EMSGSIZE;
316
317 attrs = nla_nest_start(msg->skb, TIPC_NLA_NET);
318 if (!attrs)
319 goto msg_full;
320
321 if (tn->legacy_addr_format)
322 if (nla_put_flag(msg->skb, TIPC_NLA_NET_ADDR_LEGACY))
323 goto attr_msg_full;
324
325 nla_nest_end(msg->skb, attrs);
326 genlmsg_end(msg->skb, hdr);
327
328 return 0;
329
330attr_msg_full:
331 nla_nest_cancel(msg->skb, attrs);
332msg_full:
333 genlmsg_cancel(msg->skb, hdr);
334
335 return -EMSGSIZE;
336}
337
338int tipc_nl_net_addr_legacy_get(struct sk_buff *skb, struct genl_info *info)
339{
340 struct net *net = sock_net(skb->sk);
341 struct tipc_nl_msg msg;
342 struct sk_buff *rep;
343 int err;
344
345 rep = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
346 if (!rep)
347 return -ENOMEM;
348
349 msg.skb = rep;
350 msg.portid = info->snd_portid;
351 msg.seq = info->snd_seq;
352
353 err = __tipc_nl_addr_legacy_get(net, &msg);
354 if (err) {
355 nlmsg_free(msg.skb);
356 return err;
357 }
358
359 return genlmsg_reply(msg.skb, info);
360}
361