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