📄 config.c
字号:
/* * net/tipc/config.c: TIPC configuration management code * * Copyright (c) 2002-2006, Ericsson AB * Copyright (c) 2004-2006, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include "core.h"#include "dbg.h"#include "bearer.h"#include "port.h"#include "link.h"#include "zone.h"#include "addr.h"#include "name_table.h"#include "node.h"#include "config.h"#include "discover.h"struct subscr_data { char usr_handle[8]; u32 domain; u32 port_ref; struct list_head subd_list;};struct manager { u32 user_ref; u32 port_ref; u32 subscr_ref; u32 link_subscriptions; struct list_head link_subscribers;};static struct manager mng = { 0};static DEFINE_SPINLOCK(config_lock);static const void *req_tlv_area; /* request message TLV area */static int req_tlv_space; /* request message TLV area size */static int rep_headroom; /* reply message headroom to use */void tipc_cfg_link_event(u32 addr, char *name, int up){ /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */}struct sk_buff *tipc_cfg_reply_alloc(int payload_size){ struct sk_buff *buf; buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC); if (buf) skb_reserve(buf, rep_headroom); return buf;}int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, void *tlv_data, int tlv_data_size){ struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf); int new_tlv_space = TLV_SPACE(tlv_data_size); if (skb_tailroom(buf) < new_tlv_space) { dbg("tipc_cfg_append_tlv unable to append TLV\n"); return 0; } skb_put(buf, new_tlv_space); tlv->tlv_type = htons(tlv_type); tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); if (tlv_data_size && tlv_data) memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size); return 1;}struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value){ struct sk_buff *buf; __be32 value_net; buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value))); if (buf) { value_net = htonl(value); tipc_cfg_append_tlv(buf, tlv_type, &value_net, sizeof(value_net)); } return buf;}struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string){ struct sk_buff *buf; int string_len = strlen(string) + 1; buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len)); if (buf) tipc_cfg_append_tlv(buf, tlv_type, string, string_len); return buf;}#if 0/* Now obsolete code for handling commands not yet implemented the new way */int tipc_cfg_cmd(const struct tipc_cmd_msg * msg, char *data, u32 sz, u32 *ret_size, struct tipc_portid *orig){ int rv = -EINVAL; u32 cmd = msg->cmd; *ret_size = 0; switch (cmd) { case TIPC_REMOVE_LINK: case TIPC_CMD_BLOCK_LINK: case TIPC_CMD_UNBLOCK_LINK: if (!cfg_check_connection(orig)) rv = link_control(msg->argv.link_name, msg->cmd, 0); break; case TIPC_ESTABLISH: { int connected; tipc_isconnected(mng.conn_port_ref, &connected); if (connected || !orig) { rv = TIPC_FAILURE; break; } rv = tipc_connect2port(mng.conn_port_ref, orig); if (rv == TIPC_OK) orig = 0; break; } case TIPC_GET_PEER_ADDRESS: *ret_size = link_peer_addr(msg->argv.link_name, data, sz); break; case TIPC_GET_ROUTES: rv = TIPC_OK; break; default: {} } if (*ret_size) rv = TIPC_OK; return rv;}static void cfg_cmd_event(struct tipc_cmd_msg *msg, char *data, u32 sz, struct tipc_portid const *orig){ int rv = -EINVAL; struct tipc_cmd_result_msg rmsg; struct iovec msg_sect[2]; int *arg; msg->cmd = ntohl(msg->cmd); cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect, data, 0); if (ntohl(msg->magic) != TIPC_MAGIC) goto exit; switch (msg->cmd) { case TIPC_CREATE_LINK: if (!cfg_check_connection(orig)) rv = disc_create_link(&msg->argv.create_link); break; case TIPC_LINK_SUBSCRIBE: { struct subscr_data *sub; if (mng.link_subscriptions > 64) break; sub = kmalloc(sizeof(*sub), GFP_ATOMIC); if (sub == NULL) { warn("Memory squeeze; dropped remote link subscription\n"); break; } INIT_LIST_HEAD(&sub->subd_list); tipc_createport(mng.user_ref, (void *)sub, TIPC_HIGH_IMPORTANCE, 0, 0, (tipc_conn_shutdown_event)cfg_linksubscr_cancel, 0, 0, (tipc_conn_msg_event)cfg_linksubscr_cancel, 0, &sub->port_ref); if (!sub->port_ref) { kfree(sub); break; } memcpy(sub->usr_handle,msg->usr_handle, sizeof(sub->usr_handle)); sub->domain = msg->argv.domain; list_add_tail(&sub->subd_list, &mng.link_subscribers); tipc_connect2port(sub->port_ref, orig); rmsg.retval = TIPC_OK; tipc_send(sub->port_ref, 2u, msg_sect); mng.link_subscriptions++; return; } default: rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig); } exit: rmsg.result_len = htonl(msg_sect[1].iov_len); rmsg.retval = htonl(rv); tipc_cfg_respond(msg_sect, 2u, orig);}#endifstatic struct sk_buff *cfg_enable_bearer(void){ struct tipc_bearer_config *args; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); if (tipc_enable_bearer(args->name, ntohl(args->detect_scope), ntohl(args->priority))) return tipc_cfg_reply_error_string("unable to enable bearer"); return tipc_cfg_reply_none();}static struct sk_buff *cfg_disable_bearer(void){ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) return tipc_cfg_reply_error_string("unable to disable bearer"); return tipc_cfg_reply_none();}static struct sk_buff *cfg_set_own_addr(void){ u32 addr; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (addr == tipc_own_addr) return tipc_cfg_reply_none(); if (!tipc_addr_node_valid(addr)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (node address)"); if (tipc_mode == TIPC_NET_MODE) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change node address once assigned)"); tipc_own_addr = addr; /* * Must release all spinlocks before calling start_net() because * Linux version of TIPC calls eth_media_start() which calls * register_netdevice_notifier() which may block! * * Temporarily releasing the lock should be harmless for non-Linux TIPC, * but Linux version of eth_media_start() should really be reworked * so that it can be called with spinlocks held. */ spin_unlock_bh(&config_lock); tipc_core_start_net(); spin_lock_bh(&config_lock); return tipc_cfg_reply_none();}static struct sk_buff *cfg_set_remote_mng(void){ u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); tipc_remote_management = (value != 0); return tipc_cfg_reply_none();}static struct sk_buff *cfg_set_max_publications(void){ u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != delimit(value, 1, 65535)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max publications must be 1-65535)"); tipc_max_publications = value; return tipc_cfg_reply_none();}static struct sk_buff *cfg_set_max_subscriptions(void){ u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); if (value != delimit(value, 1, 65535)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max subscriptions must be 1-65535"); tipc_max_subscriptions = value;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -