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
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
107struct tipc_net_work {
108 struct work_struct work;
109 struct net *net;
110 u32 addr;
111};
112
113static void tipc_net_finalize(struct net *net, u32 addr);
114
115int tipc_net_init(struct net *net, u8 *node_id, u32 addr)
116{
117 if (tipc_own_id(net)) {
118 pr_info("Cannot configure node identity twice\n");
119 return -1;
120 }
121 pr_info("Started in network mode\n");
122
123 if (node_id)
124 tipc_set_node_id(net, node_id);
125 if (addr)
126 tipc_net_finalize(net, addr);
127 return 0;
128}
129
130static void tipc_net_finalize(struct net *net, u32 addr)
131{
132 struct tipc_net *tn = tipc_net(net);
133
134 if (cmpxchg(&tn->node_addr, 0, addr))
135 return;
136 tipc_set_node_addr(net, addr);
137 tipc_named_reinit(net);
138 tipc_sk_reinit(net);
139 tipc_nametbl_publish(net, TIPC_CFG_SRV, addr, addr,
140 TIPC_CLUSTER_SCOPE, 0, addr);
141}
142
143static void tipc_net_finalize_work(struct work_struct *work)
144{
145 struct tipc_net_work *fwork;
146
147 fwork = container_of(work, struct tipc_net_work, work);
148 tipc_net_finalize(fwork->net, fwork->addr);
149 kfree(fwork);
150}
151
152void tipc_sched_net_finalize(struct net *net, u32 addr)
153{
154 struct tipc_net_work *fwork = kzalloc(sizeof(*fwork), GFP_ATOMIC);
155
156 if (!fwork)
157 return;
158 INIT_WORK(&fwork->work, tipc_net_finalize_work);
159 fwork->net = net;
160 fwork->addr = addr;
161 schedule_work(&fwork->work);
162}
163
164void tipc_net_stop(struct net *net)
165{
166 if (!tipc_own_id(net))
167 return;
168
169 rtnl_lock();
170 tipc_bearer_stop(net);
171 tipc_node_stop(net);
172 rtnl_unlock();
173
174 pr_info("Left network mode\n");
175}
176
177static int __tipc_nl_add_net(struct net *net, struct tipc_nl_msg *msg)
178{
179 struct tipc_net *tn = net_generic(net, tipc_net_id);
180 u64 *w0 = (u64 *)&tn->node_id[0];
181 u64 *w1 = (u64 *)&tn->node_id[8];
182 struct nlattr *attrs;
183 void *hdr;
184
185 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
186 NLM_F_MULTI, TIPC_NL_NET_GET);
187 if (!hdr)
188 return -EMSGSIZE;
189
190 attrs = nla_nest_start_noflag(msg->skb, TIPC_NLA_NET);
191 if (!attrs)
192 goto msg_full;
193
194 if (nla_put_u32(msg->skb, TIPC_NLA_NET_ID, tn->net_id))
195 goto attr_msg_full;
196 if (nla_put_u64_64bit(msg->skb, TIPC_NLA_NET_NODEID, *w0, 0))
197 goto attr_msg_full;
198 if (nla_put_u64_64bit(msg->skb, TIPC_NLA_NET_NODEID_W1, *w1, 0))
199 goto attr_msg_full;
200 nla_nest_end(msg->skb, attrs);
201 genlmsg_end(msg->skb, hdr);
202
203 return 0;
204
205attr_msg_full:
206 nla_nest_cancel(msg->skb, attrs);
207msg_full:
208 genlmsg_cancel(msg->skb, hdr);
209
210 return -EMSGSIZE;
211}
212
213int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb)
214{
215 struct net *net = sock_net(skb->sk);
216 int err;
217 int done = cb->args[0];
218 struct tipc_nl_msg msg;
219
220 if (done)
221 return 0;
222
223 msg.skb = skb;
224 msg.portid = NETLINK_CB(cb->skb).portid;
225 msg.seq = cb->nlh->nlmsg_seq;
226
227 err = __tipc_nl_add_net(net, &msg);
228 if (err)
229 goto out;
230
231 done = 1;
232out:
233 cb->args[0] = done;
234
235 return skb->len;
236}
237
238int __tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)
239{
240 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1];
241 struct net *net = sock_net(skb->sk);
242 struct tipc_net *tn = tipc_net(net);
243 int err;
244
245 if (!info->attrs[TIPC_NLA_NET])
246 return -EINVAL;
247
248 err = nla_parse_nested_deprecated(attrs, TIPC_NLA_NET_MAX,
249 info->attrs[TIPC_NLA_NET],
250 tipc_nl_net_policy, info->extack);
251
252 if (err)
253 return err;
254
255
256 if (tipc_own_addr(net))
257 return -EPERM;
258
259 if (attrs[TIPC_NLA_NET_ID]) {
260 u32 val;
261
262 val = nla_get_u32(attrs[TIPC_NLA_NET_ID]);
263 if (val < 1 || val > 9999)
264 return -EINVAL;
265
266 tn->net_id = val;
267 }
268
269 if (attrs[TIPC_NLA_NET_ADDR]) {
270 u32 addr;
271
272 addr = nla_get_u32(attrs[TIPC_NLA_NET_ADDR]);
273 if (!addr)
274 return -EINVAL;
275 tn->legacy_addr_format = true;
276 tipc_net_init(net, NULL, addr);
277 }
278
279 if (attrs[TIPC_NLA_NET_NODEID]) {
280 u8 node_id[NODE_ID_LEN];
281 u64 *w0 = (u64 *)&node_id[0];
282 u64 *w1 = (u64 *)&node_id[8];
283
284 if (!attrs[TIPC_NLA_NET_NODEID_W1])
285 return -EINVAL;
286 *w0 = nla_get_u64(attrs[TIPC_NLA_NET_NODEID]);
287 *w1 = nla_get_u64(attrs[TIPC_NLA_NET_NODEID_W1]);
288 tipc_net_init(net, node_id, 0);
289 }
290 return 0;
291}
292
293int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)
294{
295 int err;
296
297 rtnl_lock();
298 err = __tipc_nl_net_set(skb, info);
299 rtnl_unlock();
300
301 return err;
302}
303