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.c144
1 files changed, 129 insertions, 15 deletions
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 93b9944a6a8b..a54f3cbe2246 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -40,7 +40,11 @@
40#include "subscr.h" 40#include "subscr.h"
41#include "socket.h" 41#include "socket.h"
42#include "node.h" 42#include "node.h"
43#include "config.h" 43
44static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = {
45 [TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC },
46 [TIPC_NLA_NET_ID] = { .type = NLA_U32 }
47};
44 48
45/* 49/*
46 * The TIPC locking policy is designed to ensure a very fine locking 50 * The TIPC locking policy is designed to ensure a very fine locking
@@ -103,38 +107,148 @@
103 * - A local spin_lock protecting the queue of subscriber events. 107 * - A local spin_lock protecting the queue of subscriber events.
104*/ 108*/
105 109
106int tipc_net_start(u32 addr) 110int tipc_net_start(struct net *net, u32 addr)
107{ 111{
112 struct tipc_net *tn = net_generic(net, tipc_net_id);
108 char addr_string[16]; 113 char addr_string[16];
109 int res; 114 int res;
110 115
111 tipc_own_addr = addr; 116 tn->own_addr = addr;
112 tipc_named_reinit(); 117 tipc_named_reinit(net);
113 tipc_sk_reinit(); 118 tipc_sk_reinit(net);
114 res = tipc_bclink_init(); 119 res = tipc_bclink_init(net);
115 if (res) 120 if (res)
116 return res; 121 return res;
117 122
118 tipc_nametbl_publish(TIPC_CFG_SRV, tipc_own_addr, tipc_own_addr, 123 tipc_nametbl_publish(net, TIPC_CFG_SRV, tn->own_addr, tn->own_addr,
119 TIPC_ZONE_SCOPE, 0, tipc_own_addr); 124 TIPC_ZONE_SCOPE, 0, tn->own_addr);
120 125
121 pr_info("Started in network mode\n"); 126 pr_info("Started in network mode\n");
122 pr_info("Own node address %s, network identity %u\n", 127 pr_info("Own node address %s, network identity %u\n",
123 tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); 128 tipc_addr_string_fill(addr_string, tn->own_addr),
129 tn->net_id);
124 return 0; 130 return 0;
125} 131}
126 132
127void tipc_net_stop(void) 133void tipc_net_stop(struct net *net)
128{ 134{
129 if (!tipc_own_addr) 135 struct tipc_net *tn = net_generic(net, tipc_net_id);
136
137 if (!tn->own_addr)
130 return; 138 return;
131 139
132 tipc_nametbl_withdraw(TIPC_CFG_SRV, tipc_own_addr, 0, tipc_own_addr); 140 tipc_nametbl_withdraw(net, TIPC_CFG_SRV, tn->own_addr, 0,
141 tn->own_addr);
133 rtnl_lock(); 142 rtnl_lock();
134 tipc_bearer_stop(); 143 tipc_bearer_stop(net);
135 tipc_bclink_stop(); 144 tipc_bclink_stop(net);
136 tipc_node_stop(); 145 tipc_node_stop(net);
137 rtnl_unlock(); 146 rtnl_unlock();
138 147
139 pr_info("Left network mode\n"); 148 pr_info("Left network mode\n");
140} 149}
150
151static int __tipc_nl_add_net(struct net *net, struct tipc_nl_msg *msg)
152{
153 struct tipc_net *tn = net_generic(net, tipc_net_id);
154 void *hdr;
155 struct nlattr *attrs;
156
157 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
158 NLM_F_MULTI, TIPC_NL_NET_GET);
159 if (!hdr)
160 return -EMSGSIZE;
161
162 attrs = nla_nest_start(msg->skb, TIPC_NLA_NET);
163 if (!attrs)
164 goto msg_full;
165
166 if (nla_put_u32(msg->skb, TIPC_NLA_NET_ID, tn->net_id))
167 goto attr_msg_full;
168
169 nla_nest_end(msg->skb, attrs);
170 genlmsg_end(msg->skb, hdr);
171
172 return 0;
173
174attr_msg_full:
175 nla_nest_cancel(msg->skb, attrs);
176msg_full:
177 genlmsg_cancel(msg->skb, hdr);
178
179 return -EMSGSIZE;
180}
181
182int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb)
183{
184 struct net *net = sock_net(skb->sk);
185 int err;
186 int done = cb->args[0];
187 struct tipc_nl_msg msg;
188
189 if (done)
190 return 0;
191
192 msg.skb = skb;
193 msg.portid = NETLINK_CB(cb->skb).portid;
194 msg.seq = cb->nlh->nlmsg_seq;
195
196 err = __tipc_nl_add_net(net, &msg);
197 if (err)
198 goto out;
199
200 done = 1;
201out:
202 cb->args[0] = done;
203
204 return skb->len;
205}
206
207int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info)
208{
209 struct net *net = sock_net(skb->sk);
210 struct tipc_net *tn = net_generic(net, tipc_net_id);
211 struct nlattr *attrs[TIPC_NLA_NET_MAX + 1];
212 int err;
213
214 if (!info->attrs[TIPC_NLA_NET])
215 return -EINVAL;
216
217 err = nla_parse_nested(attrs, TIPC_NLA_NET_MAX,
218 info->attrs[TIPC_NLA_NET],
219 tipc_nl_net_policy);
220 if (err)
221 return err;
222
223 if (attrs[TIPC_NLA_NET_ID]) {
224 u32 val;
225
226 /* Can't change net id once TIPC has joined a network */
227 if (tn->own_addr)
228 return -EPERM;
229
230 val = nla_get_u32(attrs[TIPC_NLA_NET_ID]);
231 if (val < 1 || val > 9999)
232 return -EINVAL;
233
234 tn->net_id = val;
235 }
236
237 if (attrs[TIPC_NLA_NET_ADDR]) {
238 u32 addr;
239
240 /* Can't change net addr once TIPC has joined a network */
241 if (tn->own_addr)
242 return -EPERM;
243
244 addr = nla_get_u32(attrs[TIPC_NLA_NET_ADDR]);
245 if (!tipc_addr_node_valid(addr))
246 return -EINVAL;
247
248 rtnl_lock();
249 tipc_net_start(net, addr);
250 rtnl_unlock();
251 }
252
253 return 0;
254}