aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/config.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-02-09 16:20:53 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-09 16:20:53 -0500
commit9dce285b70c157754d753203112cfef22770b1f9 (patch)
tree4859799a8311ecd637e2a582600af1057a78e08b /net/tipc/config.c
parentc8ac18f2006b2926ce375c01646b2f487d1c33b2 (diff)
parent941787b82982b3f33ac398c8c00035ddd0f8c514 (diff)
Merge branch 'tipc-next'
Richard Alpe says: ==================== tipc: new compat layer for the legacy NL API This is a compatibility / transcoding layer for the old netlink API. It relies on the new netlink API to collect data or perform actions (dumpit / doit). The main benefit of this compat layer is that it removes a lot of complex code from the tipc core as only the new API needs to be able harness data or perform actions. I.e. the compat layer isn't concerned with locking or how the internal data-structures look. As long as the new API stays relatively intact the compat layer should be fine. The main challenge in this compat layer is the randomness of the legacy API. Some commands send binary data and some send ASCII data, some are very picky in optimizing there buffer sizes and some just don't care. Most legacy commands put there data in a single TLV (data container) but some segment the data into multiple TLV's. This list of randomness goes on and on.. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/config.c')
-rw-r--r--net/tipc/config.c332
1 files changed, 0 insertions, 332 deletions
diff --git a/net/tipc/config.c b/net/tipc/config.c
deleted file mode 100644
index 6873360cda53..000000000000
--- a/net/tipc/config.c
+++ /dev/null
@@ -1,332 +0,0 @@
1/*
2 * net/tipc/config.c: TIPC configuration management code
3 *
4 * Copyright (c) 2002-2006, Ericsson AB
5 * Copyright (c) 2004-2007, 2010-2013, Wind River Systems
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "socket.h"
39#include "name_table.h"
40#include "config.h"
41#include "server.h"
42
43#define REPLY_TRUNCATED "<truncated>\n"
44
45static const void *req_tlv_area; /* request message TLV area */
46static int req_tlv_space; /* request message TLV area size */
47static int rep_headroom; /* reply message headroom to use */
48
49struct sk_buff *tipc_cfg_reply_alloc(int payload_size)
50{
51 struct sk_buff *buf;
52
53 buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC);
54 if (buf)
55 skb_reserve(buf, rep_headroom);
56 return buf;
57}
58
59int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
60 void *tlv_data, int tlv_data_size)
61{
62 struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf);
63 int new_tlv_space = TLV_SPACE(tlv_data_size);
64
65 if (skb_tailroom(buf) < new_tlv_space)
66 return 0;
67 skb_put(buf, new_tlv_space);
68 tlv->tlv_type = htons(tlv_type);
69 tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size));
70 if (tlv_data_size && tlv_data)
71 memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size);
72 return 1;
73}
74
75static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value)
76{
77 struct sk_buff *buf;
78 __be32 value_net;
79
80 buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value)));
81 if (buf) {
82 value_net = htonl(value);
83 tipc_cfg_append_tlv(buf, tlv_type, &value_net,
84 sizeof(value_net));
85 }
86 return buf;
87}
88
89static struct sk_buff *tipc_cfg_reply_unsigned(u32 value)
90{
91 return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
92}
93
94struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)
95{
96 struct sk_buff *buf;
97 int string_len = strlen(string) + 1;
98
99 buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len));
100 if (buf)
101 tipc_cfg_append_tlv(buf, tlv_type, string, string_len);
102 return buf;
103}
104
105static struct sk_buff *tipc_show_stats(void)
106{
107 struct sk_buff *buf;
108 struct tlv_desc *rep_tlv;
109 char *pb;
110 int pb_len;
111 int str_len;
112 u32 value;
113
114 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
115 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
116
117 value = ntohl(*(u32 *)TLV_DATA(req_tlv_area));
118 if (value != 0)
119 return tipc_cfg_reply_error_string("unsupported argument");
120
121 buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
122 if (buf == NULL)
123 return NULL;
124
125 rep_tlv = (struct tlv_desc *)buf->data;
126 pb = TLV_DATA(rep_tlv);
127 pb_len = ULTRA_STRING_MAX_LEN;
128
129 str_len = tipc_snprintf(pb, pb_len, "TIPC version " TIPC_MOD_VER "\n");
130 str_len += 1; /* for "\0" */
131 skb_put(buf, TLV_SPACE(str_len));
132 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
133
134 return buf;
135}
136
137static struct sk_buff *cfg_enable_bearer(struct net *net)
138{
139 struct tipc_bearer_config *args;
140
141 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG))
142 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
143
144 args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);
145 if (tipc_enable_bearer(net, args->name,
146 ntohl(args->disc_domain),
147 ntohl(args->priority)))
148 return tipc_cfg_reply_error_string("unable to enable bearer");
149
150 return tipc_cfg_reply_none();
151}
152
153static struct sk_buff *cfg_disable_bearer(struct net *net)
154{
155 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME))
156 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
157
158 if (tipc_disable_bearer(net, (char *)TLV_DATA(req_tlv_area)))
159 return tipc_cfg_reply_error_string("unable to disable bearer");
160
161 return tipc_cfg_reply_none();
162}
163
164static struct sk_buff *cfg_set_own_addr(struct net *net)
165{
166 struct tipc_net *tn = net_generic(net, tipc_net_id);
167 u32 addr;
168
169 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
170 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
171
172 addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
173 if (addr == tn->own_addr)
174 return tipc_cfg_reply_none();
175 if (!tipc_addr_node_valid(addr))
176 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
177 " (node address)");
178 if (tn->own_addr)
179 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
180 " (cannot change node address once assigned)");
181 if (!tipc_net_start(net, addr))
182 return tipc_cfg_reply_none();
183
184 return tipc_cfg_reply_error_string("cannot change to network mode");
185}
186
187static struct sk_buff *cfg_set_netid(struct net *net)
188{
189 struct tipc_net *tn = net_generic(net, tipc_net_id);
190 u32 value;
191
192 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
193 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
194 value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
195 if (value == tn->net_id)
196 return tipc_cfg_reply_none();
197 if (value < 1 || value > 9999)
198 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
199 " (network id must be 1-9999)");
200 if (tn->own_addr)
201 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
202 " (cannot change network id once TIPC has joined a network)");
203 tn->net_id = value;
204 return tipc_cfg_reply_none();
205}
206
207struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 orig_node, u16 cmd,
208 const void *request_area, int request_space,
209 int reply_headroom)
210{
211 struct sk_buff *rep_tlv_buf;
212 struct tipc_net *tn = net_generic(net, tipc_net_id);
213
214 rtnl_lock();
215
216 /* Save request and reply details in a well-known location */
217 req_tlv_area = request_area;
218 req_tlv_space = request_space;
219 rep_headroom = reply_headroom;
220
221 /* Check command authorization */
222 if (likely(in_own_node(net, orig_node))) {
223 /* command is permitted */
224 } else {
225 rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
226 " (cannot be done remotely)");
227 goto exit;
228 }
229
230 /* Call appropriate processing routine */
231 switch (cmd) {
232 case TIPC_CMD_NOOP:
233 rep_tlv_buf = tipc_cfg_reply_none();
234 break;
235 case TIPC_CMD_GET_NODES:
236 rep_tlv_buf = tipc_node_get_nodes(net, req_tlv_area,
237 req_tlv_space);
238 break;
239 case TIPC_CMD_GET_LINKS:
240 rep_tlv_buf = tipc_node_get_links(net, req_tlv_area,
241 req_tlv_space);
242 break;
243 case TIPC_CMD_SHOW_LINK_STATS:
244 rep_tlv_buf = tipc_link_cmd_show_stats(net, req_tlv_area,
245 req_tlv_space);
246 break;
247 case TIPC_CMD_RESET_LINK_STATS:
248 rep_tlv_buf = tipc_link_cmd_reset_stats(net, req_tlv_area,
249 req_tlv_space);
250 break;
251 case TIPC_CMD_SHOW_NAME_TABLE:
252 rep_tlv_buf = tipc_nametbl_get(net, req_tlv_area,
253 req_tlv_space);
254 break;
255 case TIPC_CMD_GET_BEARER_NAMES:
256 rep_tlv_buf = tipc_bearer_get_names(net);
257 break;
258 case TIPC_CMD_GET_MEDIA_NAMES:
259 rep_tlv_buf = tipc_media_get_names();
260 break;
261 case TIPC_CMD_SHOW_PORTS:
262 rep_tlv_buf = tipc_sk_socks_show(net);
263 break;
264 case TIPC_CMD_SHOW_STATS:
265 rep_tlv_buf = tipc_show_stats();
266 break;
267 case TIPC_CMD_SET_LINK_TOL:
268 case TIPC_CMD_SET_LINK_PRI:
269 case TIPC_CMD_SET_LINK_WINDOW:
270 rep_tlv_buf = tipc_link_cmd_config(net, req_tlv_area,
271 req_tlv_space, cmd);
272 break;
273 case TIPC_CMD_ENABLE_BEARER:
274 rep_tlv_buf = cfg_enable_bearer(net);
275 break;
276 case TIPC_CMD_DISABLE_BEARER:
277 rep_tlv_buf = cfg_disable_bearer(net);
278 break;
279 case TIPC_CMD_SET_NODE_ADDR:
280 rep_tlv_buf = cfg_set_own_addr(net);
281 break;
282 case TIPC_CMD_SET_NETID:
283 rep_tlv_buf = cfg_set_netid(net);
284 break;
285 case TIPC_CMD_GET_NETID:
286 rep_tlv_buf = tipc_cfg_reply_unsigned(tn->net_id);
287 break;
288 case TIPC_CMD_NOT_NET_ADMIN:
289 rep_tlv_buf =
290 tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
291 break;
292 case TIPC_CMD_SET_MAX_ZONES:
293 case TIPC_CMD_GET_MAX_ZONES:
294 case TIPC_CMD_SET_MAX_SLAVES:
295 case TIPC_CMD_GET_MAX_SLAVES:
296 case TIPC_CMD_SET_MAX_CLUSTERS:
297 case TIPC_CMD_GET_MAX_CLUSTERS:
298 case TIPC_CMD_SET_MAX_NODES:
299 case TIPC_CMD_GET_MAX_NODES:
300 case TIPC_CMD_SET_MAX_SUBSCR:
301 case TIPC_CMD_GET_MAX_SUBSCR:
302 case TIPC_CMD_SET_MAX_PUBL:
303 case TIPC_CMD_GET_MAX_PUBL:
304 case TIPC_CMD_SET_LOG_SIZE:
305 case TIPC_CMD_SET_REMOTE_MNG:
306 case TIPC_CMD_GET_REMOTE_MNG:
307 case TIPC_CMD_DUMP_LOG:
308 case TIPC_CMD_SET_MAX_PORTS:
309 case TIPC_CMD_GET_MAX_PORTS:
310 rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
311 " (obsolete command)");
312 break;
313 default:
314 rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
315 " (unknown command)");
316 break;
317 }
318
319 WARN_ON(rep_tlv_buf->len > TLV_SPACE(ULTRA_STRING_MAX_LEN));
320
321 /* Append an error message if we cannot return all requested data */
322 if (rep_tlv_buf->len == TLV_SPACE(ULTRA_STRING_MAX_LEN)) {
323 if (*(rep_tlv_buf->data + ULTRA_STRING_MAX_LEN) != '\0')
324 sprintf(rep_tlv_buf->data + rep_tlv_buf->len -
325 sizeof(REPLY_TRUNCATED) - 1, REPLY_TRUNCATED);
326 }
327
328 /* Return reply buffer */
329exit:
330 rtnl_unlock();
331 return rep_tlv_buf;
332}