Root/
1 | /* |
2 | * net/tipc/config.c: TIPC configuration management code |
3 | * |
4 | * Copyright (c) 2002-2006, Ericsson AB |
5 | * Copyright (c) 2004-2007, 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 "port.h" |
39 | #include "name_table.h" |
40 | #include "config.h" |
41 | |
42 | static u32 config_port_ref; |
43 | |
44 | static DEFINE_SPINLOCK(config_lock); |
45 | |
46 | static const void *req_tlv_area; /* request message TLV area */ |
47 | static int req_tlv_space; /* request message TLV area size */ |
48 | static int rep_headroom; /* reply message headroom to use */ |
49 | |
50 | |
51 | struct sk_buff *tipc_cfg_reply_alloc(int payload_size) |
52 | { |
53 | struct sk_buff *buf; |
54 | |
55 | buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC); |
56 | if (buf) |
57 | skb_reserve(buf, rep_headroom); |
58 | return buf; |
59 | } |
60 | |
61 | int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, |
62 | void *tlv_data, int tlv_data_size) |
63 | { |
64 | struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf); |
65 | int new_tlv_space = TLV_SPACE(tlv_data_size); |
66 | |
67 | if (skb_tailroom(buf) < new_tlv_space) |
68 | return 0; |
69 | skb_put(buf, new_tlv_space); |
70 | tlv->tlv_type = htons(tlv_type); |
71 | tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); |
72 | if (tlv_data_size && tlv_data) |
73 | memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size); |
74 | return 1; |
75 | } |
76 | |
77 | static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value) |
78 | { |
79 | struct sk_buff *buf; |
80 | __be32 value_net; |
81 | |
82 | buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value))); |
83 | if (buf) { |
84 | value_net = htonl(value); |
85 | tipc_cfg_append_tlv(buf, tlv_type, &value_net, |
86 | sizeof(value_net)); |
87 | } |
88 | return buf; |
89 | } |
90 | |
91 | static struct sk_buff *tipc_cfg_reply_unsigned(u32 value) |
92 | { |
93 | return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); |
94 | } |
95 | |
96 | struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) |
97 | { |
98 | struct sk_buff *buf; |
99 | int string_len = strlen(string) + 1; |
100 | |
101 | buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len)); |
102 | if (buf) |
103 | tipc_cfg_append_tlv(buf, tlv_type, string, string_len); |
104 | return buf; |
105 | } |
106 | |
107 | #define MAX_STATS_INFO 2000 |
108 | |
109 | static struct sk_buff *tipc_show_stats(void) |
110 | { |
111 | struct sk_buff *buf; |
112 | struct tlv_desc *rep_tlv; |
113 | struct print_buf pb; |
114 | int str_len; |
115 | u32 value; |
116 | |
117 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
118 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
119 | |
120 | value = ntohl(*(u32 *)TLV_DATA(req_tlv_area)); |
121 | if (value != 0) |
122 | return tipc_cfg_reply_error_string("unsupported argument"); |
123 | |
124 | buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO)); |
125 | if (buf == NULL) |
126 | return NULL; |
127 | |
128 | rep_tlv = (struct tlv_desc *)buf->data; |
129 | tipc_printbuf_init(&pb, (char *)TLV_DATA(rep_tlv), MAX_STATS_INFO); |
130 | |
131 | tipc_printf(&pb, "TIPC version " TIPC_MOD_VER "\n"); |
132 | |
133 | /* Use additional tipc_printf()'s to return more info ... */ |
134 | |
135 | str_len = tipc_printbuf_validate(&pb); |
136 | skb_put(buf, TLV_SPACE(str_len)); |
137 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); |
138 | |
139 | return buf; |
140 | } |
141 | |
142 | static struct sk_buff *cfg_enable_bearer(void) |
143 | { |
144 | struct tipc_bearer_config *args; |
145 | |
146 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) |
147 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
148 | |
149 | args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); |
150 | if (tipc_enable_bearer(args->name, |
151 | ntohl(args->detect_scope), |
152 | ntohl(args->priority))) |
153 | return tipc_cfg_reply_error_string("unable to enable bearer"); |
154 | |
155 | return tipc_cfg_reply_none(); |
156 | } |
157 | |
158 | static struct sk_buff *cfg_disable_bearer(void) |
159 | { |
160 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) |
161 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
162 | |
163 | if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) |
164 | return tipc_cfg_reply_error_string("unable to disable bearer"); |
165 | |
166 | return tipc_cfg_reply_none(); |
167 | } |
168 | |
169 | static struct sk_buff *cfg_set_own_addr(void) |
170 | { |
171 | u32 addr; |
172 | |
173 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) |
174 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
175 | |
176 | addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
177 | if (addr == tipc_own_addr) |
178 | return tipc_cfg_reply_none(); |
179 | if (!tipc_addr_node_valid(addr)) |
180 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
181 | " (node address)"); |
182 | if (tipc_mode == TIPC_NET_MODE) |
183 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
184 | " (cannot change node address once assigned)"); |
185 | |
186 | /* |
187 | * Must release all spinlocks before calling start_net() because |
188 | * Linux version of TIPC calls eth_media_start() which calls |
189 | * register_netdevice_notifier() which may block! |
190 | * |
191 | * Temporarily releasing the lock should be harmless for non-Linux TIPC, |
192 | * but Linux version of eth_media_start() should really be reworked |
193 | * so that it can be called with spinlocks held. |
194 | */ |
195 | |
196 | spin_unlock_bh(&config_lock); |
197 | tipc_core_start_net(addr); |
198 | spin_lock_bh(&config_lock); |
199 | return tipc_cfg_reply_none(); |
200 | } |
201 | |
202 | static struct sk_buff *cfg_set_remote_mng(void) |
203 | { |
204 | u32 value; |
205 | |
206 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
207 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
208 | |
209 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
210 | tipc_remote_management = (value != 0); |
211 | return tipc_cfg_reply_none(); |
212 | } |
213 | |
214 | static struct sk_buff *cfg_set_max_publications(void) |
215 | { |
216 | u32 value; |
217 | |
218 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
219 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
220 | |
221 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
222 | if (value != delimit(value, 1, 65535)) |
223 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
224 | " (max publications must be 1-65535)"); |
225 | tipc_max_publications = value; |
226 | return tipc_cfg_reply_none(); |
227 | } |
228 | |
229 | static struct sk_buff *cfg_set_max_subscriptions(void) |
230 | { |
231 | u32 value; |
232 | |
233 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
234 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
235 | |
236 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
237 | if (value != delimit(value, 1, 65535)) |
238 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
239 | " (max subscriptions must be 1-65535"); |
240 | tipc_max_subscriptions = value; |
241 | return tipc_cfg_reply_none(); |
242 | } |
243 | |
244 | static struct sk_buff *cfg_set_max_ports(void) |
245 | { |
246 | u32 value; |
247 | |
248 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
249 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
250 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
251 | if (value == tipc_max_ports) |
252 | return tipc_cfg_reply_none(); |
253 | if (value != delimit(value, 127, 65535)) |
254 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
255 | " (max ports must be 127-65535)"); |
256 | if (tipc_mode != TIPC_NOT_RUNNING) |
257 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
258 | " (cannot change max ports while TIPC is active)"); |
259 | tipc_max_ports = value; |
260 | return tipc_cfg_reply_none(); |
261 | } |
262 | |
263 | static struct sk_buff *cfg_set_max_nodes(void) |
264 | { |
265 | u32 value; |
266 | |
267 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
268 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
269 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
270 | if (value == tipc_max_nodes) |
271 | return tipc_cfg_reply_none(); |
272 | if (value != delimit(value, 8, 2047)) |
273 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
274 | " (max nodes must be 8-2047)"); |
275 | if (tipc_mode == TIPC_NET_MODE) |
276 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
277 | " (cannot change max nodes once TIPC has joined a network)"); |
278 | tipc_max_nodes = value; |
279 | return tipc_cfg_reply_none(); |
280 | } |
281 | |
282 | static struct sk_buff *cfg_set_netid(void) |
283 | { |
284 | u32 value; |
285 | |
286 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
287 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
288 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
289 | if (value == tipc_net_id) |
290 | return tipc_cfg_reply_none(); |
291 | if (value != delimit(value, 1, 9999)) |
292 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
293 | " (network id must be 1-9999)"); |
294 | if (tipc_mode == TIPC_NET_MODE) |
295 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
296 | " (cannot change network id once TIPC has joined a network)"); |
297 | tipc_net_id = value; |
298 | return tipc_cfg_reply_none(); |
299 | } |
300 | |
301 | struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, |
302 | int request_space, int reply_headroom) |
303 | { |
304 | struct sk_buff *rep_tlv_buf; |
305 | |
306 | spin_lock_bh(&config_lock); |
307 | |
308 | /* Save request and reply details in a well-known location */ |
309 | |
310 | req_tlv_area = request_area; |
311 | req_tlv_space = request_space; |
312 | rep_headroom = reply_headroom; |
313 | |
314 | /* Check command authorization */ |
315 | |
316 | if (likely(orig_node == tipc_own_addr)) { |
317 | /* command is permitted */ |
318 | } else if (cmd >= 0x8000) { |
319 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
320 | " (cannot be done remotely)"); |
321 | goto exit; |
322 | } else if (!tipc_remote_management) { |
323 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE); |
324 | goto exit; |
325 | } else if (cmd >= 0x4000) { |
326 | u32 domain = 0; |
327 | |
328 | if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || |
329 | (domain != orig_node)) { |
330 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); |
331 | goto exit; |
332 | } |
333 | } |
334 | |
335 | /* Call appropriate processing routine */ |
336 | |
337 | switch (cmd) { |
338 | case TIPC_CMD_NOOP: |
339 | rep_tlv_buf = tipc_cfg_reply_none(); |
340 | break; |
341 | case TIPC_CMD_GET_NODES: |
342 | rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space); |
343 | break; |
344 | case TIPC_CMD_GET_LINKS: |
345 | rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space); |
346 | break; |
347 | case TIPC_CMD_SHOW_LINK_STATS: |
348 | rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space); |
349 | break; |
350 | case TIPC_CMD_RESET_LINK_STATS: |
351 | rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space); |
352 | break; |
353 | case TIPC_CMD_SHOW_NAME_TABLE: |
354 | rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space); |
355 | break; |
356 | case TIPC_CMD_GET_BEARER_NAMES: |
357 | rep_tlv_buf = tipc_bearer_get_names(); |
358 | break; |
359 | case TIPC_CMD_GET_MEDIA_NAMES: |
360 | rep_tlv_buf = tipc_media_get_names(); |
361 | break; |
362 | case TIPC_CMD_SHOW_PORTS: |
363 | rep_tlv_buf = tipc_port_get_ports(); |
364 | break; |
365 | case TIPC_CMD_SET_LOG_SIZE: |
366 | rep_tlv_buf = tipc_log_resize_cmd(req_tlv_area, req_tlv_space); |
367 | break; |
368 | case TIPC_CMD_DUMP_LOG: |
369 | rep_tlv_buf = tipc_log_dump(); |
370 | break; |
371 | case TIPC_CMD_SHOW_STATS: |
372 | rep_tlv_buf = tipc_show_stats(); |
373 | break; |
374 | case TIPC_CMD_SET_LINK_TOL: |
375 | case TIPC_CMD_SET_LINK_PRI: |
376 | case TIPC_CMD_SET_LINK_WINDOW: |
377 | rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd); |
378 | break; |
379 | case TIPC_CMD_ENABLE_BEARER: |
380 | rep_tlv_buf = cfg_enable_bearer(); |
381 | break; |
382 | case TIPC_CMD_DISABLE_BEARER: |
383 | rep_tlv_buf = cfg_disable_bearer(); |
384 | break; |
385 | case TIPC_CMD_SET_NODE_ADDR: |
386 | rep_tlv_buf = cfg_set_own_addr(); |
387 | break; |
388 | case TIPC_CMD_SET_REMOTE_MNG: |
389 | rep_tlv_buf = cfg_set_remote_mng(); |
390 | break; |
391 | case TIPC_CMD_SET_MAX_PORTS: |
392 | rep_tlv_buf = cfg_set_max_ports(); |
393 | break; |
394 | case TIPC_CMD_SET_MAX_PUBL: |
395 | rep_tlv_buf = cfg_set_max_publications(); |
396 | break; |
397 | case TIPC_CMD_SET_MAX_SUBSCR: |
398 | rep_tlv_buf = cfg_set_max_subscriptions(); |
399 | break; |
400 | case TIPC_CMD_SET_MAX_NODES: |
401 | rep_tlv_buf = cfg_set_max_nodes(); |
402 | break; |
403 | case TIPC_CMD_SET_NETID: |
404 | rep_tlv_buf = cfg_set_netid(); |
405 | break; |
406 | case TIPC_CMD_GET_REMOTE_MNG: |
407 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management); |
408 | break; |
409 | case TIPC_CMD_GET_MAX_PORTS: |
410 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports); |
411 | break; |
412 | case TIPC_CMD_GET_MAX_PUBL: |
413 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_publications); |
414 | break; |
415 | case TIPC_CMD_GET_MAX_SUBSCR: |
416 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions); |
417 | break; |
418 | case TIPC_CMD_GET_MAX_NODES: |
419 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes); |
420 | break; |
421 | case TIPC_CMD_GET_NETID: |
422 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); |
423 | break; |
424 | case TIPC_CMD_NOT_NET_ADMIN: |
425 | rep_tlv_buf = |
426 | tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); |
427 | break; |
428 | case TIPC_CMD_SET_MAX_ZONES: |
429 | case TIPC_CMD_GET_MAX_ZONES: |
430 | case TIPC_CMD_SET_MAX_SLAVES: |
431 | case TIPC_CMD_GET_MAX_SLAVES: |
432 | case TIPC_CMD_SET_MAX_CLUSTERS: |
433 | case TIPC_CMD_GET_MAX_CLUSTERS: |
434 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
435 | " (obsolete command)"); |
436 | break; |
437 | default: |
438 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
439 | " (unknown command)"); |
440 | break; |
441 | } |
442 | |
443 | /* Return reply buffer */ |
444 | exit: |
445 | spin_unlock_bh(&config_lock); |
446 | return rep_tlv_buf; |
447 | } |
448 | |
449 | static void cfg_named_msg_event(void *userdata, |
450 | u32 port_ref, |
451 | struct sk_buff **buf, |
452 | const unchar *msg, |
453 | u32 size, |
454 | u32 importance, |
455 | struct tipc_portid const *orig, |
456 | struct tipc_name_seq const *dest) |
457 | { |
458 | struct tipc_cfg_msg_hdr *req_hdr; |
459 | struct tipc_cfg_msg_hdr *rep_hdr; |
460 | struct sk_buff *rep_buf; |
461 | |
462 | /* Validate configuration message header (ignore invalid message) */ |
463 | |
464 | req_hdr = (struct tipc_cfg_msg_hdr *)msg; |
465 | if ((size < sizeof(*req_hdr)) || |
466 | (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || |
467 | (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { |
468 | warn("Invalid configuration message discarded\n"); |
469 | return; |
470 | } |
471 | |
472 | /* Generate reply for request (if can't, return request) */ |
473 | |
474 | rep_buf = tipc_cfg_do_cmd(orig->node, |
475 | ntohs(req_hdr->tcm_type), |
476 | msg + sizeof(*req_hdr), |
477 | size - sizeof(*req_hdr), |
478 | BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); |
479 | if (rep_buf) { |
480 | skb_push(rep_buf, sizeof(*rep_hdr)); |
481 | rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data; |
482 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); |
483 | rep_hdr->tcm_len = htonl(rep_buf->len); |
484 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); |
485 | } else { |
486 | rep_buf = *buf; |
487 | *buf = NULL; |
488 | } |
489 | |
490 | /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */ |
491 | tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); |
492 | } |
493 | |
494 | int tipc_cfg_init(void) |
495 | { |
496 | struct tipc_name_seq seq; |
497 | int res; |
498 | |
499 | res = tipc_createport(NULL, TIPC_CRITICAL_IMPORTANCE, |
500 | NULL, NULL, NULL, |
501 | NULL, cfg_named_msg_event, NULL, |
502 | NULL, &config_port_ref); |
503 | if (res) |
504 | goto failed; |
505 | |
506 | seq.type = TIPC_CFG_SRV; |
507 | seq.lower = seq.upper = tipc_own_addr; |
508 | res = tipc_nametbl_publish_rsv(config_port_ref, TIPC_ZONE_SCOPE, &seq); |
509 | if (res) |
510 | goto failed; |
511 | |
512 | return 0; |
513 | |
514 | failed: |
515 | err("Unable to create configuration service\n"); |
516 | return res; |
517 | } |
518 | |
519 | void tipc_cfg_stop(void) |
520 | { |
521 | if (config_port_ref) { |
522 | tipc_deleteport(config_port_ref); |
523 | config_port_ref = 0; |
524 | } |
525 | } |
526 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9