Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17-rc3 718 lines 20 kB view raw
1/* 2 * net/tipc/config.c: TIPC configuration management code 3 * 4 * Copyright (c) 2002-2006, Ericsson AB 5 * Copyright (c) 2004-2005, 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 u32 subscr_ref; 60 u32 link_subscriptions; 61 struct list_head link_subscribers; 62}; 63 64static struct manager mng = { 0}; 65 66static spinlock_t config_lock = SPIN_LOCK_UNLOCKED; 67 68static const void *req_tlv_area; /* request message TLV area */ 69static int req_tlv_space; /* request message TLV area size */ 70static int rep_headroom; /* reply message headroom to use */ 71 72 73void tipc_cfg_link_event(u32 addr, char *name, int up) 74{ 75 /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */ 76} 77 78 79struct sk_buff *tipc_cfg_reply_alloc(int payload_size) 80{ 81 struct sk_buff *buf; 82 83 buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC); 84 if (buf) 85 skb_reserve(buf, rep_headroom); 86 return buf; 87} 88 89int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, 90 void *tlv_data, int tlv_data_size) 91{ 92 struct tlv_desc *tlv = (struct tlv_desc *)buf->tail; 93 int new_tlv_space = TLV_SPACE(tlv_data_size); 94 95 if (skb_tailroom(buf) < new_tlv_space) { 96 dbg("tipc_cfg_append_tlv unable to append TLV\n"); 97 return 0; 98 } 99 skb_put(buf, new_tlv_space); 100 tlv->tlv_type = htons(tlv_type); 101 tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); 102 if (tlv_data_size && tlv_data) 103 memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size); 104 return 1; 105} 106 107struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value) 108{ 109 struct sk_buff *buf; 110 u32 value_net; 111 112 buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value))); 113 if (buf) { 114 value_net = htonl(value); 115 tipc_cfg_append_tlv(buf, tlv_type, &value_net, 116 sizeof(value_net)); 117 } 118 return buf; 119} 120 121struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) 122{ 123 struct sk_buff *buf; 124 int string_len = strlen(string) + 1; 125 126 buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len)); 127 if (buf) 128 tipc_cfg_append_tlv(buf, tlv_type, string, string_len); 129 return buf; 130} 131 132 133 134 135#if 0 136 137/* Now obsolete code for handling commands not yet implemented the new way */ 138 139int tipc_cfg_cmd(const struct tipc_cmd_msg * msg, 140 char *data, 141 u32 sz, 142 u32 *ret_size, 143 struct tipc_portid *orig) 144{ 145 int rv = -EINVAL; 146 u32 cmd = msg->cmd; 147 148 *ret_size = 0; 149 switch (cmd) { 150 case TIPC_REMOVE_LINK: 151 case TIPC_CMD_BLOCK_LINK: 152 case TIPC_CMD_UNBLOCK_LINK: 153 if (!cfg_check_connection(orig)) 154 rv = link_control(msg->argv.link_name, msg->cmd, 0); 155 break; 156 case TIPC_ESTABLISH: 157 { 158 int connected; 159 160 tipc_isconnected(mng.conn_port_ref, &connected); 161 if (connected || !orig) { 162 rv = TIPC_FAILURE; 163 break; 164 } 165 rv = tipc_connect2port(mng.conn_port_ref, orig); 166 if (rv == TIPC_OK) 167 orig = 0; 168 break; 169 } 170 case TIPC_GET_PEER_ADDRESS: 171 *ret_size = link_peer_addr(msg->argv.link_name, data, sz); 172 break; 173 case TIPC_GET_ROUTES: 174 rv = TIPC_OK; 175 break; 176 default: {} 177 } 178 if (*ret_size) 179 rv = TIPC_OK; 180 return rv; 181} 182 183static void cfg_cmd_event(struct tipc_cmd_msg *msg, 184 char *data, 185 u32 sz, 186 struct tipc_portid const *orig) 187{ 188 int rv = -EINVAL; 189 struct tipc_cmd_result_msg rmsg; 190 struct iovec msg_sect[2]; 191 int *arg; 192 193 msg->cmd = ntohl(msg->cmd); 194 195 cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect, 196 data, 0); 197 if (ntohl(msg->magic) != TIPC_MAGIC) 198 goto exit; 199 200 switch (msg->cmd) { 201 case TIPC_CREATE_LINK: 202 if (!cfg_check_connection(orig)) 203 rv = disc_create_link(&msg->argv.create_link); 204 break; 205 case TIPC_LINK_SUBSCRIBE: 206 { 207 struct subscr_data *sub; 208 209 if (mng.link_subscriptions > 64) 210 break; 211 sub = (struct subscr_data *)kmalloc(sizeof(*sub), 212 GFP_ATOMIC); 213 if (sub == NULL) { 214 warn("Memory squeeze; dropped remote link subscription\n"); 215 break; 216 } 217 INIT_LIST_HEAD(&sub->subd_list); 218 tipc_createport(mng.user_ref, 219 (void *)sub, 220 TIPC_HIGH_IMPORTANCE, 221 0, 222 0, 223 (tipc_conn_shutdown_event)cfg_linksubscr_cancel, 224 0, 225 0, 226 (tipc_conn_msg_event)cfg_linksubscr_cancel, 227 0, 228 &sub->port_ref); 229 if (!sub->port_ref) { 230 kfree(sub); 231 break; 232 } 233 memcpy(sub->usr_handle,msg->usr_handle, 234 sizeof(sub->usr_handle)); 235 sub->domain = msg->argv.domain; 236 list_add_tail(&sub->subd_list, &mng.link_subscribers); 237 tipc_connect2port(sub->port_ref, orig); 238 rmsg.retval = TIPC_OK; 239 tipc_send(sub->port_ref, 2u, msg_sect); 240 mng.link_subscriptions++; 241 return; 242 } 243 default: 244 rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig); 245 } 246 exit: 247 rmsg.result_len = htonl(msg_sect[1].iov_len); 248 rmsg.retval = htonl(rv); 249 tipc_cfg_respond(msg_sect, 2u, orig); 250} 251#endif 252 253static struct sk_buff *cfg_enable_bearer(void) 254{ 255 struct tipc_bearer_config *args; 256 257 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) 258 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 259 260 args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); 261 if (tipc_enable_bearer(args->name, 262 ntohl(args->detect_scope), 263 ntohl(args->priority))) 264 return tipc_cfg_reply_error_string("unable to enable bearer"); 265 266 return tipc_cfg_reply_none(); 267} 268 269static struct sk_buff *cfg_disable_bearer(void) 270{ 271 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) 272 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 273 274 if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) 275 return tipc_cfg_reply_error_string("unable to disable bearer"); 276 277 return tipc_cfg_reply_none(); 278} 279 280static struct sk_buff *cfg_set_own_addr(void) 281{ 282 u32 addr; 283 284 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) 285 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 286 287 addr = *(u32 *)TLV_DATA(req_tlv_area); 288 addr = ntohl(addr); 289 if (addr == tipc_own_addr) 290 return tipc_cfg_reply_none(); 291 if (!tipc_addr_node_valid(addr)) 292 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 293 " (node address)"); 294 if (tipc_own_addr) 295 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 296 " (cannot change node address once assigned)"); 297 298 spin_unlock_bh(&config_lock); 299 tipc_core_stop_net(); 300 tipc_own_addr = addr; 301 tipc_core_start_net(); 302 spin_lock_bh(&config_lock); 303 return tipc_cfg_reply_none(); 304} 305 306static struct sk_buff *cfg_set_remote_mng(void) 307{ 308 u32 value; 309 310 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) 311 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 312 313 value = *(u32 *)TLV_DATA(req_tlv_area); 314 value = ntohl(value); 315 tipc_remote_management = (value != 0); 316 return tipc_cfg_reply_none(); 317} 318 319static struct sk_buff *cfg_set_max_publications(void) 320{ 321 u32 value; 322 323 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) 324 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 325 326 value = *(u32 *)TLV_DATA(req_tlv_area); 327 value = ntohl(value); 328 if (value != delimit(value, 1, 65535)) 329 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 330 " (max publications must be 1-65535)"); 331 tipc_max_publications = value; 332 return tipc_cfg_reply_none(); 333} 334 335static struct sk_buff *cfg_set_max_subscriptions(void) 336{ 337 u32 value; 338 339 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) 340 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 341 342 value = *(u32 *)TLV_DATA(req_tlv_area); 343 value = ntohl(value); 344 if (value != delimit(value, 1, 65535)) 345 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 346 " (max subscriptions must be 1-65535"); 347 tipc_max_subscriptions = value; 348 return tipc_cfg_reply_none(); 349} 350 351static struct sk_buff *cfg_set_max_ports(void) 352{ 353 int orig_mode; 354 u32 value; 355 356 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) 357 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 358 value = *(u32 *)TLV_DATA(req_tlv_area); 359 value = ntohl(value); 360 if (value != delimit(value, 127, 65535)) 361 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 362 " (max ports must be 127-65535)"); 363 364 if (value == tipc_max_ports) 365 return tipc_cfg_reply_none(); 366 367 if (atomic_read(&tipc_user_count) > 2) 368 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 369 " (cannot change max ports while TIPC users exist)"); 370 371 spin_unlock_bh(&config_lock); 372 orig_mode = tipc_get_mode(); 373 if (orig_mode == TIPC_NET_MODE) 374 tipc_core_stop_net(); 375 tipc_core_stop(); 376 tipc_max_ports = value; 377 tipc_core_start(); 378 if (orig_mode == TIPC_NET_MODE) 379 tipc_core_start_net(); 380 spin_lock_bh(&config_lock); 381 return tipc_cfg_reply_none(); 382} 383 384static struct sk_buff *set_net_max(int value, int *parameter) 385{ 386 int orig_mode; 387 388 if (value != *parameter) { 389 orig_mode = tipc_get_mode(); 390 if (orig_mode == TIPC_NET_MODE) 391 tipc_core_stop_net(); 392 *parameter = value; 393 if (orig_mode == TIPC_NET_MODE) 394 tipc_core_start_net(); 395 } 396 397 return tipc_cfg_reply_none(); 398} 399 400static struct sk_buff *cfg_set_max_zones(void) 401{ 402 u32 value; 403 404 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) 405 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 406 value = *(u32 *)TLV_DATA(req_tlv_area); 407 value = ntohl(value); 408 if (value != delimit(value, 1, 255)) 409 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 410 " (max zones must be 1-255)"); 411 return set_net_max(value, &tipc_max_zones); 412} 413 414static struct sk_buff *cfg_set_max_clusters(void) 415{ 416 u32 value; 417 418 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) 419 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 420 value = *(u32 *)TLV_DATA(req_tlv_area); 421 value = ntohl(value); 422 if (value != 1) 423 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 424 " (max clusters fixed at 1)"); 425 return tipc_cfg_reply_none(); 426} 427 428static struct sk_buff *cfg_set_max_nodes(void) 429{ 430 u32 value; 431 432 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) 433 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 434 value = *(u32 *)TLV_DATA(req_tlv_area); 435 value = ntohl(value); 436 if (value != delimit(value, 8, 2047)) 437 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 438 " (max nodes must be 8-2047)"); 439 return set_net_max(value, &tipc_max_nodes); 440} 441 442static struct sk_buff *cfg_set_max_slaves(void) 443{ 444 u32 value; 445 446 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) 447 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 448 value = *(u32 *)TLV_DATA(req_tlv_area); 449 value = ntohl(value); 450 if (value != 0) 451 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 452 " (max secondary nodes fixed at 0)"); 453 return tipc_cfg_reply_none(); 454} 455 456static struct sk_buff *cfg_set_netid(void) 457{ 458 u32 value; 459 460 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) 461 return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 462 value = *(u32 *)TLV_DATA(req_tlv_area); 463 value = ntohl(value); 464 if (value != delimit(value, 1, 9999)) 465 return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE 466 " (network id must be 1-9999)"); 467 468 if (tipc_own_addr) 469 return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 470 " (cannot change network id once part of network)"); 471 472 return set_net_max(value, &tipc_net_id); 473} 474 475struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, 476 int request_space, int reply_headroom) 477{ 478 struct sk_buff *rep_tlv_buf; 479 480 spin_lock_bh(&config_lock); 481 482 /* Save request and reply details in a well-known location */ 483 484 req_tlv_area = request_area; 485 req_tlv_space = request_space; 486 rep_headroom = reply_headroom; 487 488 /* Check command authorization */ 489 490 if (likely(orig_node == tipc_own_addr)) { 491 /* command is permitted */ 492 } else if (cmd >= 0x8000) { 493 rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED 494 " (cannot be done remotely)"); 495 goto exit; 496 } else if (!tipc_remote_management) { 497 rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE); 498 goto exit; 499 } 500 else if (cmd >= 0x4000) { 501 u32 domain = 0; 502 503 if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || 504 (domain != orig_node)) { 505 rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); 506 goto exit; 507 } 508 } 509 510 /* Call appropriate processing routine */ 511 512 switch (cmd) { 513 case TIPC_CMD_NOOP: 514 rep_tlv_buf = tipc_cfg_reply_none(); 515 break; 516 case TIPC_CMD_GET_NODES: 517 rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space); 518 break; 519 case TIPC_CMD_GET_LINKS: 520 rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space); 521 break; 522 case TIPC_CMD_SHOW_LINK_STATS: 523 rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space); 524 break; 525 case TIPC_CMD_RESET_LINK_STATS: 526 rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space); 527 break; 528 case TIPC_CMD_SHOW_NAME_TABLE: 529 rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space); 530 break; 531 case TIPC_CMD_GET_BEARER_NAMES: 532 rep_tlv_buf = tipc_bearer_get_names(); 533 break; 534 case TIPC_CMD_GET_MEDIA_NAMES: 535 rep_tlv_buf = tipc_media_get_names(); 536 break; 537 case TIPC_CMD_SHOW_PORTS: 538 rep_tlv_buf = tipc_port_get_ports(); 539 break; 540#if 0 541 case TIPC_CMD_SHOW_PORT_STATS: 542 rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space); 543 break; 544 case TIPC_CMD_RESET_PORT_STATS: 545 rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED); 546 break; 547#endif 548 case TIPC_CMD_SET_LOG_SIZE: 549 rep_tlv_buf = tipc_log_resize(req_tlv_area, req_tlv_space); 550 break; 551 case TIPC_CMD_DUMP_LOG: 552 rep_tlv_buf = tipc_log_dump(); 553 break; 554 case TIPC_CMD_SET_LINK_TOL: 555 case TIPC_CMD_SET_LINK_PRI: 556 case TIPC_CMD_SET_LINK_WINDOW: 557 rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd); 558 break; 559 case TIPC_CMD_ENABLE_BEARER: 560 rep_tlv_buf = cfg_enable_bearer(); 561 break; 562 case TIPC_CMD_DISABLE_BEARER: 563 rep_tlv_buf = cfg_disable_bearer(); 564 break; 565 case TIPC_CMD_SET_NODE_ADDR: 566 rep_tlv_buf = cfg_set_own_addr(); 567 break; 568 case TIPC_CMD_SET_REMOTE_MNG: 569 rep_tlv_buf = cfg_set_remote_mng(); 570 break; 571 case TIPC_CMD_SET_MAX_PORTS: 572 rep_tlv_buf = cfg_set_max_ports(); 573 break; 574 case TIPC_CMD_SET_MAX_PUBL: 575 rep_tlv_buf = cfg_set_max_publications(); 576 break; 577 case TIPC_CMD_SET_MAX_SUBSCR: 578 rep_tlv_buf = cfg_set_max_subscriptions(); 579 break; 580 case TIPC_CMD_SET_MAX_ZONES: 581 rep_tlv_buf = cfg_set_max_zones(); 582 break; 583 case TIPC_CMD_SET_MAX_CLUSTERS: 584 rep_tlv_buf = cfg_set_max_clusters(); 585 break; 586 case TIPC_CMD_SET_MAX_NODES: 587 rep_tlv_buf = cfg_set_max_nodes(); 588 break; 589 case TIPC_CMD_SET_MAX_SLAVES: 590 rep_tlv_buf = cfg_set_max_slaves(); 591 break; 592 case TIPC_CMD_SET_NETID: 593 rep_tlv_buf = cfg_set_netid(); 594 break; 595 case TIPC_CMD_GET_REMOTE_MNG: 596 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management); 597 break; 598 case TIPC_CMD_GET_MAX_PORTS: 599 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports); 600 break; 601 case TIPC_CMD_GET_MAX_PUBL: 602 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_publications); 603 break; 604 case TIPC_CMD_GET_MAX_SUBSCR: 605 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions); 606 break; 607 case TIPC_CMD_GET_MAX_ZONES: 608 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_zones); 609 break; 610 case TIPC_CMD_GET_MAX_CLUSTERS: 611 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_clusters); 612 break; 613 case TIPC_CMD_GET_MAX_NODES: 614 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes); 615 break; 616 case TIPC_CMD_GET_MAX_SLAVES: 617 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_slaves); 618 break; 619 case TIPC_CMD_GET_NETID: 620 rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); 621 break; 622 default: 623 rep_tlv_buf = NULL; 624 break; 625 } 626 627 /* Return reply buffer */ 628exit: 629 spin_unlock_bh(&config_lock); 630 return rep_tlv_buf; 631} 632 633static void cfg_named_msg_event(void *userdata, 634 u32 port_ref, 635 struct sk_buff **buf, 636 const unchar *msg, 637 u32 size, 638 u32 importance, 639 struct tipc_portid const *orig, 640 struct tipc_name_seq const *dest) 641{ 642 struct tipc_cfg_msg_hdr *req_hdr; 643 struct tipc_cfg_msg_hdr *rep_hdr; 644 struct sk_buff *rep_buf; 645 646 /* Validate configuration message header (ignore invalid message) */ 647 648 req_hdr = (struct tipc_cfg_msg_hdr *)msg; 649 if ((size < sizeof(*req_hdr)) || 650 (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || 651 (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { 652 warn("discarded invalid configuration message\n"); 653 return; 654 } 655 656 /* Generate reply for request (if can't, return request) */ 657 658 rep_buf = tipc_cfg_do_cmd(orig->node, 659 ntohs(req_hdr->tcm_type), 660 msg + sizeof(*req_hdr), 661 size - sizeof(*req_hdr), 662 BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); 663 if (rep_buf) { 664 skb_push(rep_buf, sizeof(*rep_hdr)); 665 rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data; 666 memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); 667 rep_hdr->tcm_len = htonl(rep_buf->len); 668 rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); 669 } else { 670 rep_buf = *buf; 671 *buf = NULL; 672 } 673 674 /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */ 675 tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); 676} 677 678int tipc_cfg_init(void) 679{ 680 struct tipc_name_seq seq; 681 int res; 682 683 memset(&mng, 0, sizeof(mng)); 684 INIT_LIST_HEAD(&mng.link_subscribers); 685 686 res = tipc_attach(&mng.user_ref, NULL, NULL); 687 if (res) 688 goto failed; 689 690 res = tipc_createport(mng.user_ref, NULL, TIPC_CRITICAL_IMPORTANCE, 691 NULL, NULL, NULL, 692 NULL, cfg_named_msg_event, NULL, 693 NULL, &mng.port_ref); 694 if (res) 695 goto failed; 696 697 seq.type = TIPC_CFG_SRV; 698 seq.lower = seq.upper = tipc_own_addr; 699 res = tipc_nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq); 700 if (res) 701 goto failed; 702 703 return 0; 704 705failed: 706 err("Unable to create configuration service\n"); 707 tipc_detach(mng.user_ref); 708 mng.user_ref = 0; 709 return res; 710} 711 712void tipc_cfg_stop(void) 713{ 714 if (mng.user_ref) { 715 tipc_detach(mng.user_ref); 716 mng.user_ref = 0; 717 } 718}