Commit b0c1e928c85023c73780b5d9873406ccf1cd8019
Committed by
David S. Miller
1 parent
aa70200e00
Exists in
master
and in
39 other branches
tipc: Remove user registry subsystem
Eliminates routines, data structures, and files that make up TIPC's user registry. The user registry is no longer needed since the native API routines that utilized it no longer exist and there are no longer any internal TIPC services that use it. Signed-off-by: Allan Stephens <Allan.Stephens@windriver.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 8 changed files with 7 additions and 292 deletions Inline Diff
net/tipc/Makefile
1 | # | 1 | # |
2 | # Makefile for the Linux TIPC layer | 2 | # Makefile for the Linux TIPC layer |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_TIPC) := tipc.o | 5 | obj-$(CONFIG_TIPC) := tipc.o |
6 | 6 | ||
7 | tipc-y += addr.o bcast.o bearer.o config.o \ | 7 | tipc-y += addr.o bcast.o bearer.o config.o \ |
8 | core.o handler.o link.o discover.o msg.o \ | 8 | core.o handler.o link.o discover.o msg.o \ |
9 | name_distr.o subscr.o name_table.o net.o \ | 9 | name_distr.o subscr.o name_table.o net.o \ |
10 | netlink.o node.o node_subscr.o port.o ref.o \ | 10 | netlink.o node.o node_subscr.o port.o ref.o \ |
11 | socket.o user_reg.o dbg.o eth_media.o | 11 | socket.o dbg.o eth_media.o |
12 | 12 | ||
13 | # End of file | 13 | # End of file |
14 | 14 |
net/tipc/config.c
1 | /* | 1 | /* |
2 | * net/tipc/config.c: TIPC configuration management code | 2 | * net/tipc/config.c: TIPC configuration management code |
3 | * | 3 | * |
4 | * Copyright (c) 2002-2006, Ericsson AB | 4 | * Copyright (c) 2002-2006, Ericsson AB |
5 | * Copyright (c) 2004-2007, Wind River Systems | 5 | * Copyright (c) 2004-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions are met: | 9 | * modification, are permitted provided that the following conditions are met: |
10 | * | 10 | * |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the names of the copyright holders nor the names of its | 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 | 17 | * contributors may be used to endorse or promote products derived from |
18 | * this software without specific prior written permission. | 18 | * this software without specific prior written permission. |
19 | * | 19 | * |
20 | * Alternatively, this software may be distributed under the terms of the | 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 | 21 | * GNU General Public License ("GPL") version 2 as published by the Free |
22 | * Software Foundation. | 22 | * Software Foundation. |
23 | * | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 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 | 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 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 | 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 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 | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
34 | * POSSIBILITY OF SUCH DAMAGE. | 34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "port.h" | 38 | #include "port.h" |
39 | #include "link.h" | 39 | #include "link.h" |
40 | #include "name_table.h" | 40 | #include "name_table.h" |
41 | #include "config.h" | 41 | #include "config.h" |
42 | 42 | ||
43 | static u32 config_port_ref; | 43 | static u32 config_port_ref; |
44 | 44 | ||
45 | static DEFINE_SPINLOCK(config_lock); | 45 | static DEFINE_SPINLOCK(config_lock); |
46 | 46 | ||
47 | static const void *req_tlv_area; /* request message TLV area */ | 47 | static const void *req_tlv_area; /* request message TLV area */ |
48 | static int req_tlv_space; /* request message TLV area size */ | 48 | static int req_tlv_space; /* request message TLV area size */ |
49 | static int rep_headroom; /* reply message headroom to use */ | 49 | static int rep_headroom; /* reply message headroom to use */ |
50 | 50 | ||
51 | 51 | ||
52 | struct sk_buff *tipc_cfg_reply_alloc(int payload_size) | 52 | struct sk_buff *tipc_cfg_reply_alloc(int payload_size) |
53 | { | 53 | { |
54 | struct sk_buff *buf; | 54 | struct sk_buff *buf; |
55 | 55 | ||
56 | buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC); | 56 | buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC); |
57 | if (buf) | 57 | if (buf) |
58 | skb_reserve(buf, rep_headroom); | 58 | skb_reserve(buf, rep_headroom); |
59 | return buf; | 59 | return buf; |
60 | } | 60 | } |
61 | 61 | ||
62 | int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, | 62 | int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, |
63 | void *tlv_data, int tlv_data_size) | 63 | void *tlv_data, int tlv_data_size) |
64 | { | 64 | { |
65 | struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf); | 65 | struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf); |
66 | int new_tlv_space = TLV_SPACE(tlv_data_size); | 66 | int new_tlv_space = TLV_SPACE(tlv_data_size); |
67 | 67 | ||
68 | if (skb_tailroom(buf) < new_tlv_space) { | 68 | if (skb_tailroom(buf) < new_tlv_space) { |
69 | dbg("tipc_cfg_append_tlv unable to append TLV\n"); | 69 | dbg("tipc_cfg_append_tlv unable to append TLV\n"); |
70 | return 0; | 70 | return 0; |
71 | } | 71 | } |
72 | skb_put(buf, new_tlv_space); | 72 | skb_put(buf, new_tlv_space); |
73 | tlv->tlv_type = htons(tlv_type); | 73 | tlv->tlv_type = htons(tlv_type); |
74 | tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); | 74 | tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); |
75 | if (tlv_data_size && tlv_data) | 75 | if (tlv_data_size && tlv_data) |
76 | memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size); | 76 | memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size); |
77 | return 1; | 77 | return 1; |
78 | } | 78 | } |
79 | 79 | ||
80 | static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value) | 80 | static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value) |
81 | { | 81 | { |
82 | struct sk_buff *buf; | 82 | struct sk_buff *buf; |
83 | __be32 value_net; | 83 | __be32 value_net; |
84 | 84 | ||
85 | buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value))); | 85 | buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value))); |
86 | if (buf) { | 86 | if (buf) { |
87 | value_net = htonl(value); | 87 | value_net = htonl(value); |
88 | tipc_cfg_append_tlv(buf, tlv_type, &value_net, | 88 | tipc_cfg_append_tlv(buf, tlv_type, &value_net, |
89 | sizeof(value_net)); | 89 | sizeof(value_net)); |
90 | } | 90 | } |
91 | return buf; | 91 | return buf; |
92 | } | 92 | } |
93 | 93 | ||
94 | static struct sk_buff *tipc_cfg_reply_unsigned(u32 value) | 94 | static struct sk_buff *tipc_cfg_reply_unsigned(u32 value) |
95 | { | 95 | { |
96 | return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); | 96 | return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); |
97 | } | 97 | } |
98 | 98 | ||
99 | struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) | 99 | struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string) |
100 | { | 100 | { |
101 | struct sk_buff *buf; | 101 | struct sk_buff *buf; |
102 | int string_len = strlen(string) + 1; | 102 | int string_len = strlen(string) + 1; |
103 | 103 | ||
104 | buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len)); | 104 | buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len)); |
105 | if (buf) | 105 | if (buf) |
106 | tipc_cfg_append_tlv(buf, tlv_type, string, string_len); | 106 | tipc_cfg_append_tlv(buf, tlv_type, string, string_len); |
107 | return buf; | 107 | return buf; |
108 | } | 108 | } |
109 | 109 | ||
110 | #define MAX_STATS_INFO 2000 | 110 | #define MAX_STATS_INFO 2000 |
111 | 111 | ||
112 | static struct sk_buff *tipc_show_stats(void) | 112 | static struct sk_buff *tipc_show_stats(void) |
113 | { | 113 | { |
114 | struct sk_buff *buf; | 114 | struct sk_buff *buf; |
115 | struct tlv_desc *rep_tlv; | 115 | struct tlv_desc *rep_tlv; |
116 | struct print_buf pb; | 116 | struct print_buf pb; |
117 | int str_len; | 117 | int str_len; |
118 | u32 value; | 118 | u32 value; |
119 | 119 | ||
120 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | 120 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
121 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 121 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
122 | 122 | ||
123 | value = ntohl(*(u32 *)TLV_DATA(req_tlv_area)); | 123 | value = ntohl(*(u32 *)TLV_DATA(req_tlv_area)); |
124 | if (value != 0) | 124 | if (value != 0) |
125 | return tipc_cfg_reply_error_string("unsupported argument"); | 125 | return tipc_cfg_reply_error_string("unsupported argument"); |
126 | 126 | ||
127 | buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO)); | 127 | buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO)); |
128 | if (buf == NULL) | 128 | if (buf == NULL) |
129 | return NULL; | 129 | return NULL; |
130 | 130 | ||
131 | rep_tlv = (struct tlv_desc *)buf->data; | 131 | rep_tlv = (struct tlv_desc *)buf->data; |
132 | tipc_printbuf_init(&pb, (char *)TLV_DATA(rep_tlv), MAX_STATS_INFO); | 132 | tipc_printbuf_init(&pb, (char *)TLV_DATA(rep_tlv), MAX_STATS_INFO); |
133 | 133 | ||
134 | tipc_printf(&pb, "TIPC version " TIPC_MOD_VER "\n"); | 134 | tipc_printf(&pb, "TIPC version " TIPC_MOD_VER "\n"); |
135 | 135 | ||
136 | /* Use additional tipc_printf()'s to return more info ... */ | 136 | /* Use additional tipc_printf()'s to return more info ... */ |
137 | 137 | ||
138 | str_len = tipc_printbuf_validate(&pb); | 138 | str_len = tipc_printbuf_validate(&pb); |
139 | skb_put(buf, TLV_SPACE(str_len)); | 139 | skb_put(buf, TLV_SPACE(str_len)); |
140 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | 140 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); |
141 | 141 | ||
142 | return buf; | 142 | return buf; |
143 | } | 143 | } |
144 | 144 | ||
145 | static struct sk_buff *cfg_enable_bearer(void) | 145 | static struct sk_buff *cfg_enable_bearer(void) |
146 | { | 146 | { |
147 | struct tipc_bearer_config *args; | 147 | struct tipc_bearer_config *args; |
148 | 148 | ||
149 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) | 149 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) |
150 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 150 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
151 | 151 | ||
152 | args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); | 152 | args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); |
153 | if (tipc_enable_bearer(args->name, | 153 | if (tipc_enable_bearer(args->name, |
154 | ntohl(args->detect_scope), | 154 | ntohl(args->detect_scope), |
155 | ntohl(args->priority))) | 155 | ntohl(args->priority))) |
156 | return tipc_cfg_reply_error_string("unable to enable bearer"); | 156 | return tipc_cfg_reply_error_string("unable to enable bearer"); |
157 | 157 | ||
158 | return tipc_cfg_reply_none(); | 158 | return tipc_cfg_reply_none(); |
159 | } | 159 | } |
160 | 160 | ||
161 | static struct sk_buff *cfg_disable_bearer(void) | 161 | static struct sk_buff *cfg_disable_bearer(void) |
162 | { | 162 | { |
163 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) | 163 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) |
164 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 164 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
165 | 165 | ||
166 | if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) | 166 | if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) |
167 | return tipc_cfg_reply_error_string("unable to disable bearer"); | 167 | return tipc_cfg_reply_error_string("unable to disable bearer"); |
168 | 168 | ||
169 | return tipc_cfg_reply_none(); | 169 | return tipc_cfg_reply_none(); |
170 | } | 170 | } |
171 | 171 | ||
172 | static struct sk_buff *cfg_set_own_addr(void) | 172 | static struct sk_buff *cfg_set_own_addr(void) |
173 | { | 173 | { |
174 | u32 addr; | 174 | u32 addr; |
175 | 175 | ||
176 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | 176 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) |
177 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 177 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
178 | 178 | ||
179 | addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 179 | addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
180 | if (addr == tipc_own_addr) | 180 | if (addr == tipc_own_addr) |
181 | return tipc_cfg_reply_none(); | 181 | return tipc_cfg_reply_none(); |
182 | if (!tipc_addr_node_valid(addr)) | 182 | if (!tipc_addr_node_valid(addr)) |
183 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 183 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
184 | " (node address)"); | 184 | " (node address)"); |
185 | if (tipc_mode == TIPC_NET_MODE) | 185 | if (tipc_mode == TIPC_NET_MODE) |
186 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 186 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
187 | " (cannot change node address once assigned)"); | 187 | " (cannot change node address once assigned)"); |
188 | 188 | ||
189 | /* | 189 | /* |
190 | * Must release all spinlocks before calling start_net() because | 190 | * Must release all spinlocks before calling start_net() because |
191 | * Linux version of TIPC calls eth_media_start() which calls | 191 | * Linux version of TIPC calls eth_media_start() which calls |
192 | * register_netdevice_notifier() which may block! | 192 | * register_netdevice_notifier() which may block! |
193 | * | 193 | * |
194 | * Temporarily releasing the lock should be harmless for non-Linux TIPC, | 194 | * Temporarily releasing the lock should be harmless for non-Linux TIPC, |
195 | * but Linux version of eth_media_start() should really be reworked | 195 | * but Linux version of eth_media_start() should really be reworked |
196 | * so that it can be called with spinlocks held. | 196 | * so that it can be called with spinlocks held. |
197 | */ | 197 | */ |
198 | 198 | ||
199 | spin_unlock_bh(&config_lock); | 199 | spin_unlock_bh(&config_lock); |
200 | tipc_core_start_net(addr); | 200 | tipc_core_start_net(addr); |
201 | spin_lock_bh(&config_lock); | 201 | spin_lock_bh(&config_lock); |
202 | return tipc_cfg_reply_none(); | 202 | return tipc_cfg_reply_none(); |
203 | } | 203 | } |
204 | 204 | ||
205 | static struct sk_buff *cfg_set_remote_mng(void) | 205 | static struct sk_buff *cfg_set_remote_mng(void) |
206 | { | 206 | { |
207 | u32 value; | 207 | u32 value; |
208 | 208 | ||
209 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | 209 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
210 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 210 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
211 | 211 | ||
212 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 212 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
213 | tipc_remote_management = (value != 0); | 213 | tipc_remote_management = (value != 0); |
214 | return tipc_cfg_reply_none(); | 214 | return tipc_cfg_reply_none(); |
215 | } | 215 | } |
216 | 216 | ||
217 | static struct sk_buff *cfg_set_max_publications(void) | 217 | static struct sk_buff *cfg_set_max_publications(void) |
218 | { | 218 | { |
219 | u32 value; | 219 | u32 value; |
220 | 220 | ||
221 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | 221 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
222 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 222 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
223 | 223 | ||
224 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 224 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
225 | if (value != delimit(value, 1, 65535)) | 225 | if (value != delimit(value, 1, 65535)) |
226 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 226 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
227 | " (max publications must be 1-65535)"); | 227 | " (max publications must be 1-65535)"); |
228 | tipc_max_publications = value; | 228 | tipc_max_publications = value; |
229 | return tipc_cfg_reply_none(); | 229 | return tipc_cfg_reply_none(); |
230 | } | 230 | } |
231 | 231 | ||
232 | static struct sk_buff *cfg_set_max_subscriptions(void) | 232 | static struct sk_buff *cfg_set_max_subscriptions(void) |
233 | { | 233 | { |
234 | u32 value; | 234 | u32 value; |
235 | 235 | ||
236 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | 236 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
237 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 237 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
238 | 238 | ||
239 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 239 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
240 | if (value != delimit(value, 1, 65535)) | 240 | if (value != delimit(value, 1, 65535)) |
241 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 241 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
242 | " (max subscriptions must be 1-65535"); | 242 | " (max subscriptions must be 1-65535"); |
243 | tipc_max_subscriptions = value; | 243 | tipc_max_subscriptions = value; |
244 | return tipc_cfg_reply_none(); | 244 | return tipc_cfg_reply_none(); |
245 | } | 245 | } |
246 | 246 | ||
247 | static struct sk_buff *cfg_set_max_ports(void) | 247 | static struct sk_buff *cfg_set_max_ports(void) |
248 | { | 248 | { |
249 | u32 value; | 249 | u32 value; |
250 | 250 | ||
251 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | 251 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
252 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 252 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
253 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 253 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
254 | if (value == tipc_max_ports) | 254 | if (value == tipc_max_ports) |
255 | return tipc_cfg_reply_none(); | 255 | return tipc_cfg_reply_none(); |
256 | if (value != delimit(value, 127, 65535)) | 256 | if (value != delimit(value, 127, 65535)) |
257 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 257 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
258 | " (max ports must be 127-65535)"); | 258 | " (max ports must be 127-65535)"); |
259 | if (tipc_mode != TIPC_NOT_RUNNING) | 259 | if (tipc_mode != TIPC_NOT_RUNNING) |
260 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 260 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
261 | " (cannot change max ports while TIPC is active)"); | 261 | " (cannot change max ports while TIPC is active)"); |
262 | tipc_max_ports = value; | 262 | tipc_max_ports = value; |
263 | return tipc_cfg_reply_none(); | 263 | return tipc_cfg_reply_none(); |
264 | } | 264 | } |
265 | 265 | ||
266 | static struct sk_buff *cfg_set_max_nodes(void) | 266 | static struct sk_buff *cfg_set_max_nodes(void) |
267 | { | 267 | { |
268 | u32 value; | 268 | u32 value; |
269 | 269 | ||
270 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | 270 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
271 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 271 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
272 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 272 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
273 | if (value == tipc_max_nodes) | 273 | if (value == tipc_max_nodes) |
274 | return tipc_cfg_reply_none(); | 274 | return tipc_cfg_reply_none(); |
275 | if (value != delimit(value, 8, 2047)) | 275 | if (value != delimit(value, 8, 2047)) |
276 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 276 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
277 | " (max nodes must be 8-2047)"); | 277 | " (max nodes must be 8-2047)"); |
278 | if (tipc_mode == TIPC_NET_MODE) | 278 | if (tipc_mode == TIPC_NET_MODE) |
279 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 279 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
280 | " (cannot change max nodes once TIPC has joined a network)"); | 280 | " (cannot change max nodes once TIPC has joined a network)"); |
281 | tipc_max_nodes = value; | 281 | tipc_max_nodes = value; |
282 | return tipc_cfg_reply_none(); | 282 | return tipc_cfg_reply_none(); |
283 | } | 283 | } |
284 | 284 | ||
285 | static struct sk_buff *cfg_set_netid(void) | 285 | static struct sk_buff *cfg_set_netid(void) |
286 | { | 286 | { |
287 | u32 value; | 287 | u32 value; |
288 | 288 | ||
289 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | 289 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) |
290 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 290 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
291 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | 291 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); |
292 | if (value == tipc_net_id) | 292 | if (value == tipc_net_id) |
293 | return tipc_cfg_reply_none(); | 293 | return tipc_cfg_reply_none(); |
294 | if (value != delimit(value, 1, 9999)) | 294 | if (value != delimit(value, 1, 9999)) |
295 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 295 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
296 | " (network id must be 1-9999)"); | 296 | " (network id must be 1-9999)"); |
297 | if (tipc_mode == TIPC_NET_MODE) | 297 | if (tipc_mode == TIPC_NET_MODE) |
298 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 298 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
299 | " (cannot change network id once TIPC has joined a network)"); | 299 | " (cannot change network id once TIPC has joined a network)"); |
300 | tipc_net_id = value; | 300 | tipc_net_id = value; |
301 | return tipc_cfg_reply_none(); | 301 | return tipc_cfg_reply_none(); |
302 | } | 302 | } |
303 | 303 | ||
304 | struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, | 304 | struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, |
305 | int request_space, int reply_headroom) | 305 | int request_space, int reply_headroom) |
306 | { | 306 | { |
307 | struct sk_buff *rep_tlv_buf; | 307 | struct sk_buff *rep_tlv_buf; |
308 | 308 | ||
309 | spin_lock_bh(&config_lock); | 309 | spin_lock_bh(&config_lock); |
310 | 310 | ||
311 | /* Save request and reply details in a well-known location */ | 311 | /* Save request and reply details in a well-known location */ |
312 | 312 | ||
313 | req_tlv_area = request_area; | 313 | req_tlv_area = request_area; |
314 | req_tlv_space = request_space; | 314 | req_tlv_space = request_space; |
315 | rep_headroom = reply_headroom; | 315 | rep_headroom = reply_headroom; |
316 | 316 | ||
317 | /* Check command authorization */ | 317 | /* Check command authorization */ |
318 | 318 | ||
319 | if (likely(orig_node == tipc_own_addr)) { | 319 | if (likely(orig_node == tipc_own_addr)) { |
320 | /* command is permitted */ | 320 | /* command is permitted */ |
321 | } else if (cmd >= 0x8000) { | 321 | } else if (cmd >= 0x8000) { |
322 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 322 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
323 | " (cannot be done remotely)"); | 323 | " (cannot be done remotely)"); |
324 | goto exit; | 324 | goto exit; |
325 | } else if (!tipc_remote_management) { | 325 | } else if (!tipc_remote_management) { |
326 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE); | 326 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE); |
327 | goto exit; | 327 | goto exit; |
328 | } | 328 | } |
329 | else if (cmd >= 0x4000) { | 329 | else if (cmd >= 0x4000) { |
330 | u32 domain = 0; | 330 | u32 domain = 0; |
331 | 331 | ||
332 | if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || | 332 | if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || |
333 | (domain != orig_node)) { | 333 | (domain != orig_node)) { |
334 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); | 334 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); |
335 | goto exit; | 335 | goto exit; |
336 | } | 336 | } |
337 | } | 337 | } |
338 | 338 | ||
339 | /* Call appropriate processing routine */ | 339 | /* Call appropriate processing routine */ |
340 | 340 | ||
341 | switch (cmd) { | 341 | switch (cmd) { |
342 | case TIPC_CMD_NOOP: | 342 | case TIPC_CMD_NOOP: |
343 | rep_tlv_buf = tipc_cfg_reply_none(); | 343 | rep_tlv_buf = tipc_cfg_reply_none(); |
344 | break; | 344 | break; |
345 | case TIPC_CMD_GET_NODES: | 345 | case TIPC_CMD_GET_NODES: |
346 | rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space); | 346 | rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space); |
347 | break; | 347 | break; |
348 | case TIPC_CMD_GET_LINKS: | 348 | case TIPC_CMD_GET_LINKS: |
349 | rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space); | 349 | rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space); |
350 | break; | 350 | break; |
351 | case TIPC_CMD_SHOW_LINK_STATS: | 351 | case TIPC_CMD_SHOW_LINK_STATS: |
352 | rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space); | 352 | rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space); |
353 | break; | 353 | break; |
354 | case TIPC_CMD_RESET_LINK_STATS: | 354 | case TIPC_CMD_RESET_LINK_STATS: |
355 | rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space); | 355 | rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space); |
356 | break; | 356 | break; |
357 | case TIPC_CMD_SHOW_NAME_TABLE: | 357 | case TIPC_CMD_SHOW_NAME_TABLE: |
358 | rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space); | 358 | rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space); |
359 | break; | 359 | break; |
360 | case TIPC_CMD_GET_BEARER_NAMES: | 360 | case TIPC_CMD_GET_BEARER_NAMES: |
361 | rep_tlv_buf = tipc_bearer_get_names(); | 361 | rep_tlv_buf = tipc_bearer_get_names(); |
362 | break; | 362 | break; |
363 | case TIPC_CMD_GET_MEDIA_NAMES: | 363 | case TIPC_CMD_GET_MEDIA_NAMES: |
364 | rep_tlv_buf = tipc_media_get_names(); | 364 | rep_tlv_buf = tipc_media_get_names(); |
365 | break; | 365 | break; |
366 | case TIPC_CMD_SHOW_PORTS: | 366 | case TIPC_CMD_SHOW_PORTS: |
367 | rep_tlv_buf = tipc_port_get_ports(); | 367 | rep_tlv_buf = tipc_port_get_ports(); |
368 | break; | 368 | break; |
369 | case TIPC_CMD_SET_LOG_SIZE: | 369 | case TIPC_CMD_SET_LOG_SIZE: |
370 | rep_tlv_buf = tipc_log_resize_cmd(req_tlv_area, req_tlv_space); | 370 | rep_tlv_buf = tipc_log_resize_cmd(req_tlv_area, req_tlv_space); |
371 | break; | 371 | break; |
372 | case TIPC_CMD_DUMP_LOG: | 372 | case TIPC_CMD_DUMP_LOG: |
373 | rep_tlv_buf = tipc_log_dump(); | 373 | rep_tlv_buf = tipc_log_dump(); |
374 | break; | 374 | break; |
375 | case TIPC_CMD_SHOW_STATS: | 375 | case TIPC_CMD_SHOW_STATS: |
376 | rep_tlv_buf = tipc_show_stats(); | 376 | rep_tlv_buf = tipc_show_stats(); |
377 | break; | 377 | break; |
378 | case TIPC_CMD_SET_LINK_TOL: | 378 | case TIPC_CMD_SET_LINK_TOL: |
379 | case TIPC_CMD_SET_LINK_PRI: | 379 | case TIPC_CMD_SET_LINK_PRI: |
380 | case TIPC_CMD_SET_LINK_WINDOW: | 380 | case TIPC_CMD_SET_LINK_WINDOW: |
381 | rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd); | 381 | rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd); |
382 | break; | 382 | break; |
383 | case TIPC_CMD_ENABLE_BEARER: | 383 | case TIPC_CMD_ENABLE_BEARER: |
384 | rep_tlv_buf = cfg_enable_bearer(); | 384 | rep_tlv_buf = cfg_enable_bearer(); |
385 | break; | 385 | break; |
386 | case TIPC_CMD_DISABLE_BEARER: | 386 | case TIPC_CMD_DISABLE_BEARER: |
387 | rep_tlv_buf = cfg_disable_bearer(); | 387 | rep_tlv_buf = cfg_disable_bearer(); |
388 | break; | 388 | break; |
389 | case TIPC_CMD_SET_NODE_ADDR: | 389 | case TIPC_CMD_SET_NODE_ADDR: |
390 | rep_tlv_buf = cfg_set_own_addr(); | 390 | rep_tlv_buf = cfg_set_own_addr(); |
391 | break; | 391 | break; |
392 | case TIPC_CMD_SET_REMOTE_MNG: | 392 | case TIPC_CMD_SET_REMOTE_MNG: |
393 | rep_tlv_buf = cfg_set_remote_mng(); | 393 | rep_tlv_buf = cfg_set_remote_mng(); |
394 | break; | 394 | break; |
395 | case TIPC_CMD_SET_MAX_PORTS: | 395 | case TIPC_CMD_SET_MAX_PORTS: |
396 | rep_tlv_buf = cfg_set_max_ports(); | 396 | rep_tlv_buf = cfg_set_max_ports(); |
397 | break; | 397 | break; |
398 | case TIPC_CMD_SET_MAX_PUBL: | 398 | case TIPC_CMD_SET_MAX_PUBL: |
399 | rep_tlv_buf = cfg_set_max_publications(); | 399 | rep_tlv_buf = cfg_set_max_publications(); |
400 | break; | 400 | break; |
401 | case TIPC_CMD_SET_MAX_SUBSCR: | 401 | case TIPC_CMD_SET_MAX_SUBSCR: |
402 | rep_tlv_buf = cfg_set_max_subscriptions(); | 402 | rep_tlv_buf = cfg_set_max_subscriptions(); |
403 | break; | 403 | break; |
404 | case TIPC_CMD_SET_MAX_NODES: | 404 | case TIPC_CMD_SET_MAX_NODES: |
405 | rep_tlv_buf = cfg_set_max_nodes(); | 405 | rep_tlv_buf = cfg_set_max_nodes(); |
406 | break; | 406 | break; |
407 | case TIPC_CMD_SET_NETID: | 407 | case TIPC_CMD_SET_NETID: |
408 | rep_tlv_buf = cfg_set_netid(); | 408 | rep_tlv_buf = cfg_set_netid(); |
409 | break; | 409 | break; |
410 | case TIPC_CMD_GET_REMOTE_MNG: | 410 | case TIPC_CMD_GET_REMOTE_MNG: |
411 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management); | 411 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management); |
412 | break; | 412 | break; |
413 | case TIPC_CMD_GET_MAX_PORTS: | 413 | case TIPC_CMD_GET_MAX_PORTS: |
414 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports); | 414 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports); |
415 | break; | 415 | break; |
416 | case TIPC_CMD_GET_MAX_PUBL: | 416 | case TIPC_CMD_GET_MAX_PUBL: |
417 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_publications); | 417 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_publications); |
418 | break; | 418 | break; |
419 | case TIPC_CMD_GET_MAX_SUBSCR: | 419 | case TIPC_CMD_GET_MAX_SUBSCR: |
420 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions); | 420 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions); |
421 | break; | 421 | break; |
422 | case TIPC_CMD_GET_MAX_NODES: | 422 | case TIPC_CMD_GET_MAX_NODES: |
423 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes); | 423 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes); |
424 | break; | 424 | break; |
425 | case TIPC_CMD_GET_NETID: | 425 | case TIPC_CMD_GET_NETID: |
426 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); | 426 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); |
427 | break; | 427 | break; |
428 | case TIPC_CMD_NOT_NET_ADMIN: | 428 | case TIPC_CMD_NOT_NET_ADMIN: |
429 | rep_tlv_buf = | 429 | rep_tlv_buf = |
430 | tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); | 430 | tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); |
431 | break; | 431 | break; |
432 | case TIPC_CMD_SET_MAX_ZONES: | 432 | case TIPC_CMD_SET_MAX_ZONES: |
433 | case TIPC_CMD_GET_MAX_ZONES: | 433 | case TIPC_CMD_GET_MAX_ZONES: |
434 | case TIPC_CMD_SET_MAX_SLAVES: | 434 | case TIPC_CMD_SET_MAX_SLAVES: |
435 | case TIPC_CMD_GET_MAX_SLAVES: | 435 | case TIPC_CMD_GET_MAX_SLAVES: |
436 | case TIPC_CMD_SET_MAX_CLUSTERS: | 436 | case TIPC_CMD_SET_MAX_CLUSTERS: |
437 | case TIPC_CMD_GET_MAX_CLUSTERS: | 437 | case TIPC_CMD_GET_MAX_CLUSTERS: |
438 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 438 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
439 | " (obsolete command)"); | 439 | " (obsolete command)"); |
440 | break; | 440 | break; |
441 | default: | 441 | default: |
442 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 442 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
443 | " (unknown command)"); | 443 | " (unknown command)"); |
444 | break; | 444 | break; |
445 | } | 445 | } |
446 | 446 | ||
447 | /* Return reply buffer */ | 447 | /* Return reply buffer */ |
448 | exit: | 448 | exit: |
449 | spin_unlock_bh(&config_lock); | 449 | spin_unlock_bh(&config_lock); |
450 | return rep_tlv_buf; | 450 | return rep_tlv_buf; |
451 | } | 451 | } |
452 | 452 | ||
453 | static void cfg_named_msg_event(void *userdata, | 453 | static void cfg_named_msg_event(void *userdata, |
454 | u32 port_ref, | 454 | u32 port_ref, |
455 | struct sk_buff **buf, | 455 | struct sk_buff **buf, |
456 | const unchar *msg, | 456 | const unchar *msg, |
457 | u32 size, | 457 | u32 size, |
458 | u32 importance, | 458 | u32 importance, |
459 | struct tipc_portid const *orig, | 459 | struct tipc_portid const *orig, |
460 | struct tipc_name_seq const *dest) | 460 | struct tipc_name_seq const *dest) |
461 | { | 461 | { |
462 | struct tipc_cfg_msg_hdr *req_hdr; | 462 | struct tipc_cfg_msg_hdr *req_hdr; |
463 | struct tipc_cfg_msg_hdr *rep_hdr; | 463 | struct tipc_cfg_msg_hdr *rep_hdr; |
464 | struct sk_buff *rep_buf; | 464 | struct sk_buff *rep_buf; |
465 | 465 | ||
466 | /* Validate configuration message header (ignore invalid message) */ | 466 | /* Validate configuration message header (ignore invalid message) */ |
467 | 467 | ||
468 | req_hdr = (struct tipc_cfg_msg_hdr *)msg; | 468 | req_hdr = (struct tipc_cfg_msg_hdr *)msg; |
469 | if ((size < sizeof(*req_hdr)) || | 469 | if ((size < sizeof(*req_hdr)) || |
470 | (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || | 470 | (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || |
471 | (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { | 471 | (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { |
472 | warn("Invalid configuration message discarded\n"); | 472 | warn("Invalid configuration message discarded\n"); |
473 | return; | 473 | return; |
474 | } | 474 | } |
475 | 475 | ||
476 | /* Generate reply for request (if can't, return request) */ | 476 | /* Generate reply for request (if can't, return request) */ |
477 | 477 | ||
478 | rep_buf = tipc_cfg_do_cmd(orig->node, | 478 | rep_buf = tipc_cfg_do_cmd(orig->node, |
479 | ntohs(req_hdr->tcm_type), | 479 | ntohs(req_hdr->tcm_type), |
480 | msg + sizeof(*req_hdr), | 480 | msg + sizeof(*req_hdr), |
481 | size - sizeof(*req_hdr), | 481 | size - sizeof(*req_hdr), |
482 | BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); | 482 | BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); |
483 | if (rep_buf) { | 483 | if (rep_buf) { |
484 | skb_push(rep_buf, sizeof(*rep_hdr)); | 484 | skb_push(rep_buf, sizeof(*rep_hdr)); |
485 | rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data; | 485 | rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data; |
486 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); | 486 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); |
487 | rep_hdr->tcm_len = htonl(rep_buf->len); | 487 | rep_hdr->tcm_len = htonl(rep_buf->len); |
488 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); | 488 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); |
489 | } else { | 489 | } else { |
490 | rep_buf = *buf; | 490 | rep_buf = *buf; |
491 | *buf = NULL; | 491 | *buf = NULL; |
492 | } | 492 | } |
493 | 493 | ||
494 | /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */ | 494 | /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */ |
495 | tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); | 495 | tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); |
496 | } | 496 | } |
497 | 497 | ||
498 | int tipc_cfg_init(void) | 498 | int tipc_cfg_init(void) |
499 | { | 499 | { |
500 | struct tipc_name_seq seq; | 500 | struct tipc_name_seq seq; |
501 | int res; | 501 | int res; |
502 | 502 | ||
503 | res = tipc_createport(0, NULL, TIPC_CRITICAL_IMPORTANCE, | 503 | res = tipc_createport(NULL, TIPC_CRITICAL_IMPORTANCE, |
504 | NULL, NULL, NULL, | 504 | NULL, NULL, NULL, |
505 | NULL, cfg_named_msg_event, NULL, | 505 | NULL, cfg_named_msg_event, NULL, |
506 | NULL, &config_port_ref); | 506 | NULL, &config_port_ref); |
507 | if (res) | 507 | if (res) |
508 | goto failed; | 508 | goto failed; |
509 | 509 | ||
510 | seq.type = TIPC_CFG_SRV; | 510 | seq.type = TIPC_CFG_SRV; |
511 | seq.lower = seq.upper = tipc_own_addr; | 511 | seq.lower = seq.upper = tipc_own_addr; |
512 | res = tipc_nametbl_publish_rsv(config_port_ref, TIPC_ZONE_SCOPE, &seq); | 512 | res = tipc_nametbl_publish_rsv(config_port_ref, TIPC_ZONE_SCOPE, &seq); |
513 | if (res) | 513 | if (res) |
514 | goto failed; | 514 | goto failed; |
515 | 515 | ||
516 | return 0; | 516 | return 0; |
517 | 517 | ||
518 | failed: | 518 | failed: |
519 | err("Unable to create configuration service\n"); | 519 | err("Unable to create configuration service\n"); |
520 | return res; | 520 | return res; |
521 | } | 521 | } |
522 | 522 | ||
523 | void tipc_cfg_stop(void) | 523 | void tipc_cfg_stop(void) |
524 | { | 524 | { |
525 | if (config_port_ref) { | 525 | if (config_port_ref) { |
526 | tipc_deleteport(config_port_ref); | 526 | tipc_deleteport(config_port_ref); |
527 | config_port_ref = 0; | 527 | config_port_ref = 0; |
528 | } | 528 | } |
529 | } | 529 | } |
530 | 530 |
net/tipc/core.c
1 | /* | 1 | /* |
2 | * net/tipc/core.c: TIPC module code | 2 | * net/tipc/core.c: TIPC module code |
3 | * | 3 | * |
4 | * Copyright (c) 2003-2006, Ericsson AB | 4 | * Copyright (c) 2003-2006, Ericsson AB |
5 | * Copyright (c) 2005-2006, Wind River Systems | 5 | * Copyright (c) 2005-2006, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions are met: | 9 | * modification, are permitted provided that the following conditions are met: |
10 | * | 10 | * |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the names of the copyright holders nor the names of its | 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 | 17 | * contributors may be used to endorse or promote products derived from |
18 | * this software without specific prior written permission. | 18 | * this software without specific prior written permission. |
19 | * | 19 | * |
20 | * Alternatively, this software may be distributed under the terms of the | 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 | 21 | * GNU General Public License ("GPL") version 2 as published by the Free |
22 | * Software Foundation. | 22 | * Software Foundation. |
23 | * | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 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 | 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 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 | 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 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 | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
34 | * POSSIBILITY OF SUCH DAMAGE. | 34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/kernel.h> | 39 | #include <linux/kernel.h> |
40 | #include <linux/random.h> | 40 | #include <linux/random.h> |
41 | 41 | ||
42 | #include "core.h" | 42 | #include "core.h" |
43 | #include "ref.h" | 43 | #include "ref.h" |
44 | #include "net.h" | 44 | #include "net.h" |
45 | #include "user_reg.h" | ||
46 | #include "name_table.h" | 45 | #include "name_table.h" |
47 | #include "subscr.h" | 46 | #include "subscr.h" |
48 | #include "config.h" | 47 | #include "config.h" |
49 | 48 | ||
50 | 49 | ||
51 | #ifndef CONFIG_TIPC_NODES | 50 | #ifndef CONFIG_TIPC_NODES |
52 | #define CONFIG_TIPC_NODES 255 | 51 | #define CONFIG_TIPC_NODES 255 |
53 | #endif | 52 | #endif |
54 | 53 | ||
55 | #ifndef CONFIG_TIPC_PORTS | 54 | #ifndef CONFIG_TIPC_PORTS |
56 | #define CONFIG_TIPC_PORTS 8191 | 55 | #define CONFIG_TIPC_PORTS 8191 |
57 | #endif | 56 | #endif |
58 | 57 | ||
59 | #ifndef CONFIG_TIPC_LOG | 58 | #ifndef CONFIG_TIPC_LOG |
60 | #define CONFIG_TIPC_LOG 0 | 59 | #define CONFIG_TIPC_LOG 0 |
61 | #endif | 60 | #endif |
62 | 61 | ||
63 | /* global variables used by multiple sub-systems within TIPC */ | 62 | /* global variables used by multiple sub-systems within TIPC */ |
64 | 63 | ||
65 | int tipc_mode = TIPC_NOT_RUNNING; | 64 | int tipc_mode = TIPC_NOT_RUNNING; |
66 | int tipc_random; | 65 | int tipc_random; |
67 | atomic_t tipc_user_count = ATOMIC_INIT(0); | 66 | atomic_t tipc_user_count = ATOMIC_INIT(0); |
68 | 67 | ||
69 | const char tipc_alphabet[] = | 68 | const char tipc_alphabet[] = |
70 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."; | 69 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."; |
71 | 70 | ||
72 | /* configurable TIPC parameters */ | 71 | /* configurable TIPC parameters */ |
73 | 72 | ||
74 | u32 tipc_own_addr; | 73 | u32 tipc_own_addr; |
75 | int tipc_max_nodes; | 74 | int tipc_max_nodes; |
76 | int tipc_max_ports; | 75 | int tipc_max_ports; |
77 | int tipc_max_subscriptions; | 76 | int tipc_max_subscriptions; |
78 | int tipc_max_publications; | 77 | int tipc_max_publications; |
79 | int tipc_net_id; | 78 | int tipc_net_id; |
80 | int tipc_remote_management; | 79 | int tipc_remote_management; |
81 | 80 | ||
82 | 81 | ||
83 | /** | 82 | /** |
84 | * tipc_buf_acquire - creates a TIPC message buffer | 83 | * tipc_buf_acquire - creates a TIPC message buffer |
85 | * @size: message size (including TIPC header) | 84 | * @size: message size (including TIPC header) |
86 | * | 85 | * |
87 | * Returns a new buffer with data pointers set to the specified size. | 86 | * Returns a new buffer with data pointers set to the specified size. |
88 | * | 87 | * |
89 | * NOTE: Headroom is reserved to allow prepending of a data link header. | 88 | * NOTE: Headroom is reserved to allow prepending of a data link header. |
90 | * There may also be unrequested tailroom present at the buffer's end. | 89 | * There may also be unrequested tailroom present at the buffer's end. |
91 | */ | 90 | */ |
92 | 91 | ||
93 | struct sk_buff *tipc_buf_acquire(u32 size) | 92 | struct sk_buff *tipc_buf_acquire(u32 size) |
94 | { | 93 | { |
95 | struct sk_buff *skb; | 94 | struct sk_buff *skb; |
96 | unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; | 95 | unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; |
97 | 96 | ||
98 | skb = alloc_skb_fclone(buf_size, GFP_ATOMIC); | 97 | skb = alloc_skb_fclone(buf_size, GFP_ATOMIC); |
99 | if (skb) { | 98 | if (skb) { |
100 | skb_reserve(skb, BUF_HEADROOM); | 99 | skb_reserve(skb, BUF_HEADROOM); |
101 | skb_put(skb, size); | 100 | skb_put(skb, size); |
102 | skb->next = NULL; | 101 | skb->next = NULL; |
103 | } | 102 | } |
104 | return skb; | 103 | return skb; |
105 | } | 104 | } |
106 | 105 | ||
107 | /** | 106 | /** |
108 | * tipc_core_stop_net - shut down TIPC networking sub-systems | 107 | * tipc_core_stop_net - shut down TIPC networking sub-systems |
109 | */ | 108 | */ |
110 | 109 | ||
111 | static void tipc_core_stop_net(void) | 110 | static void tipc_core_stop_net(void) |
112 | { | 111 | { |
113 | tipc_eth_media_stop(); | 112 | tipc_eth_media_stop(); |
114 | tipc_net_stop(); | 113 | tipc_net_stop(); |
115 | } | 114 | } |
116 | 115 | ||
117 | /** | 116 | /** |
118 | * start_net - start TIPC networking sub-systems | 117 | * start_net - start TIPC networking sub-systems |
119 | */ | 118 | */ |
120 | 119 | ||
121 | int tipc_core_start_net(unsigned long addr) | 120 | int tipc_core_start_net(unsigned long addr) |
122 | { | 121 | { |
123 | int res; | 122 | int res; |
124 | 123 | ||
125 | if ((res = tipc_net_start(addr)) || | 124 | if ((res = tipc_net_start(addr)) || |
126 | (res = tipc_eth_media_start())) { | 125 | (res = tipc_eth_media_start())) { |
127 | tipc_core_stop_net(); | 126 | tipc_core_stop_net(); |
128 | } | 127 | } |
129 | return res; | 128 | return res; |
130 | } | 129 | } |
131 | 130 | ||
132 | /** | 131 | /** |
133 | * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode | 132 | * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode |
134 | */ | 133 | */ |
135 | 134 | ||
136 | static void tipc_core_stop(void) | 135 | static void tipc_core_stop(void) |
137 | { | 136 | { |
138 | if (tipc_mode != TIPC_NODE_MODE) | 137 | if (tipc_mode != TIPC_NODE_MODE) |
139 | return; | 138 | return; |
140 | 139 | ||
141 | tipc_mode = TIPC_NOT_RUNNING; | 140 | tipc_mode = TIPC_NOT_RUNNING; |
142 | 141 | ||
143 | tipc_netlink_stop(); | 142 | tipc_netlink_stop(); |
144 | tipc_handler_stop(); | 143 | tipc_handler_stop(); |
145 | tipc_cfg_stop(); | 144 | tipc_cfg_stop(); |
146 | tipc_subscr_stop(); | 145 | tipc_subscr_stop(); |
147 | tipc_reg_stop(); | ||
148 | tipc_nametbl_stop(); | 146 | tipc_nametbl_stop(); |
149 | tipc_ref_table_stop(); | 147 | tipc_ref_table_stop(); |
150 | tipc_socket_stop(); | 148 | tipc_socket_stop(); |
151 | tipc_log_resize(0); | 149 | tipc_log_resize(0); |
152 | } | 150 | } |
153 | 151 | ||
154 | /** | 152 | /** |
155 | * tipc_core_start - switch TIPC from NOT RUNNING to SINGLE NODE mode | 153 | * tipc_core_start - switch TIPC from NOT RUNNING to SINGLE NODE mode |
156 | */ | 154 | */ |
157 | 155 | ||
158 | static int tipc_core_start(void) | 156 | static int tipc_core_start(void) |
159 | { | 157 | { |
160 | int res; | 158 | int res; |
161 | 159 | ||
162 | if (tipc_mode != TIPC_NOT_RUNNING) | 160 | if (tipc_mode != TIPC_NOT_RUNNING) |
163 | return -ENOPROTOOPT; | 161 | return -ENOPROTOOPT; |
164 | 162 | ||
165 | get_random_bytes(&tipc_random, sizeof(tipc_random)); | 163 | get_random_bytes(&tipc_random, sizeof(tipc_random)); |
166 | tipc_mode = TIPC_NODE_MODE; | 164 | tipc_mode = TIPC_NODE_MODE; |
167 | 165 | ||
168 | if ((res = tipc_handler_start()) || | 166 | if ((res = tipc_handler_start()) || |
169 | (res = tipc_ref_table_init(tipc_max_ports, tipc_random)) || | 167 | (res = tipc_ref_table_init(tipc_max_ports, tipc_random)) || |
170 | (res = tipc_reg_start()) || | ||
171 | (res = tipc_nametbl_init()) || | 168 | (res = tipc_nametbl_init()) || |
172 | (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) || | 169 | (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) || |
173 | (res = tipc_k_signal((Handler)tipc_cfg_init, 0)) || | 170 | (res = tipc_k_signal((Handler)tipc_cfg_init, 0)) || |
174 | (res = tipc_netlink_start()) || | 171 | (res = tipc_netlink_start()) || |
175 | (res = tipc_socket_init())) { | 172 | (res = tipc_socket_init())) { |
176 | tipc_core_stop(); | 173 | tipc_core_stop(); |
177 | } | 174 | } |
178 | return res; | 175 | return res; |
179 | } | 176 | } |
180 | 177 | ||
181 | 178 | ||
182 | static int __init tipc_init(void) | 179 | static int __init tipc_init(void) |
183 | { | 180 | { |
184 | int res; | 181 | int res; |
185 | 182 | ||
186 | if (tipc_log_resize(CONFIG_TIPC_LOG) != 0) | 183 | if (tipc_log_resize(CONFIG_TIPC_LOG) != 0) |
187 | warn("Unable to create log buffer\n"); | 184 | warn("Unable to create log buffer\n"); |
188 | 185 | ||
189 | info("Activated (version " TIPC_MOD_VER | 186 | info("Activated (version " TIPC_MOD_VER |
190 | " compiled " __DATE__ " " __TIME__ ")\n"); | 187 | " compiled " __DATE__ " " __TIME__ ")\n"); |
191 | 188 | ||
192 | tipc_own_addr = 0; | 189 | tipc_own_addr = 0; |
193 | tipc_remote_management = 1; | 190 | tipc_remote_management = 1; |
194 | tipc_max_publications = 10000; | 191 | tipc_max_publications = 10000; |
195 | tipc_max_subscriptions = 2000; | 192 | tipc_max_subscriptions = 2000; |
196 | tipc_max_ports = CONFIG_TIPC_PORTS; | 193 | tipc_max_ports = CONFIG_TIPC_PORTS; |
197 | tipc_max_nodes = CONFIG_TIPC_NODES; | 194 | tipc_max_nodes = CONFIG_TIPC_NODES; |
198 | tipc_net_id = 4711; | 195 | tipc_net_id = 4711; |
199 | 196 | ||
200 | if ((res = tipc_core_start())) | 197 | if ((res = tipc_core_start())) |
201 | err("Unable to start in single node mode\n"); | 198 | err("Unable to start in single node mode\n"); |
202 | else | 199 | else |
203 | info("Started in single node mode\n"); | 200 | info("Started in single node mode\n"); |
204 | return res; | 201 | return res; |
205 | } | 202 | } |
206 | 203 | ||
207 | static void __exit tipc_exit(void) | 204 | static void __exit tipc_exit(void) |
208 | { | 205 | { |
209 | tipc_core_stop_net(); | 206 | tipc_core_stop_net(); |
210 | tipc_core_stop(); | 207 | tipc_core_stop(); |
211 | info("Deactivated\n"); | 208 | info("Deactivated\n"); |
212 | } | 209 | } |
213 | 210 | ||
214 | module_init(tipc_init); | 211 | module_init(tipc_init); |
215 | module_exit(tipc_exit); | 212 | module_exit(tipc_exit); |
216 | 213 | ||
217 | MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication"); | 214 | MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication"); |
218 | MODULE_LICENSE("Dual BSD/GPL"); | 215 | MODULE_LICENSE("Dual BSD/GPL"); |
219 | MODULE_VERSION(TIPC_MOD_VER); | 216 | MODULE_VERSION(TIPC_MOD_VER); |
220 | 217 |
net/tipc/port.c
1 | /* | 1 | /* |
2 | * net/tipc/port.c: TIPC port code | 2 | * net/tipc/port.c: TIPC port code |
3 | * | 3 | * |
4 | * Copyright (c) 1992-2007, Ericsson AB | 4 | * Copyright (c) 1992-2007, Ericsson AB |
5 | * Copyright (c) 2004-2008, Wind River Systems | 5 | * Copyright (c) 2004-2008, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions are met: | 9 | * modification, are permitted provided that the following conditions are met: |
10 | * | 10 | * |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the names of the copyright holders nor the names of its | 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 | 17 | * contributors may be used to endorse or promote products derived from |
18 | * this software without specific prior written permission. | 18 | * this software without specific prior written permission. |
19 | * | 19 | * |
20 | * Alternatively, this software may be distributed under the terms of the | 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 | 21 | * GNU General Public License ("GPL") version 2 as published by the Free |
22 | * Software Foundation. | 22 | * Software Foundation. |
23 | * | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 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 | 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 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 | 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 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 | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
34 | * POSSIBILITY OF SUCH DAMAGE. | 34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "config.h" | 38 | #include "config.h" |
39 | #include "port.h" | 39 | #include "port.h" |
40 | #include "name_table.h" | 40 | #include "name_table.h" |
41 | #include "user_reg.h" | ||
42 | 41 | ||
43 | /* Connection management: */ | 42 | /* Connection management: */ |
44 | #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ | 43 | #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ |
45 | #define CONFIRMED 0 | 44 | #define CONFIRMED 0 |
46 | #define PROBING 1 | 45 | #define PROBING 1 |
47 | 46 | ||
48 | #define MAX_REJECT_SIZE 1024 | 47 | #define MAX_REJECT_SIZE 1024 |
49 | 48 | ||
50 | static struct sk_buff *msg_queue_head = NULL; | 49 | static struct sk_buff *msg_queue_head = NULL; |
51 | static struct sk_buff *msg_queue_tail = NULL; | 50 | static struct sk_buff *msg_queue_tail = NULL; |
52 | 51 | ||
53 | DEFINE_SPINLOCK(tipc_port_list_lock); | 52 | DEFINE_SPINLOCK(tipc_port_list_lock); |
54 | static DEFINE_SPINLOCK(queue_lock); | 53 | static DEFINE_SPINLOCK(queue_lock); |
55 | 54 | ||
56 | static LIST_HEAD(ports); | 55 | static LIST_HEAD(ports); |
57 | static void port_handle_node_down(unsigned long ref); | 56 | static void port_handle_node_down(unsigned long ref); |
58 | static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err); | 57 | static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err); |
59 | static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err); | 58 | static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err); |
60 | static void port_timeout(unsigned long ref); | 59 | static void port_timeout(unsigned long ref); |
61 | 60 | ||
62 | 61 | ||
63 | static u32 port_peernode(struct port *p_ptr) | 62 | static u32 port_peernode(struct port *p_ptr) |
64 | { | 63 | { |
65 | return msg_destnode(&p_ptr->publ.phdr); | 64 | return msg_destnode(&p_ptr->publ.phdr); |
66 | } | 65 | } |
67 | 66 | ||
68 | static u32 port_peerport(struct port *p_ptr) | 67 | static u32 port_peerport(struct port *p_ptr) |
69 | { | 68 | { |
70 | return msg_destport(&p_ptr->publ.phdr); | 69 | return msg_destport(&p_ptr->publ.phdr); |
71 | } | 70 | } |
72 | 71 | ||
73 | static u32 port_out_seqno(struct port *p_ptr) | 72 | static u32 port_out_seqno(struct port *p_ptr) |
74 | { | 73 | { |
75 | return msg_transp_seqno(&p_ptr->publ.phdr); | 74 | return msg_transp_seqno(&p_ptr->publ.phdr); |
76 | } | 75 | } |
77 | 76 | ||
78 | static void port_incr_out_seqno(struct port *p_ptr) | 77 | static void port_incr_out_seqno(struct port *p_ptr) |
79 | { | 78 | { |
80 | struct tipc_msg *m = &p_ptr->publ.phdr; | 79 | struct tipc_msg *m = &p_ptr->publ.phdr; |
81 | 80 | ||
82 | if (likely(!msg_routed(m))) | 81 | if (likely(!msg_routed(m))) |
83 | return; | 82 | return; |
84 | msg_set_transp_seqno(m, (msg_transp_seqno(m) + 1)); | 83 | msg_set_transp_seqno(m, (msg_transp_seqno(m) + 1)); |
85 | } | 84 | } |
86 | 85 | ||
87 | /** | 86 | /** |
88 | * tipc_multicast - send a multicast message to local and remote destinations | 87 | * tipc_multicast - send a multicast message to local and remote destinations |
89 | */ | 88 | */ |
90 | 89 | ||
91 | int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, | 90 | int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, |
92 | u32 num_sect, struct iovec const *msg_sect) | 91 | u32 num_sect, struct iovec const *msg_sect) |
93 | { | 92 | { |
94 | struct tipc_msg *hdr; | 93 | struct tipc_msg *hdr; |
95 | struct sk_buff *buf; | 94 | struct sk_buff *buf; |
96 | struct sk_buff *ibuf = NULL; | 95 | struct sk_buff *ibuf = NULL; |
97 | struct port_list dports = {0, NULL, }; | 96 | struct port_list dports = {0, NULL, }; |
98 | struct port *oport = tipc_port_deref(ref); | 97 | struct port *oport = tipc_port_deref(ref); |
99 | int ext_targets; | 98 | int ext_targets; |
100 | int res; | 99 | int res; |
101 | 100 | ||
102 | if (unlikely(!oport)) | 101 | if (unlikely(!oport)) |
103 | return -EINVAL; | 102 | return -EINVAL; |
104 | 103 | ||
105 | /* Create multicast message */ | 104 | /* Create multicast message */ |
106 | 105 | ||
107 | hdr = &oport->publ.phdr; | 106 | hdr = &oport->publ.phdr; |
108 | msg_set_type(hdr, TIPC_MCAST_MSG); | 107 | msg_set_type(hdr, TIPC_MCAST_MSG); |
109 | msg_set_nametype(hdr, seq->type); | 108 | msg_set_nametype(hdr, seq->type); |
110 | msg_set_namelower(hdr, seq->lower); | 109 | msg_set_namelower(hdr, seq->lower); |
111 | msg_set_nameupper(hdr, seq->upper); | 110 | msg_set_nameupper(hdr, seq->upper); |
112 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); | 111 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); |
113 | res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, | 112 | res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, |
114 | !oport->user_port, &buf); | 113 | !oport->user_port, &buf); |
115 | if (unlikely(!buf)) | 114 | if (unlikely(!buf)) |
116 | return res; | 115 | return res; |
117 | 116 | ||
118 | /* Figure out where to send multicast message */ | 117 | /* Figure out where to send multicast message */ |
119 | 118 | ||
120 | ext_targets = tipc_nametbl_mc_translate(seq->type, seq->lower, seq->upper, | 119 | ext_targets = tipc_nametbl_mc_translate(seq->type, seq->lower, seq->upper, |
121 | TIPC_NODE_SCOPE, &dports); | 120 | TIPC_NODE_SCOPE, &dports); |
122 | 121 | ||
123 | /* Send message to destinations (duplicate it only if necessary) */ | 122 | /* Send message to destinations (duplicate it only if necessary) */ |
124 | 123 | ||
125 | if (ext_targets) { | 124 | if (ext_targets) { |
126 | if (dports.count != 0) { | 125 | if (dports.count != 0) { |
127 | ibuf = skb_copy(buf, GFP_ATOMIC); | 126 | ibuf = skb_copy(buf, GFP_ATOMIC); |
128 | if (ibuf == NULL) { | 127 | if (ibuf == NULL) { |
129 | tipc_port_list_free(&dports); | 128 | tipc_port_list_free(&dports); |
130 | buf_discard(buf); | 129 | buf_discard(buf); |
131 | return -ENOMEM; | 130 | return -ENOMEM; |
132 | } | 131 | } |
133 | } | 132 | } |
134 | res = tipc_bclink_send_msg(buf); | 133 | res = tipc_bclink_send_msg(buf); |
135 | if ((res < 0) && (dports.count != 0)) { | 134 | if ((res < 0) && (dports.count != 0)) { |
136 | buf_discard(ibuf); | 135 | buf_discard(ibuf); |
137 | } | 136 | } |
138 | } else { | 137 | } else { |
139 | ibuf = buf; | 138 | ibuf = buf; |
140 | } | 139 | } |
141 | 140 | ||
142 | if (res >= 0) { | 141 | if (res >= 0) { |
143 | if (ibuf) | 142 | if (ibuf) |
144 | tipc_port_recv_mcast(ibuf, &dports); | 143 | tipc_port_recv_mcast(ibuf, &dports); |
145 | } else { | 144 | } else { |
146 | tipc_port_list_free(&dports); | 145 | tipc_port_list_free(&dports); |
147 | } | 146 | } |
148 | return res; | 147 | return res; |
149 | } | 148 | } |
150 | 149 | ||
151 | /** | 150 | /** |
152 | * tipc_port_recv_mcast - deliver multicast message to all destination ports | 151 | * tipc_port_recv_mcast - deliver multicast message to all destination ports |
153 | * | 152 | * |
154 | * If there is no port list, perform a lookup to create one | 153 | * If there is no port list, perform a lookup to create one |
155 | */ | 154 | */ |
156 | 155 | ||
157 | void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp) | 156 | void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp) |
158 | { | 157 | { |
159 | struct tipc_msg* msg; | 158 | struct tipc_msg* msg; |
160 | struct port_list dports = {0, NULL, }; | 159 | struct port_list dports = {0, NULL, }; |
161 | struct port_list *item = dp; | 160 | struct port_list *item = dp; |
162 | int cnt = 0; | 161 | int cnt = 0; |
163 | 162 | ||
164 | msg = buf_msg(buf); | 163 | msg = buf_msg(buf); |
165 | 164 | ||
166 | /* Create destination port list, if one wasn't supplied */ | 165 | /* Create destination port list, if one wasn't supplied */ |
167 | 166 | ||
168 | if (dp == NULL) { | 167 | if (dp == NULL) { |
169 | tipc_nametbl_mc_translate(msg_nametype(msg), | 168 | tipc_nametbl_mc_translate(msg_nametype(msg), |
170 | msg_namelower(msg), | 169 | msg_namelower(msg), |
171 | msg_nameupper(msg), | 170 | msg_nameupper(msg), |
172 | TIPC_CLUSTER_SCOPE, | 171 | TIPC_CLUSTER_SCOPE, |
173 | &dports); | 172 | &dports); |
174 | item = dp = &dports; | 173 | item = dp = &dports; |
175 | } | 174 | } |
176 | 175 | ||
177 | /* Deliver a copy of message to each destination port */ | 176 | /* Deliver a copy of message to each destination port */ |
178 | 177 | ||
179 | if (dp->count != 0) { | 178 | if (dp->count != 0) { |
180 | if (dp->count == 1) { | 179 | if (dp->count == 1) { |
181 | msg_set_destport(msg, dp->ports[0]); | 180 | msg_set_destport(msg, dp->ports[0]); |
182 | tipc_port_recv_msg(buf); | 181 | tipc_port_recv_msg(buf); |
183 | tipc_port_list_free(dp); | 182 | tipc_port_list_free(dp); |
184 | return; | 183 | return; |
185 | } | 184 | } |
186 | for (; cnt < dp->count; cnt++) { | 185 | for (; cnt < dp->count; cnt++) { |
187 | int index = cnt % PLSIZE; | 186 | int index = cnt % PLSIZE; |
188 | struct sk_buff *b = skb_clone(buf, GFP_ATOMIC); | 187 | struct sk_buff *b = skb_clone(buf, GFP_ATOMIC); |
189 | 188 | ||
190 | if (b == NULL) { | 189 | if (b == NULL) { |
191 | warn("Unable to deliver multicast message(s)\n"); | 190 | warn("Unable to deliver multicast message(s)\n"); |
192 | msg_dbg(msg, "LOST:"); | 191 | msg_dbg(msg, "LOST:"); |
193 | goto exit; | 192 | goto exit; |
194 | } | 193 | } |
195 | if ((index == 0) && (cnt != 0)) { | 194 | if ((index == 0) && (cnt != 0)) { |
196 | item = item->next; | 195 | item = item->next; |
197 | } | 196 | } |
198 | msg_set_destport(buf_msg(b),item->ports[index]); | 197 | msg_set_destport(buf_msg(b),item->ports[index]); |
199 | tipc_port_recv_msg(b); | 198 | tipc_port_recv_msg(b); |
200 | } | 199 | } |
201 | } | 200 | } |
202 | exit: | 201 | exit: |
203 | buf_discard(buf); | 202 | buf_discard(buf); |
204 | tipc_port_list_free(dp); | 203 | tipc_port_list_free(dp); |
205 | } | 204 | } |
206 | 205 | ||
207 | /** | 206 | /** |
208 | * tipc_createport_raw - create a generic TIPC port | 207 | * tipc_createport_raw - create a generic TIPC port |
209 | * | 208 | * |
210 | * Returns pointer to (locked) TIPC port, or NULL if unable to create it | 209 | * Returns pointer to (locked) TIPC port, or NULL if unable to create it |
211 | */ | 210 | */ |
212 | 211 | ||
213 | struct tipc_port *tipc_createport_raw(void *usr_handle, | 212 | struct tipc_port *tipc_createport_raw(void *usr_handle, |
214 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), | 213 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), |
215 | void (*wakeup)(struct tipc_port *), | 214 | void (*wakeup)(struct tipc_port *), |
216 | const u32 importance) | 215 | const u32 importance) |
217 | { | 216 | { |
218 | struct port *p_ptr; | 217 | struct port *p_ptr; |
219 | struct tipc_msg *msg; | 218 | struct tipc_msg *msg; |
220 | u32 ref; | 219 | u32 ref; |
221 | 220 | ||
222 | p_ptr = kzalloc(sizeof(*p_ptr), GFP_ATOMIC); | 221 | p_ptr = kzalloc(sizeof(*p_ptr), GFP_ATOMIC); |
223 | if (!p_ptr) { | 222 | if (!p_ptr) { |
224 | warn("Port creation failed, no memory\n"); | 223 | warn("Port creation failed, no memory\n"); |
225 | return NULL; | 224 | return NULL; |
226 | } | 225 | } |
227 | ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock); | 226 | ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock); |
228 | if (!ref) { | 227 | if (!ref) { |
229 | warn("Port creation failed, reference table exhausted\n"); | 228 | warn("Port creation failed, reference table exhausted\n"); |
230 | kfree(p_ptr); | 229 | kfree(p_ptr); |
231 | return NULL; | 230 | return NULL; |
232 | } | 231 | } |
233 | 232 | ||
234 | p_ptr->publ.usr_handle = usr_handle; | 233 | p_ptr->publ.usr_handle = usr_handle; |
235 | p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; | 234 | p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; |
236 | p_ptr->publ.ref = ref; | 235 | p_ptr->publ.ref = ref; |
237 | msg = &p_ptr->publ.phdr; | 236 | msg = &p_ptr->publ.phdr; |
238 | tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0); | 237 | tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0); |
239 | msg_set_origport(msg, ref); | 238 | msg_set_origport(msg, ref); |
240 | p_ptr->last_in_seqno = 41; | 239 | p_ptr->last_in_seqno = 41; |
241 | p_ptr->sent = 1; | 240 | p_ptr->sent = 1; |
242 | INIT_LIST_HEAD(&p_ptr->wait_list); | 241 | INIT_LIST_HEAD(&p_ptr->wait_list); |
243 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); | 242 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); |
244 | p_ptr->dispatcher = dispatcher; | 243 | p_ptr->dispatcher = dispatcher; |
245 | p_ptr->wakeup = wakeup; | 244 | p_ptr->wakeup = wakeup; |
246 | p_ptr->user_port = NULL; | 245 | p_ptr->user_port = NULL; |
247 | k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); | 246 | k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); |
248 | spin_lock_bh(&tipc_port_list_lock); | 247 | spin_lock_bh(&tipc_port_list_lock); |
249 | INIT_LIST_HEAD(&p_ptr->publications); | 248 | INIT_LIST_HEAD(&p_ptr->publications); |
250 | INIT_LIST_HEAD(&p_ptr->port_list); | 249 | INIT_LIST_HEAD(&p_ptr->port_list); |
251 | list_add_tail(&p_ptr->port_list, &ports); | 250 | list_add_tail(&p_ptr->port_list, &ports); |
252 | spin_unlock_bh(&tipc_port_list_lock); | 251 | spin_unlock_bh(&tipc_port_list_lock); |
253 | return &(p_ptr->publ); | 252 | return &(p_ptr->publ); |
254 | } | 253 | } |
255 | 254 | ||
256 | int tipc_deleteport(u32 ref) | 255 | int tipc_deleteport(u32 ref) |
257 | { | 256 | { |
258 | struct port *p_ptr; | 257 | struct port *p_ptr; |
259 | struct sk_buff *buf = NULL; | 258 | struct sk_buff *buf = NULL; |
260 | 259 | ||
261 | tipc_withdraw(ref, 0, NULL); | 260 | tipc_withdraw(ref, 0, NULL); |
262 | p_ptr = tipc_port_lock(ref); | 261 | p_ptr = tipc_port_lock(ref); |
263 | if (!p_ptr) | 262 | if (!p_ptr) |
264 | return -EINVAL; | 263 | return -EINVAL; |
265 | 264 | ||
266 | tipc_ref_discard(ref); | 265 | tipc_ref_discard(ref); |
267 | tipc_port_unlock(p_ptr); | 266 | tipc_port_unlock(p_ptr); |
268 | 267 | ||
269 | k_cancel_timer(&p_ptr->timer); | 268 | k_cancel_timer(&p_ptr->timer); |
270 | if (p_ptr->publ.connected) { | 269 | if (p_ptr->publ.connected) { |
271 | buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); | 270 | buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); |
272 | tipc_nodesub_unsubscribe(&p_ptr->subscription); | 271 | tipc_nodesub_unsubscribe(&p_ptr->subscription); |
273 | } | 272 | } |
274 | if (p_ptr->user_port) { | 273 | if (p_ptr->user_port) { |
275 | tipc_reg_remove_port(p_ptr->user_port); | ||
276 | kfree(p_ptr->user_port); | 274 | kfree(p_ptr->user_port); |
277 | } | 275 | } |
278 | 276 | ||
279 | spin_lock_bh(&tipc_port_list_lock); | 277 | spin_lock_bh(&tipc_port_list_lock); |
280 | list_del(&p_ptr->port_list); | 278 | list_del(&p_ptr->port_list); |
281 | list_del(&p_ptr->wait_list); | 279 | list_del(&p_ptr->wait_list); |
282 | spin_unlock_bh(&tipc_port_list_lock); | 280 | spin_unlock_bh(&tipc_port_list_lock); |
283 | k_term_timer(&p_ptr->timer); | 281 | k_term_timer(&p_ptr->timer); |
284 | kfree(p_ptr); | 282 | kfree(p_ptr); |
285 | dbg("Deleted port %u\n", ref); | 283 | dbg("Deleted port %u\n", ref); |
286 | tipc_net_route_msg(buf); | 284 | tipc_net_route_msg(buf); |
287 | return 0; | 285 | return 0; |
288 | } | 286 | } |
289 | 287 | ||
290 | static int port_unreliable(struct port *p_ptr) | 288 | static int port_unreliable(struct port *p_ptr) |
291 | { | 289 | { |
292 | return msg_src_droppable(&p_ptr->publ.phdr); | 290 | return msg_src_droppable(&p_ptr->publ.phdr); |
293 | } | 291 | } |
294 | 292 | ||
295 | int tipc_portunreliable(u32 ref, unsigned int *isunreliable) | 293 | int tipc_portunreliable(u32 ref, unsigned int *isunreliable) |
296 | { | 294 | { |
297 | struct port *p_ptr; | 295 | struct port *p_ptr; |
298 | 296 | ||
299 | p_ptr = tipc_port_lock(ref); | 297 | p_ptr = tipc_port_lock(ref); |
300 | if (!p_ptr) | 298 | if (!p_ptr) |
301 | return -EINVAL; | 299 | return -EINVAL; |
302 | *isunreliable = port_unreliable(p_ptr); | 300 | *isunreliable = port_unreliable(p_ptr); |
303 | tipc_port_unlock(p_ptr); | 301 | tipc_port_unlock(p_ptr); |
304 | return 0; | 302 | return 0; |
305 | } | 303 | } |
306 | 304 | ||
307 | int tipc_set_portunreliable(u32 ref, unsigned int isunreliable) | 305 | int tipc_set_portunreliable(u32 ref, unsigned int isunreliable) |
308 | { | 306 | { |
309 | struct port *p_ptr; | 307 | struct port *p_ptr; |
310 | 308 | ||
311 | p_ptr = tipc_port_lock(ref); | 309 | p_ptr = tipc_port_lock(ref); |
312 | if (!p_ptr) | 310 | if (!p_ptr) |
313 | return -EINVAL; | 311 | return -EINVAL; |
314 | msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0)); | 312 | msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0)); |
315 | tipc_port_unlock(p_ptr); | 313 | tipc_port_unlock(p_ptr); |
316 | return 0; | 314 | return 0; |
317 | } | 315 | } |
318 | 316 | ||
319 | static int port_unreturnable(struct port *p_ptr) | 317 | static int port_unreturnable(struct port *p_ptr) |
320 | { | 318 | { |
321 | return msg_dest_droppable(&p_ptr->publ.phdr); | 319 | return msg_dest_droppable(&p_ptr->publ.phdr); |
322 | } | 320 | } |
323 | 321 | ||
324 | int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable) | 322 | int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable) |
325 | { | 323 | { |
326 | struct port *p_ptr; | 324 | struct port *p_ptr; |
327 | 325 | ||
328 | p_ptr = tipc_port_lock(ref); | 326 | p_ptr = tipc_port_lock(ref); |
329 | if (!p_ptr) | 327 | if (!p_ptr) |
330 | return -EINVAL; | 328 | return -EINVAL; |
331 | *isunrejectable = port_unreturnable(p_ptr); | 329 | *isunrejectable = port_unreturnable(p_ptr); |
332 | tipc_port_unlock(p_ptr); | 330 | tipc_port_unlock(p_ptr); |
333 | return 0; | 331 | return 0; |
334 | } | 332 | } |
335 | 333 | ||
336 | int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable) | 334 | int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable) |
337 | { | 335 | { |
338 | struct port *p_ptr; | 336 | struct port *p_ptr; |
339 | 337 | ||
340 | p_ptr = tipc_port_lock(ref); | 338 | p_ptr = tipc_port_lock(ref); |
341 | if (!p_ptr) | 339 | if (!p_ptr) |
342 | return -EINVAL; | 340 | return -EINVAL; |
343 | msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0)); | 341 | msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0)); |
344 | tipc_port_unlock(p_ptr); | 342 | tipc_port_unlock(p_ptr); |
345 | return 0; | 343 | return 0; |
346 | } | 344 | } |
347 | 345 | ||
348 | /* | 346 | /* |
349 | * port_build_proto_msg(): build a port level protocol | 347 | * port_build_proto_msg(): build a port level protocol |
350 | * or a connection abortion message. Called with | 348 | * or a connection abortion message. Called with |
351 | * tipc_port lock on. | 349 | * tipc_port lock on. |
352 | */ | 350 | */ |
353 | static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, | 351 | static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, |
354 | u32 origport, u32 orignode, | 352 | u32 origport, u32 orignode, |
355 | u32 usr, u32 type, u32 err, | 353 | u32 usr, u32 type, u32 err, |
356 | u32 seqno, u32 ack) | 354 | u32 seqno, u32 ack) |
357 | { | 355 | { |
358 | struct sk_buff *buf; | 356 | struct sk_buff *buf; |
359 | struct tipc_msg *msg; | 357 | struct tipc_msg *msg; |
360 | 358 | ||
361 | buf = tipc_buf_acquire(LONG_H_SIZE); | 359 | buf = tipc_buf_acquire(LONG_H_SIZE); |
362 | if (buf) { | 360 | if (buf) { |
363 | msg = buf_msg(buf); | 361 | msg = buf_msg(buf); |
364 | tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode); | 362 | tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode); |
365 | msg_set_errcode(msg, err); | 363 | msg_set_errcode(msg, err); |
366 | msg_set_destport(msg, destport); | 364 | msg_set_destport(msg, destport); |
367 | msg_set_origport(msg, origport); | 365 | msg_set_origport(msg, origport); |
368 | msg_set_orignode(msg, orignode); | 366 | msg_set_orignode(msg, orignode); |
369 | msg_set_transp_seqno(msg, seqno); | 367 | msg_set_transp_seqno(msg, seqno); |
370 | msg_set_msgcnt(msg, ack); | 368 | msg_set_msgcnt(msg, ack); |
371 | msg_dbg(msg, "PORT>SEND>:"); | 369 | msg_dbg(msg, "PORT>SEND>:"); |
372 | } | 370 | } |
373 | return buf; | 371 | return buf; |
374 | } | 372 | } |
375 | 373 | ||
376 | int tipc_reject_msg(struct sk_buff *buf, u32 err) | 374 | int tipc_reject_msg(struct sk_buff *buf, u32 err) |
377 | { | 375 | { |
378 | struct tipc_msg *msg = buf_msg(buf); | 376 | struct tipc_msg *msg = buf_msg(buf); |
379 | struct sk_buff *rbuf; | 377 | struct sk_buff *rbuf; |
380 | struct tipc_msg *rmsg; | 378 | struct tipc_msg *rmsg; |
381 | int hdr_sz; | 379 | int hdr_sz; |
382 | u32 imp = msg_importance(msg); | 380 | u32 imp = msg_importance(msg); |
383 | u32 data_sz = msg_data_sz(msg); | 381 | u32 data_sz = msg_data_sz(msg); |
384 | 382 | ||
385 | if (data_sz > MAX_REJECT_SIZE) | 383 | if (data_sz > MAX_REJECT_SIZE) |
386 | data_sz = MAX_REJECT_SIZE; | 384 | data_sz = MAX_REJECT_SIZE; |
387 | if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE)) | 385 | if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE)) |
388 | imp++; | 386 | imp++; |
389 | msg_dbg(msg, "port->rej: "); | 387 | msg_dbg(msg, "port->rej: "); |
390 | 388 | ||
391 | /* discard rejected message if it shouldn't be returned to sender */ | 389 | /* discard rejected message if it shouldn't be returned to sender */ |
392 | if (msg_errcode(msg) || msg_dest_droppable(msg)) { | 390 | if (msg_errcode(msg) || msg_dest_droppable(msg)) { |
393 | buf_discard(buf); | 391 | buf_discard(buf); |
394 | return data_sz; | 392 | return data_sz; |
395 | } | 393 | } |
396 | 394 | ||
397 | /* construct rejected message */ | 395 | /* construct rejected message */ |
398 | if (msg_mcast(msg)) | 396 | if (msg_mcast(msg)) |
399 | hdr_sz = MCAST_H_SIZE; | 397 | hdr_sz = MCAST_H_SIZE; |
400 | else | 398 | else |
401 | hdr_sz = LONG_H_SIZE; | 399 | hdr_sz = LONG_H_SIZE; |
402 | rbuf = tipc_buf_acquire(data_sz + hdr_sz); | 400 | rbuf = tipc_buf_acquire(data_sz + hdr_sz); |
403 | if (rbuf == NULL) { | 401 | if (rbuf == NULL) { |
404 | buf_discard(buf); | 402 | buf_discard(buf); |
405 | return data_sz; | 403 | return data_sz; |
406 | } | 404 | } |
407 | rmsg = buf_msg(rbuf); | 405 | rmsg = buf_msg(rbuf); |
408 | tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg)); | 406 | tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg)); |
409 | msg_set_errcode(rmsg, err); | 407 | msg_set_errcode(rmsg, err); |
410 | msg_set_destport(rmsg, msg_origport(msg)); | 408 | msg_set_destport(rmsg, msg_origport(msg)); |
411 | msg_set_origport(rmsg, msg_destport(msg)); | 409 | msg_set_origport(rmsg, msg_destport(msg)); |
412 | if (msg_short(msg)) { | 410 | if (msg_short(msg)) { |
413 | msg_set_orignode(rmsg, tipc_own_addr); | 411 | msg_set_orignode(rmsg, tipc_own_addr); |
414 | /* leave name type & instance as zeroes */ | 412 | /* leave name type & instance as zeroes */ |
415 | } else { | 413 | } else { |
416 | msg_set_orignode(rmsg, msg_destnode(msg)); | 414 | msg_set_orignode(rmsg, msg_destnode(msg)); |
417 | msg_set_nametype(rmsg, msg_nametype(msg)); | 415 | msg_set_nametype(rmsg, msg_nametype(msg)); |
418 | msg_set_nameinst(rmsg, msg_nameinst(msg)); | 416 | msg_set_nameinst(rmsg, msg_nameinst(msg)); |
419 | } | 417 | } |
420 | msg_set_size(rmsg, data_sz + hdr_sz); | 418 | msg_set_size(rmsg, data_sz + hdr_sz); |
421 | skb_copy_to_linear_data_offset(rbuf, hdr_sz, msg_data(msg), data_sz); | 419 | skb_copy_to_linear_data_offset(rbuf, hdr_sz, msg_data(msg), data_sz); |
422 | 420 | ||
423 | /* send self-abort message when rejecting on a connected port */ | 421 | /* send self-abort message when rejecting on a connected port */ |
424 | if (msg_connected(msg)) { | 422 | if (msg_connected(msg)) { |
425 | struct sk_buff *abuf = NULL; | 423 | struct sk_buff *abuf = NULL; |
426 | struct port *p_ptr = tipc_port_lock(msg_destport(msg)); | 424 | struct port *p_ptr = tipc_port_lock(msg_destport(msg)); |
427 | 425 | ||
428 | if (p_ptr) { | 426 | if (p_ptr) { |
429 | if (p_ptr->publ.connected) | 427 | if (p_ptr->publ.connected) |
430 | abuf = port_build_self_abort_msg(p_ptr, err); | 428 | abuf = port_build_self_abort_msg(p_ptr, err); |
431 | tipc_port_unlock(p_ptr); | 429 | tipc_port_unlock(p_ptr); |
432 | } | 430 | } |
433 | tipc_net_route_msg(abuf); | 431 | tipc_net_route_msg(abuf); |
434 | } | 432 | } |
435 | 433 | ||
436 | /* send rejected message */ | 434 | /* send rejected message */ |
437 | buf_discard(buf); | 435 | buf_discard(buf); |
438 | tipc_net_route_msg(rbuf); | 436 | tipc_net_route_msg(rbuf); |
439 | return data_sz; | 437 | return data_sz; |
440 | } | 438 | } |
441 | 439 | ||
442 | int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, | 440 | int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, |
443 | struct iovec const *msg_sect, u32 num_sect, | 441 | struct iovec const *msg_sect, u32 num_sect, |
444 | int err) | 442 | int err) |
445 | { | 443 | { |
446 | struct sk_buff *buf; | 444 | struct sk_buff *buf; |
447 | int res; | 445 | int res; |
448 | 446 | ||
449 | res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, | 447 | res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, |
450 | !p_ptr->user_port, &buf); | 448 | !p_ptr->user_port, &buf); |
451 | if (!buf) | 449 | if (!buf) |
452 | return res; | 450 | return res; |
453 | 451 | ||
454 | return tipc_reject_msg(buf, err); | 452 | return tipc_reject_msg(buf, err); |
455 | } | 453 | } |
456 | 454 | ||
457 | static void port_timeout(unsigned long ref) | 455 | static void port_timeout(unsigned long ref) |
458 | { | 456 | { |
459 | struct port *p_ptr = tipc_port_lock(ref); | 457 | struct port *p_ptr = tipc_port_lock(ref); |
460 | struct sk_buff *buf = NULL; | 458 | struct sk_buff *buf = NULL; |
461 | 459 | ||
462 | if (!p_ptr) | 460 | if (!p_ptr) |
463 | return; | 461 | return; |
464 | 462 | ||
465 | if (!p_ptr->publ.connected) { | 463 | if (!p_ptr->publ.connected) { |
466 | tipc_port_unlock(p_ptr); | 464 | tipc_port_unlock(p_ptr); |
467 | return; | 465 | return; |
468 | } | 466 | } |
469 | 467 | ||
470 | /* Last probe answered ? */ | 468 | /* Last probe answered ? */ |
471 | if (p_ptr->probing_state == PROBING) { | 469 | if (p_ptr->probing_state == PROBING) { |
472 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); | 470 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); |
473 | } else { | 471 | } else { |
474 | buf = port_build_proto_msg(port_peerport(p_ptr), | 472 | buf = port_build_proto_msg(port_peerport(p_ptr), |
475 | port_peernode(p_ptr), | 473 | port_peernode(p_ptr), |
476 | p_ptr->publ.ref, | 474 | p_ptr->publ.ref, |
477 | tipc_own_addr, | 475 | tipc_own_addr, |
478 | CONN_MANAGER, | 476 | CONN_MANAGER, |
479 | CONN_PROBE, | 477 | CONN_PROBE, |
480 | TIPC_OK, | 478 | TIPC_OK, |
481 | port_out_seqno(p_ptr), | 479 | port_out_seqno(p_ptr), |
482 | 0); | 480 | 0); |
483 | port_incr_out_seqno(p_ptr); | 481 | port_incr_out_seqno(p_ptr); |
484 | p_ptr->probing_state = PROBING; | 482 | p_ptr->probing_state = PROBING; |
485 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); | 483 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); |
486 | } | 484 | } |
487 | tipc_port_unlock(p_ptr); | 485 | tipc_port_unlock(p_ptr); |
488 | tipc_net_route_msg(buf); | 486 | tipc_net_route_msg(buf); |
489 | } | 487 | } |
490 | 488 | ||
491 | 489 | ||
492 | static void port_handle_node_down(unsigned long ref) | 490 | static void port_handle_node_down(unsigned long ref) |
493 | { | 491 | { |
494 | struct port *p_ptr = tipc_port_lock(ref); | 492 | struct port *p_ptr = tipc_port_lock(ref); |
495 | struct sk_buff* buf = NULL; | 493 | struct sk_buff* buf = NULL; |
496 | 494 | ||
497 | if (!p_ptr) | 495 | if (!p_ptr) |
498 | return; | 496 | return; |
499 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE); | 497 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE); |
500 | tipc_port_unlock(p_ptr); | 498 | tipc_port_unlock(p_ptr); |
501 | tipc_net_route_msg(buf); | 499 | tipc_net_route_msg(buf); |
502 | } | 500 | } |
503 | 501 | ||
504 | 502 | ||
505 | static struct sk_buff *port_build_self_abort_msg(struct port *p_ptr, u32 err) | 503 | static struct sk_buff *port_build_self_abort_msg(struct port *p_ptr, u32 err) |
506 | { | 504 | { |
507 | u32 imp = msg_importance(&p_ptr->publ.phdr); | 505 | u32 imp = msg_importance(&p_ptr->publ.phdr); |
508 | 506 | ||
509 | if (!p_ptr->publ.connected) | 507 | if (!p_ptr->publ.connected) |
510 | return NULL; | 508 | return NULL; |
511 | if (imp < TIPC_CRITICAL_IMPORTANCE) | 509 | if (imp < TIPC_CRITICAL_IMPORTANCE) |
512 | imp++; | 510 | imp++; |
513 | return port_build_proto_msg(p_ptr->publ.ref, | 511 | return port_build_proto_msg(p_ptr->publ.ref, |
514 | tipc_own_addr, | 512 | tipc_own_addr, |
515 | port_peerport(p_ptr), | 513 | port_peerport(p_ptr), |
516 | port_peernode(p_ptr), | 514 | port_peernode(p_ptr), |
517 | imp, | 515 | imp, |
518 | TIPC_CONN_MSG, | 516 | TIPC_CONN_MSG, |
519 | err, | 517 | err, |
520 | p_ptr->last_in_seqno + 1, | 518 | p_ptr->last_in_seqno + 1, |
521 | 0); | 519 | 0); |
522 | } | 520 | } |
523 | 521 | ||
524 | 522 | ||
525 | static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err) | 523 | static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err) |
526 | { | 524 | { |
527 | u32 imp = msg_importance(&p_ptr->publ.phdr); | 525 | u32 imp = msg_importance(&p_ptr->publ.phdr); |
528 | 526 | ||
529 | if (!p_ptr->publ.connected) | 527 | if (!p_ptr->publ.connected) |
530 | return NULL; | 528 | return NULL; |
531 | if (imp < TIPC_CRITICAL_IMPORTANCE) | 529 | if (imp < TIPC_CRITICAL_IMPORTANCE) |
532 | imp++; | 530 | imp++; |
533 | return port_build_proto_msg(port_peerport(p_ptr), | 531 | return port_build_proto_msg(port_peerport(p_ptr), |
534 | port_peernode(p_ptr), | 532 | port_peernode(p_ptr), |
535 | p_ptr->publ.ref, | 533 | p_ptr->publ.ref, |
536 | tipc_own_addr, | 534 | tipc_own_addr, |
537 | imp, | 535 | imp, |
538 | TIPC_CONN_MSG, | 536 | TIPC_CONN_MSG, |
539 | err, | 537 | err, |
540 | port_out_seqno(p_ptr), | 538 | port_out_seqno(p_ptr), |
541 | 0); | 539 | 0); |
542 | } | 540 | } |
543 | 541 | ||
544 | void tipc_port_recv_proto_msg(struct sk_buff *buf) | 542 | void tipc_port_recv_proto_msg(struct sk_buff *buf) |
545 | { | 543 | { |
546 | struct tipc_msg *msg = buf_msg(buf); | 544 | struct tipc_msg *msg = buf_msg(buf); |
547 | struct port *p_ptr = tipc_port_lock(msg_destport(msg)); | 545 | struct port *p_ptr = tipc_port_lock(msg_destport(msg)); |
548 | u32 err = TIPC_OK; | 546 | u32 err = TIPC_OK; |
549 | struct sk_buff *r_buf = NULL; | 547 | struct sk_buff *r_buf = NULL; |
550 | struct sk_buff *abort_buf = NULL; | 548 | struct sk_buff *abort_buf = NULL; |
551 | 549 | ||
552 | msg_dbg(msg, "PORT<RECV<:"); | 550 | msg_dbg(msg, "PORT<RECV<:"); |
553 | 551 | ||
554 | if (!p_ptr) { | 552 | if (!p_ptr) { |
555 | err = TIPC_ERR_NO_PORT; | 553 | err = TIPC_ERR_NO_PORT; |
556 | } else if (p_ptr->publ.connected) { | 554 | } else if (p_ptr->publ.connected) { |
557 | if ((port_peernode(p_ptr) != msg_orignode(msg)) || | 555 | if ((port_peernode(p_ptr) != msg_orignode(msg)) || |
558 | (port_peerport(p_ptr) != msg_origport(msg))) { | 556 | (port_peerport(p_ptr) != msg_origport(msg))) { |
559 | err = TIPC_ERR_NO_PORT; | 557 | err = TIPC_ERR_NO_PORT; |
560 | } else if (msg_type(msg) == CONN_ACK) { | 558 | } else if (msg_type(msg) == CONN_ACK) { |
561 | int wakeup = tipc_port_congested(p_ptr) && | 559 | int wakeup = tipc_port_congested(p_ptr) && |
562 | p_ptr->publ.congested && | 560 | p_ptr->publ.congested && |
563 | p_ptr->wakeup; | 561 | p_ptr->wakeup; |
564 | p_ptr->acked += msg_msgcnt(msg); | 562 | p_ptr->acked += msg_msgcnt(msg); |
565 | if (tipc_port_congested(p_ptr)) | 563 | if (tipc_port_congested(p_ptr)) |
566 | goto exit; | 564 | goto exit; |
567 | p_ptr->publ.congested = 0; | 565 | p_ptr->publ.congested = 0; |
568 | if (!wakeup) | 566 | if (!wakeup) |
569 | goto exit; | 567 | goto exit; |
570 | p_ptr->wakeup(&p_ptr->publ); | 568 | p_ptr->wakeup(&p_ptr->publ); |
571 | goto exit; | 569 | goto exit; |
572 | } | 570 | } |
573 | } else if (p_ptr->publ.published) { | 571 | } else if (p_ptr->publ.published) { |
574 | err = TIPC_ERR_NO_PORT; | 572 | err = TIPC_ERR_NO_PORT; |
575 | } | 573 | } |
576 | if (err) { | 574 | if (err) { |
577 | r_buf = port_build_proto_msg(msg_origport(msg), | 575 | r_buf = port_build_proto_msg(msg_origport(msg), |
578 | msg_orignode(msg), | 576 | msg_orignode(msg), |
579 | msg_destport(msg), | 577 | msg_destport(msg), |
580 | tipc_own_addr, | 578 | tipc_own_addr, |
581 | TIPC_HIGH_IMPORTANCE, | 579 | TIPC_HIGH_IMPORTANCE, |
582 | TIPC_CONN_MSG, | 580 | TIPC_CONN_MSG, |
583 | err, | 581 | err, |
584 | 0, | 582 | 0, |
585 | 0); | 583 | 0); |
586 | goto exit; | 584 | goto exit; |
587 | } | 585 | } |
588 | 586 | ||
589 | /* All is fine */ | 587 | /* All is fine */ |
590 | if (msg_type(msg) == CONN_PROBE) { | 588 | if (msg_type(msg) == CONN_PROBE) { |
591 | r_buf = port_build_proto_msg(msg_origport(msg), | 589 | r_buf = port_build_proto_msg(msg_origport(msg), |
592 | msg_orignode(msg), | 590 | msg_orignode(msg), |
593 | msg_destport(msg), | 591 | msg_destport(msg), |
594 | tipc_own_addr, | 592 | tipc_own_addr, |
595 | CONN_MANAGER, | 593 | CONN_MANAGER, |
596 | CONN_PROBE_REPLY, | 594 | CONN_PROBE_REPLY, |
597 | TIPC_OK, | 595 | TIPC_OK, |
598 | port_out_seqno(p_ptr), | 596 | port_out_seqno(p_ptr), |
599 | 0); | 597 | 0); |
600 | } | 598 | } |
601 | p_ptr->probing_state = CONFIRMED; | 599 | p_ptr->probing_state = CONFIRMED; |
602 | port_incr_out_seqno(p_ptr); | 600 | port_incr_out_seqno(p_ptr); |
603 | exit: | 601 | exit: |
604 | if (p_ptr) | 602 | if (p_ptr) |
605 | tipc_port_unlock(p_ptr); | 603 | tipc_port_unlock(p_ptr); |
606 | tipc_net_route_msg(r_buf); | 604 | tipc_net_route_msg(r_buf); |
607 | tipc_net_route_msg(abort_buf); | 605 | tipc_net_route_msg(abort_buf); |
608 | buf_discard(buf); | 606 | buf_discard(buf); |
609 | } | 607 | } |
610 | 608 | ||
611 | static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id) | 609 | static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id) |
612 | { | 610 | { |
613 | struct publication *publ; | 611 | struct publication *publ; |
614 | 612 | ||
615 | if (full_id) | 613 | if (full_id) |
616 | tipc_printf(buf, "<%u.%u.%u:%u>:", | 614 | tipc_printf(buf, "<%u.%u.%u:%u>:", |
617 | tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), | 615 | tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), |
618 | tipc_node(tipc_own_addr), p_ptr->publ.ref); | 616 | tipc_node(tipc_own_addr), p_ptr->publ.ref); |
619 | else | 617 | else |
620 | tipc_printf(buf, "%-10u:", p_ptr->publ.ref); | 618 | tipc_printf(buf, "%-10u:", p_ptr->publ.ref); |
621 | 619 | ||
622 | if (p_ptr->publ.connected) { | 620 | if (p_ptr->publ.connected) { |
623 | u32 dport = port_peerport(p_ptr); | 621 | u32 dport = port_peerport(p_ptr); |
624 | u32 destnode = port_peernode(p_ptr); | 622 | u32 destnode = port_peernode(p_ptr); |
625 | 623 | ||
626 | tipc_printf(buf, " connected to <%u.%u.%u:%u>", | 624 | tipc_printf(buf, " connected to <%u.%u.%u:%u>", |
627 | tipc_zone(destnode), tipc_cluster(destnode), | 625 | tipc_zone(destnode), tipc_cluster(destnode), |
628 | tipc_node(destnode), dport); | 626 | tipc_node(destnode), dport); |
629 | if (p_ptr->publ.conn_type != 0) | 627 | if (p_ptr->publ.conn_type != 0) |
630 | tipc_printf(buf, " via {%u,%u}", | 628 | tipc_printf(buf, " via {%u,%u}", |
631 | p_ptr->publ.conn_type, | 629 | p_ptr->publ.conn_type, |
632 | p_ptr->publ.conn_instance); | 630 | p_ptr->publ.conn_instance); |
633 | } | 631 | } |
634 | else if (p_ptr->publ.published) { | 632 | else if (p_ptr->publ.published) { |
635 | tipc_printf(buf, " bound to"); | 633 | tipc_printf(buf, " bound to"); |
636 | list_for_each_entry(publ, &p_ptr->publications, pport_list) { | 634 | list_for_each_entry(publ, &p_ptr->publications, pport_list) { |
637 | if (publ->lower == publ->upper) | 635 | if (publ->lower == publ->upper) |
638 | tipc_printf(buf, " {%u,%u}", publ->type, | 636 | tipc_printf(buf, " {%u,%u}", publ->type, |
639 | publ->lower); | 637 | publ->lower); |
640 | else | 638 | else |
641 | tipc_printf(buf, " {%u,%u,%u}", publ->type, | 639 | tipc_printf(buf, " {%u,%u,%u}", publ->type, |
642 | publ->lower, publ->upper); | 640 | publ->lower, publ->upper); |
643 | } | 641 | } |
644 | } | 642 | } |
645 | tipc_printf(buf, "\n"); | 643 | tipc_printf(buf, "\n"); |
646 | } | 644 | } |
647 | 645 | ||
648 | #define MAX_PORT_QUERY 32768 | 646 | #define MAX_PORT_QUERY 32768 |
649 | 647 | ||
650 | struct sk_buff *tipc_port_get_ports(void) | 648 | struct sk_buff *tipc_port_get_ports(void) |
651 | { | 649 | { |
652 | struct sk_buff *buf; | 650 | struct sk_buff *buf; |
653 | struct tlv_desc *rep_tlv; | 651 | struct tlv_desc *rep_tlv; |
654 | struct print_buf pb; | 652 | struct print_buf pb; |
655 | struct port *p_ptr; | 653 | struct port *p_ptr; |
656 | int str_len; | 654 | int str_len; |
657 | 655 | ||
658 | buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); | 656 | buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); |
659 | if (!buf) | 657 | if (!buf) |
660 | return NULL; | 658 | return NULL; |
661 | rep_tlv = (struct tlv_desc *)buf->data; | 659 | rep_tlv = (struct tlv_desc *)buf->data; |
662 | 660 | ||
663 | tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY); | 661 | tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY); |
664 | spin_lock_bh(&tipc_port_list_lock); | 662 | spin_lock_bh(&tipc_port_list_lock); |
665 | list_for_each_entry(p_ptr, &ports, port_list) { | 663 | list_for_each_entry(p_ptr, &ports, port_list) { |
666 | spin_lock_bh(p_ptr->publ.lock); | 664 | spin_lock_bh(p_ptr->publ.lock); |
667 | port_print(p_ptr, &pb, 0); | 665 | port_print(p_ptr, &pb, 0); |
668 | spin_unlock_bh(p_ptr->publ.lock); | 666 | spin_unlock_bh(p_ptr->publ.lock); |
669 | } | 667 | } |
670 | spin_unlock_bh(&tipc_port_list_lock); | 668 | spin_unlock_bh(&tipc_port_list_lock); |
671 | str_len = tipc_printbuf_validate(&pb); | 669 | str_len = tipc_printbuf_validate(&pb); |
672 | 670 | ||
673 | skb_put(buf, TLV_SPACE(str_len)); | 671 | skb_put(buf, TLV_SPACE(str_len)); |
674 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | 672 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); |
675 | 673 | ||
676 | return buf; | 674 | return buf; |
677 | } | 675 | } |
678 | 676 | ||
679 | void tipc_port_reinit(void) | 677 | void tipc_port_reinit(void) |
680 | { | 678 | { |
681 | struct port *p_ptr; | 679 | struct port *p_ptr; |
682 | struct tipc_msg *msg; | 680 | struct tipc_msg *msg; |
683 | 681 | ||
684 | spin_lock_bh(&tipc_port_list_lock); | 682 | spin_lock_bh(&tipc_port_list_lock); |
685 | list_for_each_entry(p_ptr, &ports, port_list) { | 683 | list_for_each_entry(p_ptr, &ports, port_list) { |
686 | msg = &p_ptr->publ.phdr; | 684 | msg = &p_ptr->publ.phdr; |
687 | if (msg_orignode(msg) == tipc_own_addr) | 685 | if (msg_orignode(msg) == tipc_own_addr) |
688 | break; | 686 | break; |
689 | msg_set_prevnode(msg, tipc_own_addr); | 687 | msg_set_prevnode(msg, tipc_own_addr); |
690 | msg_set_orignode(msg, tipc_own_addr); | 688 | msg_set_orignode(msg, tipc_own_addr); |
691 | } | 689 | } |
692 | spin_unlock_bh(&tipc_port_list_lock); | 690 | spin_unlock_bh(&tipc_port_list_lock); |
693 | } | 691 | } |
694 | 692 | ||
695 | 693 | ||
696 | /* | 694 | /* |
697 | * port_dispatcher_sigh(): Signal handler for messages destinated | 695 | * port_dispatcher_sigh(): Signal handler for messages destinated |
698 | * to the tipc_port interface. | 696 | * to the tipc_port interface. |
699 | */ | 697 | */ |
700 | 698 | ||
701 | static void port_dispatcher_sigh(void *dummy) | 699 | static void port_dispatcher_sigh(void *dummy) |
702 | { | 700 | { |
703 | struct sk_buff *buf; | 701 | struct sk_buff *buf; |
704 | 702 | ||
705 | spin_lock_bh(&queue_lock); | 703 | spin_lock_bh(&queue_lock); |
706 | buf = msg_queue_head; | 704 | buf = msg_queue_head; |
707 | msg_queue_head = NULL; | 705 | msg_queue_head = NULL; |
708 | spin_unlock_bh(&queue_lock); | 706 | spin_unlock_bh(&queue_lock); |
709 | 707 | ||
710 | while (buf) { | 708 | while (buf) { |
711 | struct port *p_ptr; | 709 | struct port *p_ptr; |
712 | struct user_port *up_ptr; | 710 | struct user_port *up_ptr; |
713 | struct tipc_portid orig; | 711 | struct tipc_portid orig; |
714 | struct tipc_name_seq dseq; | 712 | struct tipc_name_seq dseq; |
715 | void *usr_handle; | 713 | void *usr_handle; |
716 | int connected; | 714 | int connected; |
717 | int published; | 715 | int published; |
718 | u32 message_type; | 716 | u32 message_type; |
719 | 717 | ||
720 | struct sk_buff *next = buf->next; | 718 | struct sk_buff *next = buf->next; |
721 | struct tipc_msg *msg = buf_msg(buf); | 719 | struct tipc_msg *msg = buf_msg(buf); |
722 | u32 dref = msg_destport(msg); | 720 | u32 dref = msg_destport(msg); |
723 | 721 | ||
724 | message_type = msg_type(msg); | 722 | message_type = msg_type(msg); |
725 | if (message_type > TIPC_DIRECT_MSG) | 723 | if (message_type > TIPC_DIRECT_MSG) |
726 | goto reject; /* Unsupported message type */ | 724 | goto reject; /* Unsupported message type */ |
727 | 725 | ||
728 | p_ptr = tipc_port_lock(dref); | 726 | p_ptr = tipc_port_lock(dref); |
729 | if (!p_ptr) | 727 | if (!p_ptr) |
730 | goto reject; /* Port deleted while msg in queue */ | 728 | goto reject; /* Port deleted while msg in queue */ |
731 | 729 | ||
732 | orig.ref = msg_origport(msg); | 730 | orig.ref = msg_origport(msg); |
733 | orig.node = msg_orignode(msg); | 731 | orig.node = msg_orignode(msg); |
734 | up_ptr = p_ptr->user_port; | 732 | up_ptr = p_ptr->user_port; |
735 | usr_handle = up_ptr->usr_handle; | 733 | usr_handle = up_ptr->usr_handle; |
736 | connected = p_ptr->publ.connected; | 734 | connected = p_ptr->publ.connected; |
737 | published = p_ptr->publ.published; | 735 | published = p_ptr->publ.published; |
738 | 736 | ||
739 | if (unlikely(msg_errcode(msg))) | 737 | if (unlikely(msg_errcode(msg))) |
740 | goto err; | 738 | goto err; |
741 | 739 | ||
742 | switch (message_type) { | 740 | switch (message_type) { |
743 | 741 | ||
744 | case TIPC_CONN_MSG:{ | 742 | case TIPC_CONN_MSG:{ |
745 | tipc_conn_msg_event cb = up_ptr->conn_msg_cb; | 743 | tipc_conn_msg_event cb = up_ptr->conn_msg_cb; |
746 | u32 peer_port = port_peerport(p_ptr); | 744 | u32 peer_port = port_peerport(p_ptr); |
747 | u32 peer_node = port_peernode(p_ptr); | 745 | u32 peer_node = port_peernode(p_ptr); |
748 | 746 | ||
749 | tipc_port_unlock(p_ptr); | 747 | tipc_port_unlock(p_ptr); |
750 | if (unlikely(!cb)) | 748 | if (unlikely(!cb)) |
751 | goto reject; | 749 | goto reject; |
752 | if (unlikely(!connected)) { | 750 | if (unlikely(!connected)) { |
753 | if (tipc_connect2port(dref, &orig)) | 751 | if (tipc_connect2port(dref, &orig)) |
754 | goto reject; | 752 | goto reject; |
755 | } else if ((msg_origport(msg) != peer_port) || | 753 | } else if ((msg_origport(msg) != peer_port) || |
756 | (msg_orignode(msg) != peer_node)) | 754 | (msg_orignode(msg) != peer_node)) |
757 | goto reject; | 755 | goto reject; |
758 | if (unlikely(++p_ptr->publ.conn_unacked >= | 756 | if (unlikely(++p_ptr->publ.conn_unacked >= |
759 | TIPC_FLOW_CONTROL_WIN)) | 757 | TIPC_FLOW_CONTROL_WIN)) |
760 | tipc_acknowledge(dref, | 758 | tipc_acknowledge(dref, |
761 | p_ptr->publ.conn_unacked); | 759 | p_ptr->publ.conn_unacked); |
762 | skb_pull(buf, msg_hdr_sz(msg)); | 760 | skb_pull(buf, msg_hdr_sz(msg)); |
763 | cb(usr_handle, dref, &buf, msg_data(msg), | 761 | cb(usr_handle, dref, &buf, msg_data(msg), |
764 | msg_data_sz(msg)); | 762 | msg_data_sz(msg)); |
765 | break; | 763 | break; |
766 | } | 764 | } |
767 | case TIPC_DIRECT_MSG:{ | 765 | case TIPC_DIRECT_MSG:{ |
768 | tipc_msg_event cb = up_ptr->msg_cb; | 766 | tipc_msg_event cb = up_ptr->msg_cb; |
769 | 767 | ||
770 | tipc_port_unlock(p_ptr); | 768 | tipc_port_unlock(p_ptr); |
771 | if (unlikely(!cb || connected)) | 769 | if (unlikely(!cb || connected)) |
772 | goto reject; | 770 | goto reject; |
773 | skb_pull(buf, msg_hdr_sz(msg)); | 771 | skb_pull(buf, msg_hdr_sz(msg)); |
774 | cb(usr_handle, dref, &buf, msg_data(msg), | 772 | cb(usr_handle, dref, &buf, msg_data(msg), |
775 | msg_data_sz(msg), msg_importance(msg), | 773 | msg_data_sz(msg), msg_importance(msg), |
776 | &orig); | 774 | &orig); |
777 | break; | 775 | break; |
778 | } | 776 | } |
779 | case TIPC_MCAST_MSG: | 777 | case TIPC_MCAST_MSG: |
780 | case TIPC_NAMED_MSG:{ | 778 | case TIPC_NAMED_MSG:{ |
781 | tipc_named_msg_event cb = up_ptr->named_msg_cb; | 779 | tipc_named_msg_event cb = up_ptr->named_msg_cb; |
782 | 780 | ||
783 | tipc_port_unlock(p_ptr); | 781 | tipc_port_unlock(p_ptr); |
784 | if (unlikely(!cb || connected || !published)) | 782 | if (unlikely(!cb || connected || !published)) |
785 | goto reject; | 783 | goto reject; |
786 | dseq.type = msg_nametype(msg); | 784 | dseq.type = msg_nametype(msg); |
787 | dseq.lower = msg_nameinst(msg); | 785 | dseq.lower = msg_nameinst(msg); |
788 | dseq.upper = (message_type == TIPC_NAMED_MSG) | 786 | dseq.upper = (message_type == TIPC_NAMED_MSG) |
789 | ? dseq.lower : msg_nameupper(msg); | 787 | ? dseq.lower : msg_nameupper(msg); |
790 | skb_pull(buf, msg_hdr_sz(msg)); | 788 | skb_pull(buf, msg_hdr_sz(msg)); |
791 | cb(usr_handle, dref, &buf, msg_data(msg), | 789 | cb(usr_handle, dref, &buf, msg_data(msg), |
792 | msg_data_sz(msg), msg_importance(msg), | 790 | msg_data_sz(msg), msg_importance(msg), |
793 | &orig, &dseq); | 791 | &orig, &dseq); |
794 | break; | 792 | break; |
795 | } | 793 | } |
796 | } | 794 | } |
797 | if (buf) | 795 | if (buf) |
798 | buf_discard(buf); | 796 | buf_discard(buf); |
799 | buf = next; | 797 | buf = next; |
800 | continue; | 798 | continue; |
801 | err: | 799 | err: |
802 | switch (message_type) { | 800 | switch (message_type) { |
803 | 801 | ||
804 | case TIPC_CONN_MSG:{ | 802 | case TIPC_CONN_MSG:{ |
805 | tipc_conn_shutdown_event cb = | 803 | tipc_conn_shutdown_event cb = |
806 | up_ptr->conn_err_cb; | 804 | up_ptr->conn_err_cb; |
807 | u32 peer_port = port_peerport(p_ptr); | 805 | u32 peer_port = port_peerport(p_ptr); |
808 | u32 peer_node = port_peernode(p_ptr); | 806 | u32 peer_node = port_peernode(p_ptr); |
809 | 807 | ||
810 | tipc_port_unlock(p_ptr); | 808 | tipc_port_unlock(p_ptr); |
811 | if (!cb || !connected) | 809 | if (!cb || !connected) |
812 | break; | 810 | break; |
813 | if ((msg_origport(msg) != peer_port) || | 811 | if ((msg_origport(msg) != peer_port) || |
814 | (msg_orignode(msg) != peer_node)) | 812 | (msg_orignode(msg) != peer_node)) |
815 | break; | 813 | break; |
816 | tipc_disconnect(dref); | 814 | tipc_disconnect(dref); |
817 | skb_pull(buf, msg_hdr_sz(msg)); | 815 | skb_pull(buf, msg_hdr_sz(msg)); |
818 | cb(usr_handle, dref, &buf, msg_data(msg), | 816 | cb(usr_handle, dref, &buf, msg_data(msg), |
819 | msg_data_sz(msg), msg_errcode(msg)); | 817 | msg_data_sz(msg), msg_errcode(msg)); |
820 | break; | 818 | break; |
821 | } | 819 | } |
822 | case TIPC_DIRECT_MSG:{ | 820 | case TIPC_DIRECT_MSG:{ |
823 | tipc_msg_err_event cb = up_ptr->err_cb; | 821 | tipc_msg_err_event cb = up_ptr->err_cb; |
824 | 822 | ||
825 | tipc_port_unlock(p_ptr); | 823 | tipc_port_unlock(p_ptr); |
826 | if (!cb || connected) | 824 | if (!cb || connected) |
827 | break; | 825 | break; |
828 | skb_pull(buf, msg_hdr_sz(msg)); | 826 | skb_pull(buf, msg_hdr_sz(msg)); |
829 | cb(usr_handle, dref, &buf, msg_data(msg), | 827 | cb(usr_handle, dref, &buf, msg_data(msg), |
830 | msg_data_sz(msg), msg_errcode(msg), &orig); | 828 | msg_data_sz(msg), msg_errcode(msg), &orig); |
831 | break; | 829 | break; |
832 | } | 830 | } |
833 | case TIPC_MCAST_MSG: | 831 | case TIPC_MCAST_MSG: |
834 | case TIPC_NAMED_MSG:{ | 832 | case TIPC_NAMED_MSG:{ |
835 | tipc_named_msg_err_event cb = | 833 | tipc_named_msg_err_event cb = |
836 | up_ptr->named_err_cb; | 834 | up_ptr->named_err_cb; |
837 | 835 | ||
838 | tipc_port_unlock(p_ptr); | 836 | tipc_port_unlock(p_ptr); |
839 | if (!cb || connected) | 837 | if (!cb || connected) |
840 | break; | 838 | break; |
841 | dseq.type = msg_nametype(msg); | 839 | dseq.type = msg_nametype(msg); |
842 | dseq.lower = msg_nameinst(msg); | 840 | dseq.lower = msg_nameinst(msg); |
843 | dseq.upper = (message_type == TIPC_NAMED_MSG) | 841 | dseq.upper = (message_type == TIPC_NAMED_MSG) |
844 | ? dseq.lower : msg_nameupper(msg); | 842 | ? dseq.lower : msg_nameupper(msg); |
845 | skb_pull(buf, msg_hdr_sz(msg)); | 843 | skb_pull(buf, msg_hdr_sz(msg)); |
846 | cb(usr_handle, dref, &buf, msg_data(msg), | 844 | cb(usr_handle, dref, &buf, msg_data(msg), |
847 | msg_data_sz(msg), msg_errcode(msg), &dseq); | 845 | msg_data_sz(msg), msg_errcode(msg), &dseq); |
848 | break; | 846 | break; |
849 | } | 847 | } |
850 | } | 848 | } |
851 | if (buf) | 849 | if (buf) |
852 | buf_discard(buf); | 850 | buf_discard(buf); |
853 | buf = next; | 851 | buf = next; |
854 | continue; | 852 | continue; |
855 | reject: | 853 | reject: |
856 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | 854 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); |
857 | buf = next; | 855 | buf = next; |
858 | } | 856 | } |
859 | } | 857 | } |
860 | 858 | ||
861 | /* | 859 | /* |
862 | * port_dispatcher(): Dispatcher for messages destinated | 860 | * port_dispatcher(): Dispatcher for messages destinated |
863 | * to the tipc_port interface. Called with port locked. | 861 | * to the tipc_port interface. Called with port locked. |
864 | */ | 862 | */ |
865 | 863 | ||
866 | static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf) | 864 | static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf) |
867 | { | 865 | { |
868 | buf->next = NULL; | 866 | buf->next = NULL; |
869 | spin_lock_bh(&queue_lock); | 867 | spin_lock_bh(&queue_lock); |
870 | if (msg_queue_head) { | 868 | if (msg_queue_head) { |
871 | msg_queue_tail->next = buf; | 869 | msg_queue_tail->next = buf; |
872 | msg_queue_tail = buf; | 870 | msg_queue_tail = buf; |
873 | } else { | 871 | } else { |
874 | msg_queue_tail = msg_queue_head = buf; | 872 | msg_queue_tail = msg_queue_head = buf; |
875 | tipc_k_signal((Handler)port_dispatcher_sigh, 0); | 873 | tipc_k_signal((Handler)port_dispatcher_sigh, 0); |
876 | } | 874 | } |
877 | spin_unlock_bh(&queue_lock); | 875 | spin_unlock_bh(&queue_lock); |
878 | return 0; | 876 | return 0; |
879 | } | 877 | } |
880 | 878 | ||
881 | /* | 879 | /* |
882 | * Wake up port after congestion: Called with port locked, | 880 | * Wake up port after congestion: Called with port locked, |
883 | * | 881 | * |
884 | */ | 882 | */ |
885 | 883 | ||
886 | static void port_wakeup_sh(unsigned long ref) | 884 | static void port_wakeup_sh(unsigned long ref) |
887 | { | 885 | { |
888 | struct port *p_ptr; | 886 | struct port *p_ptr; |
889 | struct user_port *up_ptr; | 887 | struct user_port *up_ptr; |
890 | tipc_continue_event cb = NULL; | 888 | tipc_continue_event cb = NULL; |
891 | void *uh = NULL; | 889 | void *uh = NULL; |
892 | 890 | ||
893 | p_ptr = tipc_port_lock(ref); | 891 | p_ptr = tipc_port_lock(ref); |
894 | if (p_ptr) { | 892 | if (p_ptr) { |
895 | up_ptr = p_ptr->user_port; | 893 | up_ptr = p_ptr->user_port; |
896 | if (up_ptr) { | 894 | if (up_ptr) { |
897 | cb = up_ptr->continue_event_cb; | 895 | cb = up_ptr->continue_event_cb; |
898 | uh = up_ptr->usr_handle; | 896 | uh = up_ptr->usr_handle; |
899 | } | 897 | } |
900 | tipc_port_unlock(p_ptr); | 898 | tipc_port_unlock(p_ptr); |
901 | } | 899 | } |
902 | if (cb) | 900 | if (cb) |
903 | cb(uh, ref); | 901 | cb(uh, ref); |
904 | } | 902 | } |
905 | 903 | ||
906 | 904 | ||
907 | static void port_wakeup(struct tipc_port *p_ptr) | 905 | static void port_wakeup(struct tipc_port *p_ptr) |
908 | { | 906 | { |
909 | tipc_k_signal((Handler)port_wakeup_sh, p_ptr->ref); | 907 | tipc_k_signal((Handler)port_wakeup_sh, p_ptr->ref); |
910 | } | 908 | } |
911 | 909 | ||
912 | void tipc_acknowledge(u32 ref, u32 ack) | 910 | void tipc_acknowledge(u32 ref, u32 ack) |
913 | { | 911 | { |
914 | struct port *p_ptr; | 912 | struct port *p_ptr; |
915 | struct sk_buff *buf = NULL; | 913 | struct sk_buff *buf = NULL; |
916 | 914 | ||
917 | p_ptr = tipc_port_lock(ref); | 915 | p_ptr = tipc_port_lock(ref); |
918 | if (!p_ptr) | 916 | if (!p_ptr) |
919 | return; | 917 | return; |
920 | if (p_ptr->publ.connected) { | 918 | if (p_ptr->publ.connected) { |
921 | p_ptr->publ.conn_unacked -= ack; | 919 | p_ptr->publ.conn_unacked -= ack; |
922 | buf = port_build_proto_msg(port_peerport(p_ptr), | 920 | buf = port_build_proto_msg(port_peerport(p_ptr), |
923 | port_peernode(p_ptr), | 921 | port_peernode(p_ptr), |
924 | ref, | 922 | ref, |
925 | tipc_own_addr, | 923 | tipc_own_addr, |
926 | CONN_MANAGER, | 924 | CONN_MANAGER, |
927 | CONN_ACK, | 925 | CONN_ACK, |
928 | TIPC_OK, | 926 | TIPC_OK, |
929 | port_out_seqno(p_ptr), | 927 | port_out_seqno(p_ptr), |
930 | ack); | 928 | ack); |
931 | } | 929 | } |
932 | tipc_port_unlock(p_ptr); | 930 | tipc_port_unlock(p_ptr); |
933 | tipc_net_route_msg(buf); | 931 | tipc_net_route_msg(buf); |
934 | } | 932 | } |
935 | 933 | ||
936 | /* | 934 | /* |
937 | * tipc_createport(): user level call. Will add port to | 935 | * tipc_createport(): user level call. |
938 | * registry if non-zero user_ref. | ||
939 | */ | 936 | */ |
940 | 937 | ||
941 | int tipc_createport(u32 user_ref, | 938 | int tipc_createport(void *usr_handle, |
942 | void *usr_handle, | ||
943 | unsigned int importance, | 939 | unsigned int importance, |
944 | tipc_msg_err_event error_cb, | 940 | tipc_msg_err_event error_cb, |
945 | tipc_named_msg_err_event named_error_cb, | 941 | tipc_named_msg_err_event named_error_cb, |
946 | tipc_conn_shutdown_event conn_error_cb, | 942 | tipc_conn_shutdown_event conn_error_cb, |
947 | tipc_msg_event msg_cb, | 943 | tipc_msg_event msg_cb, |
948 | tipc_named_msg_event named_msg_cb, | 944 | tipc_named_msg_event named_msg_cb, |
949 | tipc_conn_msg_event conn_msg_cb, | 945 | tipc_conn_msg_event conn_msg_cb, |
950 | tipc_continue_event continue_event_cb,/* May be zero */ | 946 | tipc_continue_event continue_event_cb,/* May be zero */ |
951 | u32 *portref) | 947 | u32 *portref) |
952 | { | 948 | { |
953 | struct user_port *up_ptr; | 949 | struct user_port *up_ptr; |
954 | struct port *p_ptr; | 950 | struct port *p_ptr; |
955 | 951 | ||
956 | up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC); | 952 | up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC); |
957 | if (!up_ptr) { | 953 | if (!up_ptr) { |
958 | warn("Port creation failed, no memory\n"); | 954 | warn("Port creation failed, no memory\n"); |
959 | return -ENOMEM; | 955 | return -ENOMEM; |
960 | } | 956 | } |
961 | p_ptr = (struct port *)tipc_createport_raw(NULL, port_dispatcher, | 957 | p_ptr = (struct port *)tipc_createport_raw(NULL, port_dispatcher, |
962 | port_wakeup, importance); | 958 | port_wakeup, importance); |
963 | if (!p_ptr) { | 959 | if (!p_ptr) { |
964 | kfree(up_ptr); | 960 | kfree(up_ptr); |
965 | return -ENOMEM; | 961 | return -ENOMEM; |
966 | } | 962 | } |
967 | 963 | ||
968 | p_ptr->user_port = up_ptr; | 964 | p_ptr->user_port = up_ptr; |
969 | up_ptr->user_ref = user_ref; | ||
970 | up_ptr->usr_handle = usr_handle; | 965 | up_ptr->usr_handle = usr_handle; |
971 | up_ptr->ref = p_ptr->publ.ref; | 966 | up_ptr->ref = p_ptr->publ.ref; |
972 | up_ptr->err_cb = error_cb; | 967 | up_ptr->err_cb = error_cb; |
973 | up_ptr->named_err_cb = named_error_cb; | 968 | up_ptr->named_err_cb = named_error_cb; |
974 | up_ptr->conn_err_cb = conn_error_cb; | 969 | up_ptr->conn_err_cb = conn_error_cb; |
975 | up_ptr->msg_cb = msg_cb; | 970 | up_ptr->msg_cb = msg_cb; |
976 | up_ptr->named_msg_cb = named_msg_cb; | 971 | up_ptr->named_msg_cb = named_msg_cb; |
977 | up_ptr->conn_msg_cb = conn_msg_cb; | 972 | up_ptr->conn_msg_cb = conn_msg_cb; |
978 | up_ptr->continue_event_cb = continue_event_cb; | 973 | up_ptr->continue_event_cb = continue_event_cb; |
979 | INIT_LIST_HEAD(&up_ptr->uport_list); | ||
980 | tipc_reg_add_port(up_ptr); | ||
981 | *portref = p_ptr->publ.ref; | 974 | *portref = p_ptr->publ.ref; |
982 | tipc_port_unlock(p_ptr); | 975 | tipc_port_unlock(p_ptr); |
983 | return 0; | 976 | return 0; |
984 | } | 977 | } |
985 | 978 | ||
986 | int tipc_portimportance(u32 ref, unsigned int *importance) | 979 | int tipc_portimportance(u32 ref, unsigned int *importance) |
987 | { | 980 | { |
988 | struct port *p_ptr; | 981 | struct port *p_ptr; |
989 | 982 | ||
990 | p_ptr = tipc_port_lock(ref); | 983 | p_ptr = tipc_port_lock(ref); |
991 | if (!p_ptr) | 984 | if (!p_ptr) |
992 | return -EINVAL; | 985 | return -EINVAL; |
993 | *importance = (unsigned int)msg_importance(&p_ptr->publ.phdr); | 986 | *importance = (unsigned int)msg_importance(&p_ptr->publ.phdr); |
994 | tipc_port_unlock(p_ptr); | 987 | tipc_port_unlock(p_ptr); |
995 | return 0; | 988 | return 0; |
996 | } | 989 | } |
997 | 990 | ||
998 | int tipc_set_portimportance(u32 ref, unsigned int imp) | 991 | int tipc_set_portimportance(u32 ref, unsigned int imp) |
999 | { | 992 | { |
1000 | struct port *p_ptr; | 993 | struct port *p_ptr; |
1001 | 994 | ||
1002 | if (imp > TIPC_CRITICAL_IMPORTANCE) | 995 | if (imp > TIPC_CRITICAL_IMPORTANCE) |
1003 | return -EINVAL; | 996 | return -EINVAL; |
1004 | 997 | ||
1005 | p_ptr = tipc_port_lock(ref); | 998 | p_ptr = tipc_port_lock(ref); |
1006 | if (!p_ptr) | 999 | if (!p_ptr) |
1007 | return -EINVAL; | 1000 | return -EINVAL; |
1008 | msg_set_importance(&p_ptr->publ.phdr, (u32)imp); | 1001 | msg_set_importance(&p_ptr->publ.phdr, (u32)imp); |
1009 | tipc_port_unlock(p_ptr); | 1002 | tipc_port_unlock(p_ptr); |
1010 | return 0; | 1003 | return 0; |
1011 | } | 1004 | } |
1012 | 1005 | ||
1013 | 1006 | ||
1014 | int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) | 1007 | int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) |
1015 | { | 1008 | { |
1016 | struct port *p_ptr; | 1009 | struct port *p_ptr; |
1017 | struct publication *publ; | 1010 | struct publication *publ; |
1018 | u32 key; | 1011 | u32 key; |
1019 | int res = -EINVAL; | 1012 | int res = -EINVAL; |
1020 | 1013 | ||
1021 | p_ptr = tipc_port_lock(ref); | 1014 | p_ptr = tipc_port_lock(ref); |
1022 | if (!p_ptr) | 1015 | if (!p_ptr) |
1023 | return -EINVAL; | 1016 | return -EINVAL; |
1024 | 1017 | ||
1025 | dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, " | 1018 | dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, " |
1026 | "lower = %u, upper = %u\n", | 1019 | "lower = %u, upper = %u\n", |
1027 | ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper); | 1020 | ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper); |
1028 | if (p_ptr->publ.connected) | 1021 | if (p_ptr->publ.connected) |
1029 | goto exit; | 1022 | goto exit; |
1030 | if (seq->lower > seq->upper) | 1023 | if (seq->lower > seq->upper) |
1031 | goto exit; | 1024 | goto exit; |
1032 | if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE)) | 1025 | if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE)) |
1033 | goto exit; | 1026 | goto exit; |
1034 | key = ref + p_ptr->pub_count + 1; | 1027 | key = ref + p_ptr->pub_count + 1; |
1035 | if (key == ref) { | 1028 | if (key == ref) { |
1036 | res = -EADDRINUSE; | 1029 | res = -EADDRINUSE; |
1037 | goto exit; | 1030 | goto exit; |
1038 | } | 1031 | } |
1039 | publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper, | 1032 | publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper, |
1040 | scope, p_ptr->publ.ref, key); | 1033 | scope, p_ptr->publ.ref, key); |
1041 | if (publ) { | 1034 | if (publ) { |
1042 | list_add(&publ->pport_list, &p_ptr->publications); | 1035 | list_add(&publ->pport_list, &p_ptr->publications); |
1043 | p_ptr->pub_count++; | 1036 | p_ptr->pub_count++; |
1044 | p_ptr->publ.published = 1; | 1037 | p_ptr->publ.published = 1; |
1045 | res = 0; | 1038 | res = 0; |
1046 | } | 1039 | } |
1047 | exit: | 1040 | exit: |
1048 | tipc_port_unlock(p_ptr); | 1041 | tipc_port_unlock(p_ptr); |
1049 | return res; | 1042 | return res; |
1050 | } | 1043 | } |
1051 | 1044 | ||
1052 | int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) | 1045 | int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) |
1053 | { | 1046 | { |
1054 | struct port *p_ptr; | 1047 | struct port *p_ptr; |
1055 | struct publication *publ; | 1048 | struct publication *publ; |
1056 | struct publication *tpubl; | 1049 | struct publication *tpubl; |
1057 | int res = -EINVAL; | 1050 | int res = -EINVAL; |
1058 | 1051 | ||
1059 | p_ptr = tipc_port_lock(ref); | 1052 | p_ptr = tipc_port_lock(ref); |
1060 | if (!p_ptr) | 1053 | if (!p_ptr) |
1061 | return -EINVAL; | 1054 | return -EINVAL; |
1062 | if (!seq) { | 1055 | if (!seq) { |
1063 | list_for_each_entry_safe(publ, tpubl, | 1056 | list_for_each_entry_safe(publ, tpubl, |
1064 | &p_ptr->publications, pport_list) { | 1057 | &p_ptr->publications, pport_list) { |
1065 | tipc_nametbl_withdraw(publ->type, publ->lower, | 1058 | tipc_nametbl_withdraw(publ->type, publ->lower, |
1066 | publ->ref, publ->key); | 1059 | publ->ref, publ->key); |
1067 | } | 1060 | } |
1068 | res = 0; | 1061 | res = 0; |
1069 | } else { | 1062 | } else { |
1070 | list_for_each_entry_safe(publ, tpubl, | 1063 | list_for_each_entry_safe(publ, tpubl, |
1071 | &p_ptr->publications, pport_list) { | 1064 | &p_ptr->publications, pport_list) { |
1072 | if (publ->scope != scope) | 1065 | if (publ->scope != scope) |
1073 | continue; | 1066 | continue; |
1074 | if (publ->type != seq->type) | 1067 | if (publ->type != seq->type) |
1075 | continue; | 1068 | continue; |
1076 | if (publ->lower != seq->lower) | 1069 | if (publ->lower != seq->lower) |
1077 | continue; | 1070 | continue; |
1078 | if (publ->upper != seq->upper) | 1071 | if (publ->upper != seq->upper) |
1079 | break; | 1072 | break; |
1080 | tipc_nametbl_withdraw(publ->type, publ->lower, | 1073 | tipc_nametbl_withdraw(publ->type, publ->lower, |
1081 | publ->ref, publ->key); | 1074 | publ->ref, publ->key); |
1082 | res = 0; | 1075 | res = 0; |
1083 | break; | 1076 | break; |
1084 | } | 1077 | } |
1085 | } | 1078 | } |
1086 | if (list_empty(&p_ptr->publications)) | 1079 | if (list_empty(&p_ptr->publications)) |
1087 | p_ptr->publ.published = 0; | 1080 | p_ptr->publ.published = 0; |
1088 | tipc_port_unlock(p_ptr); | 1081 | tipc_port_unlock(p_ptr); |
1089 | return res; | 1082 | return res; |
1090 | } | 1083 | } |
1091 | 1084 | ||
1092 | int tipc_connect2port(u32 ref, struct tipc_portid const *peer) | 1085 | int tipc_connect2port(u32 ref, struct tipc_portid const *peer) |
1093 | { | 1086 | { |
1094 | struct port *p_ptr; | 1087 | struct port *p_ptr; |
1095 | struct tipc_msg *msg; | 1088 | struct tipc_msg *msg; |
1096 | int res = -EINVAL; | 1089 | int res = -EINVAL; |
1097 | 1090 | ||
1098 | p_ptr = tipc_port_lock(ref); | 1091 | p_ptr = tipc_port_lock(ref); |
1099 | if (!p_ptr) | 1092 | if (!p_ptr) |
1100 | return -EINVAL; | 1093 | return -EINVAL; |
1101 | if (p_ptr->publ.published || p_ptr->publ.connected) | 1094 | if (p_ptr->publ.published || p_ptr->publ.connected) |
1102 | goto exit; | 1095 | goto exit; |
1103 | if (!peer->ref) | 1096 | if (!peer->ref) |
1104 | goto exit; | 1097 | goto exit; |
1105 | 1098 | ||
1106 | msg = &p_ptr->publ.phdr; | 1099 | msg = &p_ptr->publ.phdr; |
1107 | msg_set_destnode(msg, peer->node); | 1100 | msg_set_destnode(msg, peer->node); |
1108 | msg_set_destport(msg, peer->ref); | 1101 | msg_set_destport(msg, peer->ref); |
1109 | msg_set_orignode(msg, tipc_own_addr); | 1102 | msg_set_orignode(msg, tipc_own_addr); |
1110 | msg_set_origport(msg, p_ptr->publ.ref); | 1103 | msg_set_origport(msg, p_ptr->publ.ref); |
1111 | msg_set_transp_seqno(msg, 42); | 1104 | msg_set_transp_seqno(msg, 42); |
1112 | msg_set_type(msg, TIPC_CONN_MSG); | 1105 | msg_set_type(msg, TIPC_CONN_MSG); |
1113 | msg_set_hdr_sz(msg, SHORT_H_SIZE); | 1106 | msg_set_hdr_sz(msg, SHORT_H_SIZE); |
1114 | 1107 | ||
1115 | p_ptr->probing_interval = PROBING_INTERVAL; | 1108 | p_ptr->probing_interval = PROBING_INTERVAL; |
1116 | p_ptr->probing_state = CONFIRMED; | 1109 | p_ptr->probing_state = CONFIRMED; |
1117 | p_ptr->publ.connected = 1; | 1110 | p_ptr->publ.connected = 1; |
1118 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); | 1111 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); |
1119 | 1112 | ||
1120 | tipc_nodesub_subscribe(&p_ptr->subscription,peer->node, | 1113 | tipc_nodesub_subscribe(&p_ptr->subscription,peer->node, |
1121 | (void *)(unsigned long)ref, | 1114 | (void *)(unsigned long)ref, |
1122 | (net_ev_handler)port_handle_node_down); | 1115 | (net_ev_handler)port_handle_node_down); |
1123 | res = 0; | 1116 | res = 0; |
1124 | exit: | 1117 | exit: |
1125 | tipc_port_unlock(p_ptr); | 1118 | tipc_port_unlock(p_ptr); |
1126 | p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref); | 1119 | p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref); |
1127 | return res; | 1120 | return res; |
1128 | } | 1121 | } |
1129 | 1122 | ||
1130 | /** | 1123 | /** |
1131 | * tipc_disconnect_port - disconnect port from peer | 1124 | * tipc_disconnect_port - disconnect port from peer |
1132 | * | 1125 | * |
1133 | * Port must be locked. | 1126 | * Port must be locked. |
1134 | */ | 1127 | */ |
1135 | 1128 | ||
1136 | int tipc_disconnect_port(struct tipc_port *tp_ptr) | 1129 | int tipc_disconnect_port(struct tipc_port *tp_ptr) |
1137 | { | 1130 | { |
1138 | int res; | 1131 | int res; |
1139 | 1132 | ||
1140 | if (tp_ptr->connected) { | 1133 | if (tp_ptr->connected) { |
1141 | tp_ptr->connected = 0; | 1134 | tp_ptr->connected = 0; |
1142 | /* let timer expire on it's own to avoid deadlock! */ | 1135 | /* let timer expire on it's own to avoid deadlock! */ |
1143 | tipc_nodesub_unsubscribe( | 1136 | tipc_nodesub_unsubscribe( |
1144 | &((struct port *)tp_ptr)->subscription); | 1137 | &((struct port *)tp_ptr)->subscription); |
1145 | res = 0; | 1138 | res = 0; |
1146 | } else { | 1139 | } else { |
1147 | res = -ENOTCONN; | 1140 | res = -ENOTCONN; |
1148 | } | 1141 | } |
1149 | return res; | 1142 | return res; |
1150 | } | 1143 | } |
1151 | 1144 | ||
1152 | /* | 1145 | /* |
1153 | * tipc_disconnect(): Disconnect port form peer. | 1146 | * tipc_disconnect(): Disconnect port form peer. |
1154 | * This is a node local operation. | 1147 | * This is a node local operation. |
1155 | */ | 1148 | */ |
1156 | 1149 | ||
1157 | int tipc_disconnect(u32 ref) | 1150 | int tipc_disconnect(u32 ref) |
1158 | { | 1151 | { |
1159 | struct port *p_ptr; | 1152 | struct port *p_ptr; |
1160 | int res; | 1153 | int res; |
1161 | 1154 | ||
1162 | p_ptr = tipc_port_lock(ref); | 1155 | p_ptr = tipc_port_lock(ref); |
1163 | if (!p_ptr) | 1156 | if (!p_ptr) |
1164 | return -EINVAL; | 1157 | return -EINVAL; |
1165 | res = tipc_disconnect_port((struct tipc_port *)p_ptr); | 1158 | res = tipc_disconnect_port((struct tipc_port *)p_ptr); |
1166 | tipc_port_unlock(p_ptr); | 1159 | tipc_port_unlock(p_ptr); |
1167 | return res; | 1160 | return res; |
1168 | } | 1161 | } |
1169 | 1162 | ||
1170 | /* | 1163 | /* |
1171 | * tipc_shutdown(): Send a SHUTDOWN msg to peer and disconnect | 1164 | * tipc_shutdown(): Send a SHUTDOWN msg to peer and disconnect |
1172 | */ | 1165 | */ |
1173 | int tipc_shutdown(u32 ref) | 1166 | int tipc_shutdown(u32 ref) |
1174 | { | 1167 | { |
1175 | struct port *p_ptr; | 1168 | struct port *p_ptr; |
1176 | struct sk_buff *buf = NULL; | 1169 | struct sk_buff *buf = NULL; |
1177 | 1170 | ||
1178 | p_ptr = tipc_port_lock(ref); | 1171 | p_ptr = tipc_port_lock(ref); |
1179 | if (!p_ptr) | 1172 | if (!p_ptr) |
1180 | return -EINVAL; | 1173 | return -EINVAL; |
1181 | 1174 | ||
1182 | if (p_ptr->publ.connected) { | 1175 | if (p_ptr->publ.connected) { |
1183 | u32 imp = msg_importance(&p_ptr->publ.phdr); | 1176 | u32 imp = msg_importance(&p_ptr->publ.phdr); |
1184 | if (imp < TIPC_CRITICAL_IMPORTANCE) | 1177 | if (imp < TIPC_CRITICAL_IMPORTANCE) |
1185 | imp++; | 1178 | imp++; |
1186 | buf = port_build_proto_msg(port_peerport(p_ptr), | 1179 | buf = port_build_proto_msg(port_peerport(p_ptr), |
1187 | port_peernode(p_ptr), | 1180 | port_peernode(p_ptr), |
1188 | ref, | 1181 | ref, |
1189 | tipc_own_addr, | 1182 | tipc_own_addr, |
1190 | imp, | 1183 | imp, |
1191 | TIPC_CONN_MSG, | 1184 | TIPC_CONN_MSG, |
1192 | TIPC_CONN_SHUTDOWN, | 1185 | TIPC_CONN_SHUTDOWN, |
1193 | port_out_seqno(p_ptr), | 1186 | port_out_seqno(p_ptr), |
1194 | 0); | 1187 | 0); |
1195 | } | 1188 | } |
1196 | tipc_port_unlock(p_ptr); | 1189 | tipc_port_unlock(p_ptr); |
1197 | tipc_net_route_msg(buf); | 1190 | tipc_net_route_msg(buf); |
1198 | return tipc_disconnect(ref); | 1191 | return tipc_disconnect(ref); |
1199 | } | 1192 | } |
1200 | 1193 | ||
1201 | /* | 1194 | /* |
1202 | * tipc_port_recv_sections(): Concatenate and deliver sectioned | 1195 | * tipc_port_recv_sections(): Concatenate and deliver sectioned |
1203 | * message for this node. | 1196 | * message for this node. |
1204 | */ | 1197 | */ |
1205 | 1198 | ||
1206 | static int tipc_port_recv_sections(struct port *sender, unsigned int num_sect, | 1199 | static int tipc_port_recv_sections(struct port *sender, unsigned int num_sect, |
1207 | struct iovec const *msg_sect) | 1200 | struct iovec const *msg_sect) |
1208 | { | 1201 | { |
1209 | struct sk_buff *buf; | 1202 | struct sk_buff *buf; |
1210 | int res; | 1203 | int res; |
1211 | 1204 | ||
1212 | res = tipc_msg_build(&sender->publ.phdr, msg_sect, num_sect, | 1205 | res = tipc_msg_build(&sender->publ.phdr, msg_sect, num_sect, |
1213 | MAX_MSG_SIZE, !sender->user_port, &buf); | 1206 | MAX_MSG_SIZE, !sender->user_port, &buf); |
1214 | if (likely(buf)) | 1207 | if (likely(buf)) |
1215 | tipc_port_recv_msg(buf); | 1208 | tipc_port_recv_msg(buf); |
1216 | return res; | 1209 | return res; |
1217 | } | 1210 | } |
1218 | 1211 | ||
1219 | /** | 1212 | /** |
1220 | * tipc_send - send message sections on connection | 1213 | * tipc_send - send message sections on connection |
1221 | */ | 1214 | */ |
1222 | 1215 | ||
1223 | int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) | 1216 | int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) |
1224 | { | 1217 | { |
1225 | struct port *p_ptr; | 1218 | struct port *p_ptr; |
1226 | u32 destnode; | 1219 | u32 destnode; |
1227 | int res; | 1220 | int res; |
1228 | 1221 | ||
1229 | p_ptr = tipc_port_deref(ref); | 1222 | p_ptr = tipc_port_deref(ref); |
1230 | if (!p_ptr || !p_ptr->publ.connected) | 1223 | if (!p_ptr || !p_ptr->publ.connected) |
1231 | return -EINVAL; | 1224 | return -EINVAL; |
1232 | 1225 | ||
1233 | p_ptr->publ.congested = 1; | 1226 | p_ptr->publ.congested = 1; |
1234 | if (!tipc_port_congested(p_ptr)) { | 1227 | if (!tipc_port_congested(p_ptr)) { |
1235 | destnode = port_peernode(p_ptr); | 1228 | destnode = port_peernode(p_ptr); |
1236 | if (likely(destnode != tipc_own_addr)) | 1229 | if (likely(destnode != tipc_own_addr)) |
1237 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, | 1230 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, |
1238 | destnode); | 1231 | destnode); |
1239 | else | 1232 | else |
1240 | res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect); | 1233 | res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect); |
1241 | 1234 | ||
1242 | if (likely(res != -ELINKCONG)) { | 1235 | if (likely(res != -ELINKCONG)) { |
1243 | port_incr_out_seqno(p_ptr); | 1236 | port_incr_out_seqno(p_ptr); |
1244 | p_ptr->publ.congested = 0; | 1237 | p_ptr->publ.congested = 0; |
1245 | p_ptr->sent++; | 1238 | p_ptr->sent++; |
1246 | return res; | 1239 | return res; |
1247 | } | 1240 | } |
1248 | } | 1241 | } |
1249 | if (port_unreliable(p_ptr)) { | 1242 | if (port_unreliable(p_ptr)) { |
1250 | p_ptr->publ.congested = 0; | 1243 | p_ptr->publ.congested = 0; |
1251 | /* Just calculate msg length and return */ | 1244 | /* Just calculate msg length and return */ |
1252 | return tipc_msg_calc_data_size(msg_sect, num_sect); | 1245 | return tipc_msg_calc_data_size(msg_sect, num_sect); |
1253 | } | 1246 | } |
1254 | return -ELINKCONG; | 1247 | return -ELINKCONG; |
1255 | } | 1248 | } |
1256 | 1249 | ||
1257 | /** | 1250 | /** |
1258 | * tipc_send2name - send message sections to port name | 1251 | * tipc_send2name - send message sections to port name |
1259 | */ | 1252 | */ |
1260 | 1253 | ||
1261 | int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, | 1254 | int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, |
1262 | unsigned int num_sect, struct iovec const *msg_sect) | 1255 | unsigned int num_sect, struct iovec const *msg_sect) |
1263 | { | 1256 | { |
1264 | struct port *p_ptr; | 1257 | struct port *p_ptr; |
1265 | struct tipc_msg *msg; | 1258 | struct tipc_msg *msg; |
1266 | u32 destnode = domain; | 1259 | u32 destnode = domain; |
1267 | u32 destport; | 1260 | u32 destport; |
1268 | int res; | 1261 | int res; |
1269 | 1262 | ||
1270 | p_ptr = tipc_port_deref(ref); | 1263 | p_ptr = tipc_port_deref(ref); |
1271 | if (!p_ptr || p_ptr->publ.connected) | 1264 | if (!p_ptr || p_ptr->publ.connected) |
1272 | return -EINVAL; | 1265 | return -EINVAL; |
1273 | 1266 | ||
1274 | msg = &p_ptr->publ.phdr; | 1267 | msg = &p_ptr->publ.phdr; |
1275 | msg_set_type(msg, TIPC_NAMED_MSG); | 1268 | msg_set_type(msg, TIPC_NAMED_MSG); |
1276 | msg_set_orignode(msg, tipc_own_addr); | 1269 | msg_set_orignode(msg, tipc_own_addr); |
1277 | msg_set_origport(msg, ref); | 1270 | msg_set_origport(msg, ref); |
1278 | msg_set_hdr_sz(msg, LONG_H_SIZE); | 1271 | msg_set_hdr_sz(msg, LONG_H_SIZE); |
1279 | msg_set_nametype(msg, name->type); | 1272 | msg_set_nametype(msg, name->type); |
1280 | msg_set_nameinst(msg, name->instance); | 1273 | msg_set_nameinst(msg, name->instance); |
1281 | msg_set_lookup_scope(msg, tipc_addr_scope(domain)); | 1274 | msg_set_lookup_scope(msg, tipc_addr_scope(domain)); |
1282 | destport = tipc_nametbl_translate(name->type, name->instance, &destnode); | 1275 | destport = tipc_nametbl_translate(name->type, name->instance, &destnode); |
1283 | msg_set_destnode(msg, destnode); | 1276 | msg_set_destnode(msg, destnode); |
1284 | msg_set_destport(msg, destport); | 1277 | msg_set_destport(msg, destport); |
1285 | 1278 | ||
1286 | if (likely(destport)) { | 1279 | if (likely(destport)) { |
1287 | p_ptr->sent++; | 1280 | p_ptr->sent++; |
1288 | if (likely(destnode == tipc_own_addr)) | 1281 | if (likely(destnode == tipc_own_addr)) |
1289 | return tipc_port_recv_sections(p_ptr, num_sect, msg_sect); | 1282 | return tipc_port_recv_sections(p_ptr, num_sect, msg_sect); |
1290 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, | 1283 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, |
1291 | destnode); | 1284 | destnode); |
1292 | if (likely(res != -ELINKCONG)) | 1285 | if (likely(res != -ELINKCONG)) |
1293 | return res; | 1286 | return res; |
1294 | if (port_unreliable(p_ptr)) { | 1287 | if (port_unreliable(p_ptr)) { |
1295 | /* Just calculate msg length and return */ | 1288 | /* Just calculate msg length and return */ |
1296 | return tipc_msg_calc_data_size(msg_sect, num_sect); | 1289 | return tipc_msg_calc_data_size(msg_sect, num_sect); |
1297 | } | 1290 | } |
1298 | return -ELINKCONG; | 1291 | return -ELINKCONG; |
1299 | } | 1292 | } |
1300 | return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, | 1293 | return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, |
1301 | TIPC_ERR_NO_NAME); | 1294 | TIPC_ERR_NO_NAME); |
1302 | } | 1295 | } |
1303 | 1296 | ||
1304 | /** | 1297 | /** |
1305 | * tipc_send2port - send message sections to port identity | 1298 | * tipc_send2port - send message sections to port identity |
1306 | */ | 1299 | */ |
1307 | 1300 | ||
1308 | int tipc_send2port(u32 ref, struct tipc_portid const *dest, | 1301 | int tipc_send2port(u32 ref, struct tipc_portid const *dest, |
1309 | unsigned int num_sect, struct iovec const *msg_sect) | 1302 | unsigned int num_sect, struct iovec const *msg_sect) |
1310 | { | 1303 | { |
1311 | struct port *p_ptr; | 1304 | struct port *p_ptr; |
1312 | struct tipc_msg *msg; | 1305 | struct tipc_msg *msg; |
1313 | int res; | 1306 | int res; |
1314 | 1307 | ||
1315 | p_ptr = tipc_port_deref(ref); | 1308 | p_ptr = tipc_port_deref(ref); |
1316 | if (!p_ptr || p_ptr->publ.connected) | 1309 | if (!p_ptr || p_ptr->publ.connected) |
1317 | return -EINVAL; | 1310 | return -EINVAL; |
1318 | 1311 | ||
1319 | msg = &p_ptr->publ.phdr; | 1312 | msg = &p_ptr->publ.phdr; |
1320 | msg_set_type(msg, TIPC_DIRECT_MSG); | 1313 | msg_set_type(msg, TIPC_DIRECT_MSG); |
1321 | msg_set_orignode(msg, tipc_own_addr); | 1314 | msg_set_orignode(msg, tipc_own_addr); |
1322 | msg_set_origport(msg, ref); | 1315 | msg_set_origport(msg, ref); |
1323 | msg_set_destnode(msg, dest->node); | 1316 | msg_set_destnode(msg, dest->node); |
1324 | msg_set_destport(msg, dest->ref); | 1317 | msg_set_destport(msg, dest->ref); |
1325 | msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); | 1318 | msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); |
1326 | p_ptr->sent++; | 1319 | p_ptr->sent++; |
1327 | if (dest->node == tipc_own_addr) | 1320 | if (dest->node == tipc_own_addr) |
1328 | return tipc_port_recv_sections(p_ptr, num_sect, msg_sect); | 1321 | return tipc_port_recv_sections(p_ptr, num_sect, msg_sect); |
1329 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node); | 1322 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node); |
1330 | if (likely(res != -ELINKCONG)) | 1323 | if (likely(res != -ELINKCONG)) |
1331 | return res; | 1324 | return res; |
1332 | if (port_unreliable(p_ptr)) { | 1325 | if (port_unreliable(p_ptr)) { |
1333 | /* Just calculate msg length and return */ | 1326 | /* Just calculate msg length and return */ |
1334 | return tipc_msg_calc_data_size(msg_sect, num_sect); | 1327 | return tipc_msg_calc_data_size(msg_sect, num_sect); |
1335 | } | 1328 | } |
1336 | return -ELINKCONG; | 1329 | return -ELINKCONG; |
1337 | } | 1330 | } |
1338 | 1331 | ||
1339 | /** | 1332 | /** |
1340 | * tipc_send_buf2port - send message buffer to port identity | 1333 | * tipc_send_buf2port - send message buffer to port identity |
1341 | */ | 1334 | */ |
1342 | 1335 | ||
1343 | int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest, | 1336 | int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest, |
1344 | struct sk_buff *buf, unsigned int dsz) | 1337 | struct sk_buff *buf, unsigned int dsz) |
1345 | { | 1338 | { |
1346 | struct port *p_ptr; | 1339 | struct port *p_ptr; |
1347 | struct tipc_msg *msg; | 1340 | struct tipc_msg *msg; |
1348 | int res; | 1341 | int res; |
1349 | 1342 | ||
1350 | p_ptr = (struct port *)tipc_ref_deref(ref); | 1343 | p_ptr = (struct port *)tipc_ref_deref(ref); |
1351 | if (!p_ptr || p_ptr->publ.connected) | 1344 | if (!p_ptr || p_ptr->publ.connected) |
1352 | return -EINVAL; | 1345 | return -EINVAL; |
1353 | 1346 | ||
1354 | msg = &p_ptr->publ.phdr; | 1347 | msg = &p_ptr->publ.phdr; |
1355 | msg_set_type(msg, TIPC_DIRECT_MSG); | 1348 | msg_set_type(msg, TIPC_DIRECT_MSG); |
1356 | msg_set_orignode(msg, tipc_own_addr); | 1349 | msg_set_orignode(msg, tipc_own_addr); |
1357 | msg_set_origport(msg, ref); | 1350 | msg_set_origport(msg, ref); |
1358 | msg_set_destnode(msg, dest->node); | 1351 | msg_set_destnode(msg, dest->node); |
1359 | msg_set_destport(msg, dest->ref); | 1352 | msg_set_destport(msg, dest->ref); |
1360 | msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); | 1353 | msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); |
1361 | msg_set_size(msg, DIR_MSG_H_SIZE + dsz); | 1354 | msg_set_size(msg, DIR_MSG_H_SIZE + dsz); |
1362 | if (skb_cow(buf, DIR_MSG_H_SIZE)) | 1355 | if (skb_cow(buf, DIR_MSG_H_SIZE)) |
1363 | return -ENOMEM; | 1356 | return -ENOMEM; |
1364 | 1357 | ||
1365 | skb_push(buf, DIR_MSG_H_SIZE); | 1358 | skb_push(buf, DIR_MSG_H_SIZE); |
1366 | skb_copy_to_linear_data(buf, msg, DIR_MSG_H_SIZE); | 1359 | skb_copy_to_linear_data(buf, msg, DIR_MSG_H_SIZE); |
1367 | msg_dbg(msg, "buf2port: "); | 1360 | msg_dbg(msg, "buf2port: "); |
1368 | p_ptr->sent++; | 1361 | p_ptr->sent++; |
1369 | if (dest->node == tipc_own_addr) | 1362 | if (dest->node == tipc_own_addr) |
1370 | return tipc_port_recv_msg(buf); | 1363 | return tipc_port_recv_msg(buf); |
1371 | res = tipc_send_buf_fast(buf, dest->node); | 1364 | res = tipc_send_buf_fast(buf, dest->node); |
1372 | if (likely(res != -ELINKCONG)) | 1365 | if (likely(res != -ELINKCONG)) |
1373 | return res; | 1366 | return res; |
1374 | if (port_unreliable(p_ptr)) | 1367 | if (port_unreliable(p_ptr)) |
1375 | return dsz; | 1368 | return dsz; |
1376 | return -ELINKCONG; | 1369 | return -ELINKCONG; |
1377 | } | 1370 | } |
1378 | 1371 | ||
1379 | 1372 |
net/tipc/port.h
1 | /* | 1 | /* |
2 | * net/tipc/port.h: Include file for TIPC port code | 2 | * net/tipc/port.h: Include file for TIPC port code |
3 | * | 3 | * |
4 | * Copyright (c) 1994-2007, Ericsson AB | 4 | * Copyright (c) 1994-2007, Ericsson AB |
5 | * Copyright (c) 2004-2007, Wind River Systems | 5 | * Copyright (c) 2004-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions are met: | 9 | * modification, are permitted provided that the following conditions are met: |
10 | * | 10 | * |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the names of the copyright holders nor the names of its | 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 | 17 | * contributors may be used to endorse or promote products derived from |
18 | * this software without specific prior written permission. | 18 | * this software without specific prior written permission. |
19 | * | 19 | * |
20 | * Alternatively, this software may be distributed under the terms of the | 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 | 21 | * GNU General Public License ("GPL") version 2 as published by the Free |
22 | * Software Foundation. | 22 | * Software Foundation. |
23 | * | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 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 | 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 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 | 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 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 | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
34 | * POSSIBILITY OF SUCH DAMAGE. | 34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #ifndef _TIPC_PORT_H | 37 | #ifndef _TIPC_PORT_H |
38 | #define _TIPC_PORT_H | 38 | #define _TIPC_PORT_H |
39 | 39 | ||
40 | #include "ref.h" | 40 | #include "ref.h" |
41 | #include "net.h" | 41 | #include "net.h" |
42 | #include "msg.h" | 42 | #include "msg.h" |
43 | #include "node_subscr.h" | 43 | #include "node_subscr.h" |
44 | 44 | ||
45 | #define TIPC_FLOW_CONTROL_WIN 512 | 45 | #define TIPC_FLOW_CONTROL_WIN 512 |
46 | 46 | ||
47 | typedef void (*tipc_msg_err_event) (void *usr_handle, u32 portref, | 47 | typedef void (*tipc_msg_err_event) (void *usr_handle, u32 portref, |
48 | struct sk_buff **buf, unsigned char const *data, | 48 | struct sk_buff **buf, unsigned char const *data, |
49 | unsigned int size, int reason, | 49 | unsigned int size, int reason, |
50 | struct tipc_portid const *attmpt_destid); | 50 | struct tipc_portid const *attmpt_destid); |
51 | 51 | ||
52 | typedef void (*tipc_named_msg_err_event) (void *usr_handle, u32 portref, | 52 | typedef void (*tipc_named_msg_err_event) (void *usr_handle, u32 portref, |
53 | struct sk_buff **buf, unsigned char const *data, | 53 | struct sk_buff **buf, unsigned char const *data, |
54 | unsigned int size, int reason, | 54 | unsigned int size, int reason, |
55 | struct tipc_name_seq const *attmpt_dest); | 55 | struct tipc_name_seq const *attmpt_dest); |
56 | 56 | ||
57 | typedef void (*tipc_conn_shutdown_event) (void *usr_handle, u32 portref, | 57 | typedef void (*tipc_conn_shutdown_event) (void *usr_handle, u32 portref, |
58 | struct sk_buff **buf, unsigned char const *data, | 58 | struct sk_buff **buf, unsigned char const *data, |
59 | unsigned int size, int reason); | 59 | unsigned int size, int reason); |
60 | 60 | ||
61 | typedef void (*tipc_msg_event) (void *usr_handle, u32 portref, | 61 | typedef void (*tipc_msg_event) (void *usr_handle, u32 portref, |
62 | struct sk_buff **buf, unsigned char const *data, | 62 | struct sk_buff **buf, unsigned char const *data, |
63 | unsigned int size, unsigned int importance, | 63 | unsigned int size, unsigned int importance, |
64 | struct tipc_portid const *origin); | 64 | struct tipc_portid const *origin); |
65 | 65 | ||
66 | typedef void (*tipc_named_msg_event) (void *usr_handle, u32 portref, | 66 | typedef void (*tipc_named_msg_event) (void *usr_handle, u32 portref, |
67 | struct sk_buff **buf, unsigned char const *data, | 67 | struct sk_buff **buf, unsigned char const *data, |
68 | unsigned int size, unsigned int importance, | 68 | unsigned int size, unsigned int importance, |
69 | struct tipc_portid const *orig, | 69 | struct tipc_portid const *orig, |
70 | struct tipc_name_seq const *dest); | 70 | struct tipc_name_seq const *dest); |
71 | 71 | ||
72 | typedef void (*tipc_conn_msg_event) (void *usr_handle, u32 portref, | 72 | typedef void (*tipc_conn_msg_event) (void *usr_handle, u32 portref, |
73 | struct sk_buff **buf, unsigned char const *data, | 73 | struct sk_buff **buf, unsigned char const *data, |
74 | unsigned int size); | 74 | unsigned int size); |
75 | 75 | ||
76 | typedef void (*tipc_continue_event) (void *usr_handle, u32 portref); | 76 | typedef void (*tipc_continue_event) (void *usr_handle, u32 portref); |
77 | 77 | ||
78 | /** | 78 | /** |
79 | * struct user_port - TIPC user port (used with native API) | 79 | * struct user_port - TIPC user port (used with native API) |
80 | * @user_ref: id of user who created user port | ||
81 | * @usr_handle: user-specified field | 80 | * @usr_handle: user-specified field |
82 | * @ref: object reference to associated TIPC port | 81 | * @ref: object reference to associated TIPC port |
83 | * <various callback routines> | 82 | * <various callback routines> |
84 | * @uport_list: adjacent user ports in list of ports held by user | ||
85 | */ | 83 | */ |
86 | 84 | ||
87 | struct user_port { | 85 | struct user_port { |
88 | u32 user_ref; | ||
89 | void *usr_handle; | 86 | void *usr_handle; |
90 | u32 ref; | 87 | u32 ref; |
91 | tipc_msg_err_event err_cb; | 88 | tipc_msg_err_event err_cb; |
92 | tipc_named_msg_err_event named_err_cb; | 89 | tipc_named_msg_err_event named_err_cb; |
93 | tipc_conn_shutdown_event conn_err_cb; | 90 | tipc_conn_shutdown_event conn_err_cb; |
94 | tipc_msg_event msg_cb; | 91 | tipc_msg_event msg_cb; |
95 | tipc_named_msg_event named_msg_cb; | 92 | tipc_named_msg_event named_msg_cb; |
96 | tipc_conn_msg_event conn_msg_cb; | 93 | tipc_conn_msg_event conn_msg_cb; |
97 | tipc_continue_event continue_event_cb; | 94 | tipc_continue_event continue_event_cb; |
98 | struct list_head uport_list; | ||
99 | }; | 95 | }; |
100 | 96 | ||
101 | /** | 97 | /** |
102 | * struct tipc_port - TIPC port info available to socket API | 98 | * struct tipc_port - TIPC port info available to socket API |
103 | * @usr_handle: pointer to additional user-defined information about port | 99 | * @usr_handle: pointer to additional user-defined information about port |
104 | * @lock: pointer to spinlock for controlling access to port | 100 | * @lock: pointer to spinlock for controlling access to port |
105 | * @connected: non-zero if port is currently connected to a peer port | 101 | * @connected: non-zero if port is currently connected to a peer port |
106 | * @conn_type: TIPC type used when connection was established | 102 | * @conn_type: TIPC type used when connection was established |
107 | * @conn_instance: TIPC instance used when connection was established | 103 | * @conn_instance: TIPC instance used when connection was established |
108 | * @conn_unacked: number of unacknowledged messages received from peer port | 104 | * @conn_unacked: number of unacknowledged messages received from peer port |
109 | * @published: non-zero if port has one or more associated names | 105 | * @published: non-zero if port has one or more associated names |
110 | * @congested: non-zero if cannot send because of link or port congestion | 106 | * @congested: non-zero if cannot send because of link or port congestion |
111 | * @max_pkt: maximum packet size "hint" used when building messages sent by port | 107 | * @max_pkt: maximum packet size "hint" used when building messages sent by port |
112 | * @ref: unique reference to port in TIPC object registry | 108 | * @ref: unique reference to port in TIPC object registry |
113 | * @phdr: preformatted message header used when sending messages | 109 | * @phdr: preformatted message header used when sending messages |
114 | */ | 110 | */ |
115 | struct tipc_port { | 111 | struct tipc_port { |
116 | void *usr_handle; | 112 | void *usr_handle; |
117 | spinlock_t *lock; | 113 | spinlock_t *lock; |
118 | int connected; | 114 | int connected; |
119 | u32 conn_type; | 115 | u32 conn_type; |
120 | u32 conn_instance; | 116 | u32 conn_instance; |
121 | u32 conn_unacked; | 117 | u32 conn_unacked; |
122 | int published; | 118 | int published; |
123 | u32 congested; | 119 | u32 congested; |
124 | u32 max_pkt; | 120 | u32 max_pkt; |
125 | u32 ref; | 121 | u32 ref; |
126 | struct tipc_msg phdr; | 122 | struct tipc_msg phdr; |
127 | }; | 123 | }; |
128 | 124 | ||
129 | /** | 125 | /** |
130 | * struct port - TIPC port structure | 126 | * struct port - TIPC port structure |
131 | * @publ: TIPC port info available to privileged users | 127 | * @publ: TIPC port info available to privileged users |
132 | * @port_list: adjacent ports in TIPC's global list of ports | 128 | * @port_list: adjacent ports in TIPC's global list of ports |
133 | * @dispatcher: ptr to routine which handles received messages | 129 | * @dispatcher: ptr to routine which handles received messages |
134 | * @wakeup: ptr to routine to call when port is no longer congested | 130 | * @wakeup: ptr to routine to call when port is no longer congested |
135 | * @user_port: ptr to user port associated with port (if any) | 131 | * @user_port: ptr to user port associated with port (if any) |
136 | * @wait_list: adjacent ports in list of ports waiting on link congestion | 132 | * @wait_list: adjacent ports in list of ports waiting on link congestion |
137 | * @waiting_pkts: | 133 | * @waiting_pkts: |
138 | * @sent: | 134 | * @sent: |
139 | * @acked: | 135 | * @acked: |
140 | * @publications: list of publications for port | 136 | * @publications: list of publications for port |
141 | * @pub_count: total # of publications port has made during its lifetime | 137 | * @pub_count: total # of publications port has made during its lifetime |
142 | * @probing_state: | 138 | * @probing_state: |
143 | * @probing_interval: | 139 | * @probing_interval: |
144 | * @last_in_seqno: | 140 | * @last_in_seqno: |
145 | * @timer_ref: | 141 | * @timer_ref: |
146 | * @subscription: "node down" subscription used to terminate failed connections | 142 | * @subscription: "node down" subscription used to terminate failed connections |
147 | */ | 143 | */ |
148 | 144 | ||
149 | struct port { | 145 | struct port { |
150 | struct tipc_port publ; | 146 | struct tipc_port publ; |
151 | struct list_head port_list; | 147 | struct list_head port_list; |
152 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *); | 148 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *); |
153 | void (*wakeup)(struct tipc_port *); | 149 | void (*wakeup)(struct tipc_port *); |
154 | struct user_port *user_port; | 150 | struct user_port *user_port; |
155 | struct list_head wait_list; | 151 | struct list_head wait_list; |
156 | u32 waiting_pkts; | 152 | u32 waiting_pkts; |
157 | u32 sent; | 153 | u32 sent; |
158 | u32 acked; | 154 | u32 acked; |
159 | struct list_head publications; | 155 | struct list_head publications; |
160 | u32 pub_count; | 156 | u32 pub_count; |
161 | u32 probing_state; | 157 | u32 probing_state; |
162 | u32 probing_interval; | 158 | u32 probing_interval; |
163 | u32 last_in_seqno; | 159 | u32 last_in_seqno; |
164 | struct timer_list timer; | 160 | struct timer_list timer; |
165 | struct tipc_node_subscr subscription; | 161 | struct tipc_node_subscr subscription; |
166 | }; | 162 | }; |
167 | 163 | ||
168 | extern spinlock_t tipc_port_list_lock; | 164 | extern spinlock_t tipc_port_list_lock; |
169 | struct port_list; | 165 | struct port_list; |
170 | 166 | ||
171 | /* | 167 | /* |
172 | * TIPC port manipulation routines | 168 | * TIPC port manipulation routines |
173 | */ | 169 | */ |
174 | struct tipc_port *tipc_createport_raw(void *usr_handle, | 170 | struct tipc_port *tipc_createport_raw(void *usr_handle, |
175 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), | 171 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), |
176 | void (*wakeup)(struct tipc_port *), const u32 importance); | 172 | void (*wakeup)(struct tipc_port *), const u32 importance); |
177 | 173 | ||
178 | int tipc_reject_msg(struct sk_buff *buf, u32 err); | 174 | int tipc_reject_msg(struct sk_buff *buf, u32 err); |
179 | 175 | ||
180 | int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode); | 176 | int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode); |
181 | 177 | ||
182 | void tipc_acknowledge(u32 port_ref, u32 ack); | 178 | void tipc_acknowledge(u32 port_ref, u32 ack); |
183 | 179 | ||
184 | int tipc_createport(unsigned int tipc_user, void *usr_handle, | 180 | int tipc_createport(void *usr_handle, |
185 | unsigned int importance, tipc_msg_err_event error_cb, | 181 | unsigned int importance, tipc_msg_err_event error_cb, |
186 | tipc_named_msg_err_event named_error_cb, | 182 | tipc_named_msg_err_event named_error_cb, |
187 | tipc_conn_shutdown_event conn_error_cb, tipc_msg_event msg_cb, | 183 | tipc_conn_shutdown_event conn_error_cb, tipc_msg_event msg_cb, |
188 | tipc_named_msg_event named_msg_cb, | 184 | tipc_named_msg_event named_msg_cb, |
189 | tipc_conn_msg_event conn_msg_cb, | 185 | tipc_conn_msg_event conn_msg_cb, |
190 | tipc_continue_event continue_event_cb, u32 *portref); | 186 | tipc_continue_event continue_event_cb, u32 *portref); |
191 | 187 | ||
192 | int tipc_deleteport(u32 portref); | 188 | int tipc_deleteport(u32 portref); |
193 | 189 | ||
194 | int tipc_portimportance(u32 portref, unsigned int *importance); | 190 | int tipc_portimportance(u32 portref, unsigned int *importance); |
195 | int tipc_set_portimportance(u32 portref, unsigned int importance); | 191 | int tipc_set_portimportance(u32 portref, unsigned int importance); |
196 | 192 | ||
197 | int tipc_portunreliable(u32 portref, unsigned int *isunreliable); | 193 | int tipc_portunreliable(u32 portref, unsigned int *isunreliable); |
198 | int tipc_set_portunreliable(u32 portref, unsigned int isunreliable); | 194 | int tipc_set_portunreliable(u32 portref, unsigned int isunreliable); |
199 | 195 | ||
200 | int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable); | 196 | int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable); |
201 | int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); | 197 | int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); |
202 | 198 | ||
203 | int tipc_publish(u32 portref, unsigned int scope, | 199 | int tipc_publish(u32 portref, unsigned int scope, |
204 | struct tipc_name_seq const *name_seq); | 200 | struct tipc_name_seq const *name_seq); |
205 | int tipc_withdraw(u32 portref, unsigned int scope, | 201 | int tipc_withdraw(u32 portref, unsigned int scope, |
206 | struct tipc_name_seq const *name_seq); | 202 | struct tipc_name_seq const *name_seq); |
207 | 203 | ||
208 | int tipc_connect2port(u32 portref, struct tipc_portid const *port); | 204 | int tipc_connect2port(u32 portref, struct tipc_portid const *port); |
209 | 205 | ||
210 | int tipc_disconnect(u32 portref); | 206 | int tipc_disconnect(u32 portref); |
211 | 207 | ||
212 | int tipc_shutdown(u32 ref); | 208 | int tipc_shutdown(u32 ref); |
213 | 209 | ||
214 | 210 | ||
215 | /* | 211 | /* |
216 | * The following routines require that the port be locked on entry | 212 | * The following routines require that the port be locked on entry |
217 | */ | 213 | */ |
218 | int tipc_disconnect_port(struct tipc_port *tp_ptr); | 214 | int tipc_disconnect_port(struct tipc_port *tp_ptr); |
219 | 215 | ||
220 | /* | 216 | /* |
221 | * TIPC messaging routines | 217 | * TIPC messaging routines |
222 | */ | 218 | */ |
223 | int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect); | 219 | int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect); |
224 | 220 | ||
225 | int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain, | 221 | int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain, |
226 | unsigned int num_sect, struct iovec const *msg_sect); | 222 | unsigned int num_sect, struct iovec const *msg_sect); |
227 | 223 | ||
228 | int tipc_send2port(u32 portref, struct tipc_portid const *dest, | 224 | int tipc_send2port(u32 portref, struct tipc_portid const *dest, |
229 | unsigned int num_sect, struct iovec const *msg_sect); | 225 | unsigned int num_sect, struct iovec const *msg_sect); |
230 | 226 | ||
231 | int tipc_send_buf2port(u32 portref, struct tipc_portid const *dest, | 227 | int tipc_send_buf2port(u32 portref, struct tipc_portid const *dest, |
232 | struct sk_buff *buf, unsigned int dsz); | 228 | struct sk_buff *buf, unsigned int dsz); |
233 | 229 | ||
234 | int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, | 230 | int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, |
235 | unsigned int section_count, struct iovec const *msg); | 231 | unsigned int section_count, struct iovec const *msg); |
236 | 232 | ||
237 | int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, | 233 | int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, |
238 | struct iovec const *msg_sect, u32 num_sect, | 234 | struct iovec const *msg_sect, u32 num_sect, |
239 | int err); | 235 | int err); |
240 | struct sk_buff *tipc_port_get_ports(void); | 236 | struct sk_buff *tipc_port_get_ports(void); |
241 | void tipc_port_recv_proto_msg(struct sk_buff *buf); | 237 | void tipc_port_recv_proto_msg(struct sk_buff *buf); |
242 | void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp); | 238 | void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp); |
243 | void tipc_port_reinit(void); | 239 | void tipc_port_reinit(void); |
244 | 240 | ||
245 | /** | 241 | /** |
246 | * tipc_port_lock - lock port instance referred to and return its pointer | 242 | * tipc_port_lock - lock port instance referred to and return its pointer |
247 | */ | 243 | */ |
248 | 244 | ||
249 | static inline struct port *tipc_port_lock(u32 ref) | 245 | static inline struct port *tipc_port_lock(u32 ref) |
250 | { | 246 | { |
251 | return (struct port *)tipc_ref_lock(ref); | 247 | return (struct port *)tipc_ref_lock(ref); |
252 | } | 248 | } |
253 | 249 | ||
254 | /** | 250 | /** |
255 | * tipc_port_unlock - unlock a port instance | 251 | * tipc_port_unlock - unlock a port instance |
256 | * | 252 | * |
257 | * Can use pointer instead of tipc_ref_unlock() since port is already locked. | 253 | * Can use pointer instead of tipc_ref_unlock() since port is already locked. |
258 | */ | 254 | */ |
259 | 255 | ||
260 | static inline void tipc_port_unlock(struct port *p_ptr) | 256 | static inline void tipc_port_unlock(struct port *p_ptr) |
261 | { | 257 | { |
262 | spin_unlock_bh(p_ptr->publ.lock); | 258 | spin_unlock_bh(p_ptr->publ.lock); |
263 | } | 259 | } |
264 | 260 | ||
265 | static inline struct port* tipc_port_deref(u32 ref) | 261 | static inline struct port* tipc_port_deref(u32 ref) |
266 | { | 262 | { |
267 | return (struct port *)tipc_ref_deref(ref); | 263 | return (struct port *)tipc_ref_deref(ref); |
268 | } | 264 | } |
269 | 265 | ||
270 | static inline u32 tipc_peer_port(struct port *p_ptr) | 266 | static inline u32 tipc_peer_port(struct port *p_ptr) |
271 | { | 267 | { |
272 | return msg_destport(&p_ptr->publ.phdr); | 268 | return msg_destport(&p_ptr->publ.phdr); |
273 | } | 269 | } |
274 | 270 | ||
275 | static inline u32 tipc_peer_node(struct port *p_ptr) | 271 | static inline u32 tipc_peer_node(struct port *p_ptr) |
276 | { | 272 | { |
277 | return msg_destnode(&p_ptr->publ.phdr); | 273 | return msg_destnode(&p_ptr->publ.phdr); |
278 | } | 274 | } |
279 | 275 | ||
280 | static inline int tipc_port_congested(struct port *p_ptr) | 276 | static inline int tipc_port_congested(struct port *p_ptr) |
281 | { | 277 | { |
282 | return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2); | 278 | return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2); |
283 | } | 279 | } |
284 | 280 | ||
285 | /** | 281 | /** |
286 | * tipc_port_recv_msg - receive message from lower layer and deliver to port user | 282 | * tipc_port_recv_msg - receive message from lower layer and deliver to port user |
287 | */ | 283 | */ |
288 | 284 | ||
289 | static inline int tipc_port_recv_msg(struct sk_buff *buf) | 285 | static inline int tipc_port_recv_msg(struct sk_buff *buf) |
290 | { | 286 | { |
291 | struct port *p_ptr; | 287 | struct port *p_ptr; |
292 | struct tipc_msg *msg = buf_msg(buf); | 288 | struct tipc_msg *msg = buf_msg(buf); |
293 | u32 destport = msg_destport(msg); | 289 | u32 destport = msg_destport(msg); |
294 | u32 dsz = msg_data_sz(msg); | 290 | u32 dsz = msg_data_sz(msg); |
295 | u32 err; | 291 | u32 err; |
296 | 292 | ||
297 | /* forward unresolved named message */ | 293 | /* forward unresolved named message */ |
298 | if (unlikely(!destport)) { | 294 | if (unlikely(!destport)) { |
299 | tipc_net_route_msg(buf); | 295 | tipc_net_route_msg(buf); |
300 | return dsz; | 296 | return dsz; |
301 | } | 297 | } |
302 | 298 | ||
303 | /* validate destination & pass to port, otherwise reject message */ | 299 | /* validate destination & pass to port, otherwise reject message */ |
304 | p_ptr = tipc_port_lock(destport); | 300 | p_ptr = tipc_port_lock(destport); |
305 | if (likely(p_ptr)) { | 301 | if (likely(p_ptr)) { |
306 | if (likely(p_ptr->publ.connected)) { | 302 | if (likely(p_ptr->publ.connected)) { |
307 | if ((unlikely(msg_origport(msg) != tipc_peer_port(p_ptr))) || | 303 | if ((unlikely(msg_origport(msg) != tipc_peer_port(p_ptr))) || |
308 | (unlikely(msg_orignode(msg) != tipc_peer_node(p_ptr))) || | 304 | (unlikely(msg_orignode(msg) != tipc_peer_node(p_ptr))) || |
309 | (unlikely(!msg_connected(msg)))) { | 305 | (unlikely(!msg_connected(msg)))) { |
310 | err = TIPC_ERR_NO_PORT; | 306 | err = TIPC_ERR_NO_PORT; |
311 | tipc_port_unlock(p_ptr); | 307 | tipc_port_unlock(p_ptr); |
312 | goto reject; | 308 | goto reject; |
313 | } | 309 | } |
314 | } | 310 | } |
315 | err = p_ptr->dispatcher(&p_ptr->publ, buf); | 311 | err = p_ptr->dispatcher(&p_ptr->publ, buf); |
316 | tipc_port_unlock(p_ptr); | 312 | tipc_port_unlock(p_ptr); |
317 | if (likely(!err)) | 313 | if (likely(!err)) |
318 | return dsz; | 314 | return dsz; |
319 | } else { | 315 | } else { |
320 | err = TIPC_ERR_NO_PORT; | 316 | err = TIPC_ERR_NO_PORT; |
321 | } | 317 | } |
322 | reject: | 318 | reject: |
323 | dbg("port->rejecting, err = %x..\n",err); | 319 | dbg("port->rejecting, err = %x..\n",err); |
324 | return tipc_reject_msg(buf, err); | 320 | return tipc_reject_msg(buf, err); |
325 | } | 321 | } |
326 | 322 | ||
327 | #endif | 323 | #endif |
328 | 324 |
net/tipc/subscr.c
1 | /* | 1 | /* |
2 | * net/tipc/subscr.c: TIPC network topology service | 2 | * net/tipc/subscr.c: TIPC network topology service |
3 | * | 3 | * |
4 | * Copyright (c) 2000-2006, Ericsson AB | 4 | * Copyright (c) 2000-2006, Ericsson AB |
5 | * Copyright (c) 2005-2007, Wind River Systems | 5 | * Copyright (c) 2005-2007, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions are met: | 9 | * modification, are permitted provided that the following conditions are met: |
10 | * | 10 | * |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the names of the copyright holders nor the names of its | 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 | 17 | * contributors may be used to endorse or promote products derived from |
18 | * this software without specific prior written permission. | 18 | * this software without specific prior written permission. |
19 | * | 19 | * |
20 | * Alternatively, this software may be distributed under the terms of the | 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 | 21 | * GNU General Public License ("GPL") version 2 as published by the Free |
22 | * Software Foundation. | 22 | * Software Foundation. |
23 | * | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 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 | 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 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 | 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 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 | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
34 | * POSSIBILITY OF SUCH DAMAGE. | 34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "name_table.h" | 38 | #include "name_table.h" |
39 | #include "port.h" | 39 | #include "port.h" |
40 | #include "subscr.h" | 40 | #include "subscr.h" |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * struct subscriber - TIPC network topology subscriber | 43 | * struct subscriber - TIPC network topology subscriber |
44 | * @port_ref: object reference to server port connecting to subscriber | 44 | * @port_ref: object reference to server port connecting to subscriber |
45 | * @lock: pointer to spinlock controlling access to subscriber's server port | 45 | * @lock: pointer to spinlock controlling access to subscriber's server port |
46 | * @subscriber_list: adjacent subscribers in top. server's list of subscribers | 46 | * @subscriber_list: adjacent subscribers in top. server's list of subscribers |
47 | * @subscription_list: list of subscription objects for this subscriber | 47 | * @subscription_list: list of subscription objects for this subscriber |
48 | */ | 48 | */ |
49 | 49 | ||
50 | struct subscriber { | 50 | struct subscriber { |
51 | u32 port_ref; | 51 | u32 port_ref; |
52 | spinlock_t *lock; | 52 | spinlock_t *lock; |
53 | struct list_head subscriber_list; | 53 | struct list_head subscriber_list; |
54 | struct list_head subscription_list; | 54 | struct list_head subscription_list; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | /** | 57 | /** |
58 | * struct top_srv - TIPC network topology subscription service | 58 | * struct top_srv - TIPC network topology subscription service |
59 | * @user_ref: TIPC userid of subscription service | 59 | * @user_ref: TIPC userid of subscription service |
60 | * @setup_port: reference to TIPC port that handles subscription requests | 60 | * @setup_port: reference to TIPC port that handles subscription requests |
61 | * @subscription_count: number of active subscriptions (not subscribers!) | 61 | * @subscription_count: number of active subscriptions (not subscribers!) |
62 | * @subscriber_list: list of ports subscribing to service | 62 | * @subscriber_list: list of ports subscribing to service |
63 | * @lock: spinlock govering access to subscriber list | 63 | * @lock: spinlock govering access to subscriber list |
64 | */ | 64 | */ |
65 | 65 | ||
66 | struct top_srv { | 66 | struct top_srv { |
67 | u32 setup_port; | 67 | u32 setup_port; |
68 | atomic_t subscription_count; | 68 | atomic_t subscription_count; |
69 | struct list_head subscriber_list; | 69 | struct list_head subscriber_list; |
70 | spinlock_t lock; | 70 | spinlock_t lock; |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static struct top_srv topsrv = { 0 }; | 73 | static struct top_srv topsrv = { 0 }; |
74 | 74 | ||
75 | /** | 75 | /** |
76 | * htohl - convert value to endianness used by destination | 76 | * htohl - convert value to endianness used by destination |
77 | * @in: value to convert | 77 | * @in: value to convert |
78 | * @swap: non-zero if endianness must be reversed | 78 | * @swap: non-zero if endianness must be reversed |
79 | * | 79 | * |
80 | * Returns converted value | 80 | * Returns converted value |
81 | */ | 81 | */ |
82 | 82 | ||
83 | static u32 htohl(u32 in, int swap) | 83 | static u32 htohl(u32 in, int swap) |
84 | { | 84 | { |
85 | return swap ? swab32(in) : in; | 85 | return swap ? swab32(in) : in; |
86 | } | 86 | } |
87 | 87 | ||
88 | /** | 88 | /** |
89 | * subscr_send_event - send a message containing a tipc_event to the subscriber | 89 | * subscr_send_event - send a message containing a tipc_event to the subscriber |
90 | * | 90 | * |
91 | * Note: Must not hold subscriber's server port lock, since tipc_send() will | 91 | * Note: Must not hold subscriber's server port lock, since tipc_send() will |
92 | * try to take the lock if the message is rejected and returned! | 92 | * try to take the lock if the message is rejected and returned! |
93 | */ | 93 | */ |
94 | 94 | ||
95 | static void subscr_send_event(struct subscription *sub, | 95 | static void subscr_send_event(struct subscription *sub, |
96 | u32 found_lower, | 96 | u32 found_lower, |
97 | u32 found_upper, | 97 | u32 found_upper, |
98 | u32 event, | 98 | u32 event, |
99 | u32 port_ref, | 99 | u32 port_ref, |
100 | u32 node) | 100 | u32 node) |
101 | { | 101 | { |
102 | struct iovec msg_sect; | 102 | struct iovec msg_sect; |
103 | 103 | ||
104 | msg_sect.iov_base = (void *)&sub->evt; | 104 | msg_sect.iov_base = (void *)&sub->evt; |
105 | msg_sect.iov_len = sizeof(struct tipc_event); | 105 | msg_sect.iov_len = sizeof(struct tipc_event); |
106 | 106 | ||
107 | sub->evt.event = htohl(event, sub->swap); | 107 | sub->evt.event = htohl(event, sub->swap); |
108 | sub->evt.found_lower = htohl(found_lower, sub->swap); | 108 | sub->evt.found_lower = htohl(found_lower, sub->swap); |
109 | sub->evt.found_upper = htohl(found_upper, sub->swap); | 109 | sub->evt.found_upper = htohl(found_upper, sub->swap); |
110 | sub->evt.port.ref = htohl(port_ref, sub->swap); | 110 | sub->evt.port.ref = htohl(port_ref, sub->swap); |
111 | sub->evt.port.node = htohl(node, sub->swap); | 111 | sub->evt.port.node = htohl(node, sub->swap); |
112 | tipc_send(sub->server_ref, 1, &msg_sect); | 112 | tipc_send(sub->server_ref, 1, &msg_sect); |
113 | } | 113 | } |
114 | 114 | ||
115 | /** | 115 | /** |
116 | * tipc_subscr_overlap - test for subscription overlap with the given values | 116 | * tipc_subscr_overlap - test for subscription overlap with the given values |
117 | * | 117 | * |
118 | * Returns 1 if there is overlap, otherwise 0. | 118 | * Returns 1 if there is overlap, otherwise 0. |
119 | */ | 119 | */ |
120 | 120 | ||
121 | int tipc_subscr_overlap(struct subscription *sub, | 121 | int tipc_subscr_overlap(struct subscription *sub, |
122 | u32 found_lower, | 122 | u32 found_lower, |
123 | u32 found_upper) | 123 | u32 found_upper) |
124 | 124 | ||
125 | { | 125 | { |
126 | if (found_lower < sub->seq.lower) | 126 | if (found_lower < sub->seq.lower) |
127 | found_lower = sub->seq.lower; | 127 | found_lower = sub->seq.lower; |
128 | if (found_upper > sub->seq.upper) | 128 | if (found_upper > sub->seq.upper) |
129 | found_upper = sub->seq.upper; | 129 | found_upper = sub->seq.upper; |
130 | if (found_lower > found_upper) | 130 | if (found_lower > found_upper) |
131 | return 0; | 131 | return 0; |
132 | return 1; | 132 | return 1; |
133 | } | 133 | } |
134 | 134 | ||
135 | /** | 135 | /** |
136 | * tipc_subscr_report_overlap - issue event if there is subscription overlap | 136 | * tipc_subscr_report_overlap - issue event if there is subscription overlap |
137 | * | 137 | * |
138 | * Protected by nameseq.lock in name_table.c | 138 | * Protected by nameseq.lock in name_table.c |
139 | */ | 139 | */ |
140 | 140 | ||
141 | void tipc_subscr_report_overlap(struct subscription *sub, | 141 | void tipc_subscr_report_overlap(struct subscription *sub, |
142 | u32 found_lower, | 142 | u32 found_lower, |
143 | u32 found_upper, | 143 | u32 found_upper, |
144 | u32 event, | 144 | u32 event, |
145 | u32 port_ref, | 145 | u32 port_ref, |
146 | u32 node, | 146 | u32 node, |
147 | int must) | 147 | int must) |
148 | { | 148 | { |
149 | if (!tipc_subscr_overlap(sub, found_lower, found_upper)) | 149 | if (!tipc_subscr_overlap(sub, found_lower, found_upper)) |
150 | return; | 150 | return; |
151 | if (!must && !(sub->filter & TIPC_SUB_PORTS)) | 151 | if (!must && !(sub->filter & TIPC_SUB_PORTS)) |
152 | return; | 152 | return; |
153 | 153 | ||
154 | sub->event_cb(sub, found_lower, found_upper, event, port_ref, node); | 154 | sub->event_cb(sub, found_lower, found_upper, event, port_ref, node); |
155 | } | 155 | } |
156 | 156 | ||
157 | /** | 157 | /** |
158 | * subscr_timeout - subscription timeout has occurred | 158 | * subscr_timeout - subscription timeout has occurred |
159 | */ | 159 | */ |
160 | 160 | ||
161 | static void subscr_timeout(struct subscription *sub) | 161 | static void subscr_timeout(struct subscription *sub) |
162 | { | 162 | { |
163 | struct port *server_port; | 163 | struct port *server_port; |
164 | 164 | ||
165 | /* Validate server port reference (in case subscriber is terminating) */ | 165 | /* Validate server port reference (in case subscriber is terminating) */ |
166 | 166 | ||
167 | server_port = tipc_port_lock(sub->server_ref); | 167 | server_port = tipc_port_lock(sub->server_ref); |
168 | if (server_port == NULL) | 168 | if (server_port == NULL) |
169 | return; | 169 | return; |
170 | 170 | ||
171 | /* Validate timeout (in case subscription is being cancelled) */ | 171 | /* Validate timeout (in case subscription is being cancelled) */ |
172 | 172 | ||
173 | if (sub->timeout == TIPC_WAIT_FOREVER) { | 173 | if (sub->timeout == TIPC_WAIT_FOREVER) { |
174 | tipc_port_unlock(server_port); | 174 | tipc_port_unlock(server_port); |
175 | return; | 175 | return; |
176 | } | 176 | } |
177 | 177 | ||
178 | /* Unlink subscription from name table */ | 178 | /* Unlink subscription from name table */ |
179 | 179 | ||
180 | tipc_nametbl_unsubscribe(sub); | 180 | tipc_nametbl_unsubscribe(sub); |
181 | 181 | ||
182 | /* Unlink subscription from subscriber */ | 182 | /* Unlink subscription from subscriber */ |
183 | 183 | ||
184 | list_del(&sub->subscription_list); | 184 | list_del(&sub->subscription_list); |
185 | 185 | ||
186 | /* Release subscriber's server port */ | 186 | /* Release subscriber's server port */ |
187 | 187 | ||
188 | tipc_port_unlock(server_port); | 188 | tipc_port_unlock(server_port); |
189 | 189 | ||
190 | /* Notify subscriber of timeout */ | 190 | /* Notify subscriber of timeout */ |
191 | 191 | ||
192 | subscr_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, | 192 | subscr_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, |
193 | TIPC_SUBSCR_TIMEOUT, 0, 0); | 193 | TIPC_SUBSCR_TIMEOUT, 0, 0); |
194 | 194 | ||
195 | /* Now destroy subscription */ | 195 | /* Now destroy subscription */ |
196 | 196 | ||
197 | k_term_timer(&sub->timer); | 197 | k_term_timer(&sub->timer); |
198 | kfree(sub); | 198 | kfree(sub); |
199 | atomic_dec(&topsrv.subscription_count); | 199 | atomic_dec(&topsrv.subscription_count); |
200 | } | 200 | } |
201 | 201 | ||
202 | /** | 202 | /** |
203 | * subscr_del - delete a subscription within a subscription list | 203 | * subscr_del - delete a subscription within a subscription list |
204 | * | 204 | * |
205 | * Called with subscriber port locked. | 205 | * Called with subscriber port locked. |
206 | */ | 206 | */ |
207 | 207 | ||
208 | static void subscr_del(struct subscription *sub) | 208 | static void subscr_del(struct subscription *sub) |
209 | { | 209 | { |
210 | tipc_nametbl_unsubscribe(sub); | 210 | tipc_nametbl_unsubscribe(sub); |
211 | list_del(&sub->subscription_list); | 211 | list_del(&sub->subscription_list); |
212 | kfree(sub); | 212 | kfree(sub); |
213 | atomic_dec(&topsrv.subscription_count); | 213 | atomic_dec(&topsrv.subscription_count); |
214 | } | 214 | } |
215 | 215 | ||
216 | /** | 216 | /** |
217 | * subscr_terminate - terminate communication with a subscriber | 217 | * subscr_terminate - terminate communication with a subscriber |
218 | * | 218 | * |
219 | * Called with subscriber port locked. Routine must temporarily release lock | 219 | * Called with subscriber port locked. Routine must temporarily release lock |
220 | * to enable subscription timeout routine(s) to finish without deadlocking; | 220 | * to enable subscription timeout routine(s) to finish without deadlocking; |
221 | * the lock is then reclaimed to allow caller to release it upon return. | 221 | * the lock is then reclaimed to allow caller to release it upon return. |
222 | * (This should work even in the unlikely event some other thread creates | 222 | * (This should work even in the unlikely event some other thread creates |
223 | * a new object reference in the interim that uses this lock; this routine will | 223 | * a new object reference in the interim that uses this lock; this routine will |
224 | * simply wait for it to be released, then claim it.) | 224 | * simply wait for it to be released, then claim it.) |
225 | */ | 225 | */ |
226 | 226 | ||
227 | static void subscr_terminate(struct subscriber *subscriber) | 227 | static void subscr_terminate(struct subscriber *subscriber) |
228 | { | 228 | { |
229 | u32 port_ref; | 229 | u32 port_ref; |
230 | struct subscription *sub; | 230 | struct subscription *sub; |
231 | struct subscription *sub_temp; | 231 | struct subscription *sub_temp; |
232 | 232 | ||
233 | /* Invalidate subscriber reference */ | 233 | /* Invalidate subscriber reference */ |
234 | 234 | ||
235 | port_ref = subscriber->port_ref; | 235 | port_ref = subscriber->port_ref; |
236 | subscriber->port_ref = 0; | 236 | subscriber->port_ref = 0; |
237 | spin_unlock_bh(subscriber->lock); | 237 | spin_unlock_bh(subscriber->lock); |
238 | 238 | ||
239 | /* Sever connection to subscriber */ | 239 | /* Sever connection to subscriber */ |
240 | 240 | ||
241 | tipc_shutdown(port_ref); | 241 | tipc_shutdown(port_ref); |
242 | tipc_deleteport(port_ref); | 242 | tipc_deleteport(port_ref); |
243 | 243 | ||
244 | /* Destroy any existing subscriptions for subscriber */ | 244 | /* Destroy any existing subscriptions for subscriber */ |
245 | 245 | ||
246 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | 246 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, |
247 | subscription_list) { | 247 | subscription_list) { |
248 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 248 | if (sub->timeout != TIPC_WAIT_FOREVER) { |
249 | k_cancel_timer(&sub->timer); | 249 | k_cancel_timer(&sub->timer); |
250 | k_term_timer(&sub->timer); | 250 | k_term_timer(&sub->timer); |
251 | } | 251 | } |
252 | dbg("Term: Removing sub %u,%u,%u from subscriber %x list\n", | 252 | dbg("Term: Removing sub %u,%u,%u from subscriber %x list\n", |
253 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); | 253 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); |
254 | subscr_del(sub); | 254 | subscr_del(sub); |
255 | } | 255 | } |
256 | 256 | ||
257 | /* Remove subscriber from topology server's subscriber list */ | 257 | /* Remove subscriber from topology server's subscriber list */ |
258 | 258 | ||
259 | spin_lock_bh(&topsrv.lock); | 259 | spin_lock_bh(&topsrv.lock); |
260 | list_del(&subscriber->subscriber_list); | 260 | list_del(&subscriber->subscriber_list); |
261 | spin_unlock_bh(&topsrv.lock); | 261 | spin_unlock_bh(&topsrv.lock); |
262 | 262 | ||
263 | /* Reclaim subscriber lock */ | 263 | /* Reclaim subscriber lock */ |
264 | 264 | ||
265 | spin_lock_bh(subscriber->lock); | 265 | spin_lock_bh(subscriber->lock); |
266 | 266 | ||
267 | /* Now destroy subscriber */ | 267 | /* Now destroy subscriber */ |
268 | 268 | ||
269 | kfree(subscriber); | 269 | kfree(subscriber); |
270 | } | 270 | } |
271 | 271 | ||
272 | /** | 272 | /** |
273 | * subscr_cancel - handle subscription cancellation request | 273 | * subscr_cancel - handle subscription cancellation request |
274 | * | 274 | * |
275 | * Called with subscriber port locked. Routine must temporarily release lock | 275 | * Called with subscriber port locked. Routine must temporarily release lock |
276 | * to enable the subscription timeout routine to finish without deadlocking; | 276 | * to enable the subscription timeout routine to finish without deadlocking; |
277 | * the lock is then reclaimed to allow caller to release it upon return. | 277 | * the lock is then reclaimed to allow caller to release it upon return. |
278 | * | 278 | * |
279 | * Note that fields of 's' use subscriber's endianness! | 279 | * Note that fields of 's' use subscriber's endianness! |
280 | */ | 280 | */ |
281 | 281 | ||
282 | static void subscr_cancel(struct tipc_subscr *s, | 282 | static void subscr_cancel(struct tipc_subscr *s, |
283 | struct subscriber *subscriber) | 283 | struct subscriber *subscriber) |
284 | { | 284 | { |
285 | struct subscription *sub; | 285 | struct subscription *sub; |
286 | struct subscription *sub_temp; | 286 | struct subscription *sub_temp; |
287 | int found = 0; | 287 | int found = 0; |
288 | 288 | ||
289 | /* Find first matching subscription, exit if not found */ | 289 | /* Find first matching subscription, exit if not found */ |
290 | 290 | ||
291 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | 291 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, |
292 | subscription_list) { | 292 | subscription_list) { |
293 | if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { | 293 | if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { |
294 | found = 1; | 294 | found = 1; |
295 | break; | 295 | break; |
296 | } | 296 | } |
297 | } | 297 | } |
298 | if (!found) | 298 | if (!found) |
299 | return; | 299 | return; |
300 | 300 | ||
301 | /* Cancel subscription timer (if used), then delete subscription */ | 301 | /* Cancel subscription timer (if used), then delete subscription */ |
302 | 302 | ||
303 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 303 | if (sub->timeout != TIPC_WAIT_FOREVER) { |
304 | sub->timeout = TIPC_WAIT_FOREVER; | 304 | sub->timeout = TIPC_WAIT_FOREVER; |
305 | spin_unlock_bh(subscriber->lock); | 305 | spin_unlock_bh(subscriber->lock); |
306 | k_cancel_timer(&sub->timer); | 306 | k_cancel_timer(&sub->timer); |
307 | k_term_timer(&sub->timer); | 307 | k_term_timer(&sub->timer); |
308 | spin_lock_bh(subscriber->lock); | 308 | spin_lock_bh(subscriber->lock); |
309 | } | 309 | } |
310 | dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n", | 310 | dbg("Cancel: removing sub %u,%u,%u from subscriber %x list\n", |
311 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); | 311 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); |
312 | subscr_del(sub); | 312 | subscr_del(sub); |
313 | } | 313 | } |
314 | 314 | ||
315 | /** | 315 | /** |
316 | * subscr_subscribe - create subscription for subscriber | 316 | * subscr_subscribe - create subscription for subscriber |
317 | * | 317 | * |
318 | * Called with subscriber port locked. | 318 | * Called with subscriber port locked. |
319 | */ | 319 | */ |
320 | 320 | ||
321 | static struct subscription *subscr_subscribe(struct tipc_subscr *s, | 321 | static struct subscription *subscr_subscribe(struct tipc_subscr *s, |
322 | struct subscriber *subscriber) | 322 | struct subscriber *subscriber) |
323 | { | 323 | { |
324 | struct subscription *sub; | 324 | struct subscription *sub; |
325 | int swap; | 325 | int swap; |
326 | 326 | ||
327 | /* Determine subscriber's endianness */ | 327 | /* Determine subscriber's endianness */ |
328 | 328 | ||
329 | swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)); | 329 | swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)); |
330 | 330 | ||
331 | /* Detect & process a subscription cancellation request */ | 331 | /* Detect & process a subscription cancellation request */ |
332 | 332 | ||
333 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { | 333 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { |
334 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); | 334 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); |
335 | subscr_cancel(s, subscriber); | 335 | subscr_cancel(s, subscriber); |
336 | return NULL; | 336 | return NULL; |
337 | } | 337 | } |
338 | 338 | ||
339 | /* Refuse subscription if global limit exceeded */ | 339 | /* Refuse subscription if global limit exceeded */ |
340 | 340 | ||
341 | if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { | 341 | if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { |
342 | warn("Subscription rejected, subscription limit reached (%u)\n", | 342 | warn("Subscription rejected, subscription limit reached (%u)\n", |
343 | tipc_max_subscriptions); | 343 | tipc_max_subscriptions); |
344 | subscr_terminate(subscriber); | 344 | subscr_terminate(subscriber); |
345 | return NULL; | 345 | return NULL; |
346 | } | 346 | } |
347 | 347 | ||
348 | /* Allocate subscription object */ | 348 | /* Allocate subscription object */ |
349 | 349 | ||
350 | sub = kmalloc(sizeof(*sub), GFP_ATOMIC); | 350 | sub = kmalloc(sizeof(*sub), GFP_ATOMIC); |
351 | if (!sub) { | 351 | if (!sub) { |
352 | warn("Subscription rejected, no memory\n"); | 352 | warn("Subscription rejected, no memory\n"); |
353 | subscr_terminate(subscriber); | 353 | subscr_terminate(subscriber); |
354 | return NULL; | 354 | return NULL; |
355 | } | 355 | } |
356 | 356 | ||
357 | /* Initialize subscription object */ | 357 | /* Initialize subscription object */ |
358 | 358 | ||
359 | sub->seq.type = htohl(s->seq.type, swap); | 359 | sub->seq.type = htohl(s->seq.type, swap); |
360 | sub->seq.lower = htohl(s->seq.lower, swap); | 360 | sub->seq.lower = htohl(s->seq.lower, swap); |
361 | sub->seq.upper = htohl(s->seq.upper, swap); | 361 | sub->seq.upper = htohl(s->seq.upper, swap); |
362 | sub->timeout = htohl(s->timeout, swap); | 362 | sub->timeout = htohl(s->timeout, swap); |
363 | sub->filter = htohl(s->filter, swap); | 363 | sub->filter = htohl(s->filter, swap); |
364 | if ((!(sub->filter & TIPC_SUB_PORTS) == | 364 | if ((!(sub->filter & TIPC_SUB_PORTS) == |
365 | !(sub->filter & TIPC_SUB_SERVICE)) || | 365 | !(sub->filter & TIPC_SUB_SERVICE)) || |
366 | (sub->seq.lower > sub->seq.upper)) { | 366 | (sub->seq.lower > sub->seq.upper)) { |
367 | warn("Subscription rejected, illegal request\n"); | 367 | warn("Subscription rejected, illegal request\n"); |
368 | kfree(sub); | 368 | kfree(sub); |
369 | subscr_terminate(subscriber); | 369 | subscr_terminate(subscriber); |
370 | return NULL; | 370 | return NULL; |
371 | } | 371 | } |
372 | sub->event_cb = subscr_send_event; | 372 | sub->event_cb = subscr_send_event; |
373 | INIT_LIST_HEAD(&sub->nameseq_list); | 373 | INIT_LIST_HEAD(&sub->nameseq_list); |
374 | list_add(&sub->subscription_list, &subscriber->subscription_list); | 374 | list_add(&sub->subscription_list, &subscriber->subscription_list); |
375 | sub->server_ref = subscriber->port_ref; | 375 | sub->server_ref = subscriber->port_ref; |
376 | sub->swap = swap; | 376 | sub->swap = swap; |
377 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); | 377 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); |
378 | atomic_inc(&topsrv.subscription_count); | 378 | atomic_inc(&topsrv.subscription_count); |
379 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 379 | if (sub->timeout != TIPC_WAIT_FOREVER) { |
380 | k_init_timer(&sub->timer, | 380 | k_init_timer(&sub->timer, |
381 | (Handler)subscr_timeout, (unsigned long)sub); | 381 | (Handler)subscr_timeout, (unsigned long)sub); |
382 | k_start_timer(&sub->timer, sub->timeout); | 382 | k_start_timer(&sub->timer, sub->timeout); |
383 | } | 383 | } |
384 | 384 | ||
385 | return sub; | 385 | return sub; |
386 | } | 386 | } |
387 | 387 | ||
388 | /** | 388 | /** |
389 | * subscr_conn_shutdown_event - handle termination request from subscriber | 389 | * subscr_conn_shutdown_event - handle termination request from subscriber |
390 | * | 390 | * |
391 | * Called with subscriber's server port unlocked. | 391 | * Called with subscriber's server port unlocked. |
392 | */ | 392 | */ |
393 | 393 | ||
394 | static void subscr_conn_shutdown_event(void *usr_handle, | 394 | static void subscr_conn_shutdown_event(void *usr_handle, |
395 | u32 port_ref, | 395 | u32 port_ref, |
396 | struct sk_buff **buf, | 396 | struct sk_buff **buf, |
397 | unsigned char const *data, | 397 | unsigned char const *data, |
398 | unsigned int size, | 398 | unsigned int size, |
399 | int reason) | 399 | int reason) |
400 | { | 400 | { |
401 | struct subscriber *subscriber = usr_handle; | 401 | struct subscriber *subscriber = usr_handle; |
402 | spinlock_t *subscriber_lock; | 402 | spinlock_t *subscriber_lock; |
403 | 403 | ||
404 | if (tipc_port_lock(port_ref) == NULL) | 404 | if (tipc_port_lock(port_ref) == NULL) |
405 | return; | 405 | return; |
406 | 406 | ||
407 | subscriber_lock = subscriber->lock; | 407 | subscriber_lock = subscriber->lock; |
408 | subscr_terminate(subscriber); | 408 | subscr_terminate(subscriber); |
409 | spin_unlock_bh(subscriber_lock); | 409 | spin_unlock_bh(subscriber_lock); |
410 | } | 410 | } |
411 | 411 | ||
412 | /** | 412 | /** |
413 | * subscr_conn_msg_event - handle new subscription request from subscriber | 413 | * subscr_conn_msg_event - handle new subscription request from subscriber |
414 | * | 414 | * |
415 | * Called with subscriber's server port unlocked. | 415 | * Called with subscriber's server port unlocked. |
416 | */ | 416 | */ |
417 | 417 | ||
418 | static void subscr_conn_msg_event(void *usr_handle, | 418 | static void subscr_conn_msg_event(void *usr_handle, |
419 | u32 port_ref, | 419 | u32 port_ref, |
420 | struct sk_buff **buf, | 420 | struct sk_buff **buf, |
421 | const unchar *data, | 421 | const unchar *data, |
422 | u32 size) | 422 | u32 size) |
423 | { | 423 | { |
424 | struct subscriber *subscriber = usr_handle; | 424 | struct subscriber *subscriber = usr_handle; |
425 | spinlock_t *subscriber_lock; | 425 | spinlock_t *subscriber_lock; |
426 | struct subscription *sub; | 426 | struct subscription *sub; |
427 | 427 | ||
428 | /* | 428 | /* |
429 | * Lock subscriber's server port (& make a local copy of lock pointer, | 429 | * Lock subscriber's server port (& make a local copy of lock pointer, |
430 | * in case subscriber is deleted while processing subscription request) | 430 | * in case subscriber is deleted while processing subscription request) |
431 | */ | 431 | */ |
432 | 432 | ||
433 | if (tipc_port_lock(port_ref) == NULL) | 433 | if (tipc_port_lock(port_ref) == NULL) |
434 | return; | 434 | return; |
435 | 435 | ||
436 | subscriber_lock = subscriber->lock; | 436 | subscriber_lock = subscriber->lock; |
437 | 437 | ||
438 | if (size != sizeof(struct tipc_subscr)) { | 438 | if (size != sizeof(struct tipc_subscr)) { |
439 | subscr_terminate(subscriber); | 439 | subscr_terminate(subscriber); |
440 | spin_unlock_bh(subscriber_lock); | 440 | spin_unlock_bh(subscriber_lock); |
441 | } else { | 441 | } else { |
442 | sub = subscr_subscribe((struct tipc_subscr *)data, subscriber); | 442 | sub = subscr_subscribe((struct tipc_subscr *)data, subscriber); |
443 | spin_unlock_bh(subscriber_lock); | 443 | spin_unlock_bh(subscriber_lock); |
444 | if (sub != NULL) { | 444 | if (sub != NULL) { |
445 | 445 | ||
446 | /* | 446 | /* |
447 | * We must release the server port lock before adding a | 447 | * We must release the server port lock before adding a |
448 | * subscription to the name table since TIPC needs to be | 448 | * subscription to the name table since TIPC needs to be |
449 | * able to (re)acquire the port lock if an event message | 449 | * able to (re)acquire the port lock if an event message |
450 | * issued by the subscription process is rejected and | 450 | * issued by the subscription process is rejected and |
451 | * returned. The subscription cannot be deleted while | 451 | * returned. The subscription cannot be deleted while |
452 | * it is being added to the name table because: | 452 | * it is being added to the name table because: |
453 | * a) the single-threading of the native API port code | 453 | * a) the single-threading of the native API port code |
454 | * ensures the subscription cannot be cancelled and | 454 | * ensures the subscription cannot be cancelled and |
455 | * the subscriber connection cannot be broken, and | 455 | * the subscriber connection cannot be broken, and |
456 | * b) the name table lock ensures the subscription | 456 | * b) the name table lock ensures the subscription |
457 | * timeout code cannot delete the subscription, | 457 | * timeout code cannot delete the subscription, |
458 | * so the subscription object is still protected. | 458 | * so the subscription object is still protected. |
459 | */ | 459 | */ |
460 | 460 | ||
461 | tipc_nametbl_subscribe(sub); | 461 | tipc_nametbl_subscribe(sub); |
462 | } | 462 | } |
463 | } | 463 | } |
464 | } | 464 | } |
465 | 465 | ||
466 | /** | 466 | /** |
467 | * subscr_named_msg_event - handle request to establish a new subscriber | 467 | * subscr_named_msg_event - handle request to establish a new subscriber |
468 | */ | 468 | */ |
469 | 469 | ||
470 | static void subscr_named_msg_event(void *usr_handle, | 470 | static void subscr_named_msg_event(void *usr_handle, |
471 | u32 port_ref, | 471 | u32 port_ref, |
472 | struct sk_buff **buf, | 472 | struct sk_buff **buf, |
473 | const unchar *data, | 473 | const unchar *data, |
474 | u32 size, | 474 | u32 size, |
475 | u32 importance, | 475 | u32 importance, |
476 | struct tipc_portid const *orig, | 476 | struct tipc_portid const *orig, |
477 | struct tipc_name_seq const *dest) | 477 | struct tipc_name_seq const *dest) |
478 | { | 478 | { |
479 | static struct iovec msg_sect = {NULL, 0}; | 479 | static struct iovec msg_sect = {NULL, 0}; |
480 | 480 | ||
481 | struct subscriber *subscriber; | 481 | struct subscriber *subscriber; |
482 | u32 server_port_ref; | 482 | u32 server_port_ref; |
483 | 483 | ||
484 | /* Create subscriber object */ | 484 | /* Create subscriber object */ |
485 | 485 | ||
486 | subscriber = kzalloc(sizeof(struct subscriber), GFP_ATOMIC); | 486 | subscriber = kzalloc(sizeof(struct subscriber), GFP_ATOMIC); |
487 | if (subscriber == NULL) { | 487 | if (subscriber == NULL) { |
488 | warn("Subscriber rejected, no memory\n"); | 488 | warn("Subscriber rejected, no memory\n"); |
489 | return; | 489 | return; |
490 | } | 490 | } |
491 | INIT_LIST_HEAD(&subscriber->subscription_list); | 491 | INIT_LIST_HEAD(&subscriber->subscription_list); |
492 | INIT_LIST_HEAD(&subscriber->subscriber_list); | 492 | INIT_LIST_HEAD(&subscriber->subscriber_list); |
493 | 493 | ||
494 | /* Create server port & establish connection to subscriber */ | 494 | /* Create server port & establish connection to subscriber */ |
495 | 495 | ||
496 | tipc_createport(0, | 496 | tipc_createport(subscriber, |
497 | subscriber, | ||
498 | importance, | 497 | importance, |
499 | NULL, | 498 | NULL, |
500 | NULL, | 499 | NULL, |
501 | subscr_conn_shutdown_event, | 500 | subscr_conn_shutdown_event, |
502 | NULL, | 501 | NULL, |
503 | NULL, | 502 | NULL, |
504 | subscr_conn_msg_event, | 503 | subscr_conn_msg_event, |
505 | NULL, | 504 | NULL, |
506 | &subscriber->port_ref); | 505 | &subscriber->port_ref); |
507 | if (subscriber->port_ref == 0) { | 506 | if (subscriber->port_ref == 0) { |
508 | warn("Subscriber rejected, unable to create port\n"); | 507 | warn("Subscriber rejected, unable to create port\n"); |
509 | kfree(subscriber); | 508 | kfree(subscriber); |
510 | return; | 509 | return; |
511 | } | 510 | } |
512 | tipc_connect2port(subscriber->port_ref, orig); | 511 | tipc_connect2port(subscriber->port_ref, orig); |
513 | 512 | ||
514 | /* Lock server port (& save lock address for future use) */ | 513 | /* Lock server port (& save lock address for future use) */ |
515 | 514 | ||
516 | subscriber->lock = tipc_port_lock(subscriber->port_ref)->publ.lock; | 515 | subscriber->lock = tipc_port_lock(subscriber->port_ref)->publ.lock; |
517 | 516 | ||
518 | /* Add subscriber to topology server's subscriber list */ | 517 | /* Add subscriber to topology server's subscriber list */ |
519 | 518 | ||
520 | spin_lock_bh(&topsrv.lock); | 519 | spin_lock_bh(&topsrv.lock); |
521 | list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); | 520 | list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); |
522 | spin_unlock_bh(&topsrv.lock); | 521 | spin_unlock_bh(&topsrv.lock); |
523 | 522 | ||
524 | /* Unlock server port */ | 523 | /* Unlock server port */ |
525 | 524 | ||
526 | server_port_ref = subscriber->port_ref; | 525 | server_port_ref = subscriber->port_ref; |
527 | spin_unlock_bh(subscriber->lock); | 526 | spin_unlock_bh(subscriber->lock); |
528 | 527 | ||
529 | /* Send an ACK- to complete connection handshaking */ | 528 | /* Send an ACK- to complete connection handshaking */ |
530 | 529 | ||
531 | tipc_send(server_port_ref, 1, &msg_sect); | 530 | tipc_send(server_port_ref, 1, &msg_sect); |
532 | 531 | ||
533 | /* Handle optional subscription request */ | 532 | /* Handle optional subscription request */ |
534 | 533 | ||
535 | if (size != 0) { | 534 | if (size != 0) { |
536 | subscr_conn_msg_event(subscriber, server_port_ref, | 535 | subscr_conn_msg_event(subscriber, server_port_ref, |
537 | buf, data, size); | 536 | buf, data, size); |
538 | } | 537 | } |
539 | } | 538 | } |
540 | 539 | ||
541 | int tipc_subscr_start(void) | 540 | int tipc_subscr_start(void) |
542 | { | 541 | { |
543 | struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV}; | 542 | struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV}; |
544 | int res; | 543 | int res; |
545 | 544 | ||
546 | memset(&topsrv, 0, sizeof (topsrv)); | 545 | memset(&topsrv, 0, sizeof (topsrv)); |
547 | spin_lock_init(&topsrv.lock); | 546 | spin_lock_init(&topsrv.lock); |
548 | INIT_LIST_HEAD(&topsrv.subscriber_list); | 547 | INIT_LIST_HEAD(&topsrv.subscriber_list); |
549 | 548 | ||
550 | spin_lock_bh(&topsrv.lock); | 549 | spin_lock_bh(&topsrv.lock); |
551 | res = tipc_createport(0, | 550 | res = tipc_createport(NULL, |
552 | NULL, | ||
553 | TIPC_CRITICAL_IMPORTANCE, | 551 | TIPC_CRITICAL_IMPORTANCE, |
554 | NULL, | 552 | NULL, |
555 | NULL, | 553 | NULL, |
556 | NULL, | 554 | NULL, |
557 | NULL, | 555 | NULL, |
558 | subscr_named_msg_event, | 556 | subscr_named_msg_event, |
559 | NULL, | 557 | NULL, |
560 | NULL, | 558 | NULL, |
561 | &topsrv.setup_port); | 559 | &topsrv.setup_port); |
562 | if (res) | 560 | if (res) |
563 | goto failed; | 561 | goto failed; |
564 | 562 | ||
565 | res = tipc_nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); | 563 | res = tipc_nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); |
566 | if (res) { | 564 | if (res) { |
567 | tipc_deleteport(topsrv.setup_port); | 565 | tipc_deleteport(topsrv.setup_port); |
568 | topsrv.setup_port = 0; | 566 | topsrv.setup_port = 0; |
569 | goto failed; | 567 | goto failed; |
570 | } | 568 | } |
571 | 569 | ||
572 | spin_unlock_bh(&topsrv.lock); | 570 | spin_unlock_bh(&topsrv.lock); |
573 | return 0; | 571 | return 0; |
574 | 572 | ||
575 | failed: | 573 | failed: |
576 | err("Failed to create subscription service\n"); | 574 | err("Failed to create subscription service\n"); |
577 | spin_unlock_bh(&topsrv.lock); | 575 | spin_unlock_bh(&topsrv.lock); |
578 | return res; | 576 | return res; |
579 | } | 577 | } |
580 | 578 | ||
581 | void tipc_subscr_stop(void) | 579 | void tipc_subscr_stop(void) |
582 | { | 580 | { |
583 | struct subscriber *subscriber; | 581 | struct subscriber *subscriber; |
584 | struct subscriber *subscriber_temp; | 582 | struct subscriber *subscriber_temp; |
585 | spinlock_t *subscriber_lock; | 583 | spinlock_t *subscriber_lock; |
586 | 584 | ||
587 | if (topsrv.setup_port) { | 585 | if (topsrv.setup_port) { |
588 | tipc_deleteport(topsrv.setup_port); | 586 | tipc_deleteport(topsrv.setup_port); |
589 | topsrv.setup_port = 0; | 587 | topsrv.setup_port = 0; |
590 | 588 | ||
591 | list_for_each_entry_safe(subscriber, subscriber_temp, | 589 | list_for_each_entry_safe(subscriber, subscriber_temp, |
592 | &topsrv.subscriber_list, | 590 | &topsrv.subscriber_list, |
593 | subscriber_list) { | 591 | subscriber_list) { |
594 | subscriber_lock = subscriber->lock; | 592 | subscriber_lock = subscriber->lock; |
595 | spin_lock_bh(subscriber_lock); | 593 | spin_lock_bh(subscriber_lock); |
596 | subscr_terminate(subscriber); | 594 | subscr_terminate(subscriber); |
597 | spin_unlock_bh(subscriber_lock); | 595 | spin_unlock_bh(subscriber_lock); |
598 | } | 596 | } |
599 | } | 597 | } |
600 | } | 598 | } |
601 | 599 |
net/tipc/user_reg.c
1 | /* | File was deleted | |
2 | * net/tipc/user_reg.c: TIPC user registry code | ||
3 | * | ||
4 | * Copyright (c) 2000-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 "user_reg.h" | ||
39 | |||
40 | /* | ||
41 | * TIPC user registry keeps track of users of the tipc_port interface. | ||
42 | * | ||
43 | * The registry utilizes an array of "TIPC user" entries; | ||
44 | * a user's ID is the index of their associated array entry. | ||
45 | * Array entry 0 is not used, so userid 0 is not valid; | ||
46 | * TIPC sometimes uses this value to denote an anonymous user. | ||
47 | * The list of free entries is initially chained from last entry to entry 1. | ||
48 | */ | ||
49 | |||
50 | /** | ||
51 | * struct tipc_user - registered TIPC user info | ||
52 | * @next: index of next free registry entry (or -1 for an allocated entry) | ||
53 | * @ports: list of user ports owned by the user | ||
54 | */ | ||
55 | |||
56 | struct tipc_user { | ||
57 | int next; | ||
58 | struct list_head ports; | ||
59 | }; | ||
60 | |||
61 | #define MAX_USERID 64 | ||
62 | #define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user)) | ||
63 | |||
64 | static struct tipc_user *users = NULL; | ||
65 | static u32 next_free_user = MAX_USERID + 1; | ||
66 | static DEFINE_SPINLOCK(reg_lock); | ||
67 | |||
68 | /** | ||
69 | * reg_init - create TIPC user registry (but don't activate it) | ||
70 | * | ||
71 | * If registry has been pre-initialized it is left "as is". | ||
72 | * NOTE: This routine may be called when TIPC is inactive. | ||
73 | */ | ||
74 | |||
75 | static int reg_init(void) | ||
76 | { | ||
77 | u32 i; | ||
78 | |||
79 | spin_lock_bh(®_lock); | ||
80 | if (!users) { | ||
81 | users = kzalloc(USER_LIST_SIZE, GFP_ATOMIC); | ||
82 | if (users) { | ||
83 | for (i = 1; i <= MAX_USERID; i++) { | ||
84 | users[i].next = i - 1; | ||
85 | } | ||
86 | next_free_user = MAX_USERID; | ||
87 | } | ||
88 | } | ||
89 | spin_unlock_bh(®_lock); | ||
90 | return users ? 0 : -ENOMEM; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * tipc_reg_start - activate TIPC user registry | ||
95 | */ | ||
96 | |||
97 | int tipc_reg_start(void) | ||
98 | { | ||
99 | return reg_init(); | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * tipc_reg_stop - shut down & delete TIPC user registry | ||
104 | */ | ||
105 | |||
106 | void tipc_reg_stop(void) | ||
107 | { | ||
108 | if (!users) | ||
109 | return; | ||
110 | |||
111 | kfree(users); | ||
112 | users = NULL; | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * tipc_attach - register a TIPC user | ||
117 | * | ||
118 | * NOTE: This routine may be called when TIPC is inactive. | ||
119 | */ | ||
120 | |||
121 | int tipc_attach(u32 *userid) | ||
122 | { | ||
123 | struct tipc_user *user_ptr; | ||
124 | |||
125 | if (!users) | ||
126 | reg_init(); | ||
127 | |||
128 | spin_lock_bh(®_lock); | ||
129 | if (!next_free_user) { | ||
130 | spin_unlock_bh(®_lock); | ||
131 | return -EBUSY; | ||
132 | } | ||
133 | user_ptr = &users[next_free_user]; | ||
134 | *userid = next_free_user; | ||
135 | next_free_user = user_ptr->next; | ||
136 | user_ptr->next = -1; | ||
137 | spin_unlock_bh(®_lock); | ||
138 | |||
139 | INIT_LIST_HEAD(&user_ptr->ports); | ||
140 | atomic_inc(&tipc_user_count); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * tipc_detach - deregister a TIPC user | ||
147 | */ | ||
148 | |||
149 | void tipc_detach(u32 userid) | ||
150 | { | ||
151 | struct tipc_user *user_ptr; | ||
152 | struct list_head ports_temp; | ||
153 | struct user_port *up_ptr, *temp_up_ptr; | ||
154 | |||
155 | if ((userid == 0) || (userid > MAX_USERID)) | ||
156 | return; | ||
157 | |||
158 | spin_lock_bh(®_lock); | ||
159 | if ((!users) || (users[userid].next >= 0)) { | ||
160 | spin_unlock_bh(®_lock); | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | user_ptr = &users[userid]; | ||
165 | INIT_LIST_HEAD(&ports_temp); | ||
166 | list_splice(&user_ptr->ports, &ports_temp); | ||
167 | user_ptr->next = next_free_user; | ||
168 | next_free_user = userid; | ||
169 | spin_unlock_bh(®_lock); | ||
170 | |||
171 | atomic_dec(&tipc_user_count); | ||
172 | |||
173 | list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) { | ||
174 | tipc_deleteport(up_ptr->ref); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * tipc_reg_add_port - register a user's driver port | ||
180 | */ | ||
181 | |||
182 | int tipc_reg_add_port(struct user_port *up_ptr) | ||
183 | { | ||
184 | struct tipc_user *user_ptr; | ||
185 | |||
186 | if (up_ptr->user_ref == 0) | ||
187 | return 0; | ||
188 | if (up_ptr->user_ref > MAX_USERID) | ||
189 | return -EINVAL; | ||
190 | if ((tipc_mode == TIPC_NOT_RUNNING) || !users ) | ||
191 | return -ENOPROTOOPT; | ||
192 | |||
193 | spin_lock_bh(®_lock); | ||
194 | user_ptr = &users[up_ptr->user_ref]; | ||
195 | list_add(&up_ptr->uport_list, &user_ptr->ports); | ||
196 | spin_unlock_bh(®_lock); | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | /** | ||
201 | * tipc_reg_remove_port - deregister a user's driver port | ||
202 | */ | ||
203 | |||
204 | int tipc_reg_remove_port(struct user_port *up_ptr) | ||
205 | { | ||
206 | if (up_ptr->user_ref == 0) | ||
207 | return 0; | ||
208 | if (up_ptr->user_ref > MAX_USERID) | ||
209 | return -EINVAL; | ||
210 | if (!users ) | ||
211 | return -ENOPROTOOPT; | ||
212 | |||
213 | spin_lock_bh(®_lock); | ||
214 | list_del_init(&up_ptr->uport_list); | ||
215 | spin_unlock_bh(®_lock); | ||
216 | return 0; | ||
217 | } | ||
218 | 1 | /* | |
219 | 2 | * net/tipc/user_reg.c: TIPC user registry code |
net/tipc/user_reg.h
1 | /* | File was deleted | |
2 | * net/tipc/user_reg.h: Include file for TIPC user registry code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 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 | #ifndef _TIPC_USER_REG_H | ||
38 | #define _TIPC_USER_REG_H | ||
39 | |||
40 | #include "port.h" | ||
41 | |||
42 | int tipc_reg_start(void); | ||
43 | void tipc_reg_stop(void); | ||
44 | |||
45 | int tipc_attach(unsigned int *userref); | ||
46 | void tipc_detach(unsigned int userref); | ||
47 | |||
48 | int tipc_reg_add_port(struct user_port *up_ptr); | ||
49 | int tipc_reg_remove_port(struct user_port *up_ptr); | ||
50 | |||
51 | #endif | ||
52 | 1 | /* |