tipc: clean up socket timer function
[deliverable/linux.git] / net / tipc / port.c
CommitLineData
b97bf3fd
PL
1/*
2 * net/tipc/port.c: TIPC port code
c4307285 3 *
8826cde6 4 * Copyright (c) 1992-2007, 2014, Ericsson AB
198d73b8 5 * Copyright (c) 2004-2008, 2010-2013, Wind River Systems
b97bf3fd
PL
6 * All rights reserved.
7 *
9ea1fd3c 8 * Redistribution and use in source and binary forms, with or without
b97bf3fd
PL
9 * modification, are permitted provided that the following conditions are met:
10 *
9ea1fd3c
PL
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.
b97bf3fd 19 *
9ea1fd3c
PL
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
b97bf3fd
PL
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "config.h"
b97bf3fd 39#include "port.h"
b97bf3fd 40#include "name_table.h"
8826cde6 41#include "socket.h"
b97bf3fd
PL
42
43/* Connection management: */
44#define PROBING_INTERVAL 3600000 /* [ms] => 1 h */
b97bf3fd
PL
45
46#define MAX_REJECT_SIZE 1024
47
34af946a 48DEFINE_SPINLOCK(tipc_port_list_lock);
b97bf3fd 49
4323add6 50static LIST_HEAD(ports);
b97bf3fd 51
2c53040f 52/**
f0712e86
AS
53 * tipc_port_peer_msg - verify message was sent by connected port's peer
54 *
55 * Handles cases where the node's network address has changed from
56 * the default of <0.0.0> to its configured setting.
57 */
f0712e86
AS
58int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg)
59{
60 u32 peernode;
61 u32 orignode;
62
f9fef18c 63 if (msg_origport(msg) != tipc_port_peerport(p_ptr))
f0712e86
AS
64 return 0;
65
66 orignode = msg_orignode(msg);
f9fef18c 67 peernode = tipc_port_peernode(p_ptr);
f0712e86
AS
68 return (orignode == peernode) ||
69 (!orignode && (peernode == tipc_own_addr)) ||
70 (!peernode && (orignode == tipc_own_addr));
71}
72
24be34b5 73/* tipc_port_init - intiate TIPC port and lock it
c4307285 74 *
24be34b5 75 * Returns obtained reference if initialization is successful, zero otherwise
b97bf3fd 76 */
24be34b5
JPM
77u32 tipc_port_init(struct tipc_port *p_ptr,
78 const unsigned int importance)
b97bf3fd 79{
b97bf3fd
PL
80 struct tipc_msg *msg;
81 u32 ref;
82
23dd4cce 83 ref = tipc_ref_acquire(p_ptr, &p_ptr->lock);
b97bf3fd 84 if (!ref) {
8826cde6 85 pr_warn("Port registration failed, ref. table exhausted\n");
24be34b5 86 return 0;
b97bf3fd
PL
87 }
88
23dd4cce
AS
89 p_ptr->max_pkt = MAX_PKT_DEFAULT;
90 p_ptr->ref = ref;
b97bf3fd 91 INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
b97bf3fd
PL
92 INIT_LIST_HEAD(&p_ptr->publications);
93 INIT_LIST_HEAD(&p_ptr->port_list);
f21536d1
AS
94
95 /*
96 * Must hold port list lock while initializing message header template
97 * to ensure a change to node's own network address doesn't result
98 * in template containing out-dated network address information
99 */
f21536d1
AS
100 spin_lock_bh(&tipc_port_list_lock);
101 msg = &p_ptr->phdr;
102 tipc_msg_init(msg, importance, TIPC_NAMED_MSG, NAMED_H_SIZE, 0);
103 msg_set_origport(msg, ref);
b97bf3fd 104 list_add_tail(&p_ptr->port_list, &ports);
4323add6 105 spin_unlock_bh(&tipc_port_list_lock);
24be34b5 106 return ref;
b97bf3fd
PL
107}
108
24be34b5 109void tipc_port_destroy(struct tipc_port *p_ptr)
b97bf3fd 110{
1fc54d8f 111 struct sk_buff *buf = NULL;
b786e2b0 112 struct tipc_msg *msg = NULL;
57289015 113 u32 peer_node;
b97bf3fd 114
84602761 115 tipc_withdraw(p_ptr, 0, NULL);
b97bf3fd 116
84602761
YX
117 spin_lock_bh(p_ptr->lock);
118 tipc_ref_discard(p_ptr->ref);
119 spin_unlock_bh(p_ptr->lock);
b97bf3fd
PL
120
121 k_cancel_timer(&p_ptr->timer);
23dd4cce 122 if (p_ptr->connected) {
57289015
JPM
123 peer_node = tipc_port_peernode(p_ptr);
124 buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG,
125 SHORT_H_SIZE, 0, peer_node,
126 tipc_own_addr, tipc_port_peerport(p_ptr),
127 p_ptr->ref, TIPC_ERR_NO_PORT);
128 if (buf) {
129 msg = buf_msg(buf);
130 tipc_link_xmit(buf, peer_node, msg_link_selector(msg));
131 }
132 tipc_node_remove_conn(peer_node, p_ptr->ref);
b97bf3fd 133 }
4323add6 134 spin_lock_bh(&tipc_port_list_lock);
b97bf3fd 135 list_del(&p_ptr->port_list);
4323add6 136 spin_unlock_bh(&tipc_port_list_lock);
b97bf3fd 137 k_term_timer(&p_ptr->timer);
b97bf3fd
PL
138}
139
dc1aed37 140static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id)
b97bf3fd 141{
c4307285 142 struct publication *publ;
dc1aed37 143 int ret;
b97bf3fd
PL
144
145 if (full_id)
dc1aed37
EH
146 ret = tipc_snprintf(buf, len, "<%u.%u.%u:%u>:",
147 tipc_zone(tipc_own_addr),
148 tipc_cluster(tipc_own_addr),
149 tipc_node(tipc_own_addr), p_ptr->ref);
b97bf3fd 150 else
dc1aed37 151 ret = tipc_snprintf(buf, len, "%-10u:", p_ptr->ref);
b97bf3fd 152
23dd4cce 153 if (p_ptr->connected) {
f9fef18c
JPM
154 u32 dport = tipc_port_peerport(p_ptr);
155 u32 destnode = tipc_port_peernode(p_ptr);
c4307285 156
dc1aed37
EH
157 ret += tipc_snprintf(buf + ret, len - ret,
158 " connected to <%u.%u.%u:%u>",
159 tipc_zone(destnode),
160 tipc_cluster(destnode),
161 tipc_node(destnode), dport);
23dd4cce 162 if (p_ptr->conn_type != 0)
dc1aed37
EH
163 ret += tipc_snprintf(buf + ret, len - ret,
164 " via {%u,%u}", p_ptr->conn_type,
165 p_ptr->conn_instance);
23dd4cce 166 } else if (p_ptr->published) {
dc1aed37 167 ret += tipc_snprintf(buf + ret, len - ret, " bound to");
c4307285 168 list_for_each_entry(publ, &p_ptr->publications, pport_list) {
b97bf3fd 169 if (publ->lower == publ->upper)
dc1aed37
EH
170 ret += tipc_snprintf(buf + ret, len - ret,
171 " {%u,%u}", publ->type,
172 publ->lower);
b97bf3fd 173 else
dc1aed37
EH
174 ret += tipc_snprintf(buf + ret, len - ret,
175 " {%u,%u,%u}", publ->type,
176 publ->lower, publ->upper);
c4307285
YH
177 }
178 }
dc1aed37
EH
179 ret += tipc_snprintf(buf + ret, len - ret, "\n");
180 return ret;
b97bf3fd
PL
181}
182
4323add6 183struct sk_buff *tipc_port_get_ports(void)
b97bf3fd
PL
184{
185 struct sk_buff *buf;
186 struct tlv_desc *rep_tlv;
dc1aed37
EH
187 char *pb;
188 int pb_len;
23dd4cce 189 struct tipc_port *p_ptr;
dc1aed37 190 int str_len = 0;
b97bf3fd 191
dc1aed37 192 buf = tipc_cfg_reply_alloc(TLV_SPACE(ULTRA_STRING_MAX_LEN));
b97bf3fd
PL
193 if (!buf)
194 return NULL;
195 rep_tlv = (struct tlv_desc *)buf->data;
dc1aed37
EH
196 pb = TLV_DATA(rep_tlv);
197 pb_len = ULTRA_STRING_MAX_LEN;
b97bf3fd 198
4323add6 199 spin_lock_bh(&tipc_port_list_lock);
b97bf3fd 200 list_for_each_entry(p_ptr, &ports, port_list) {
23dd4cce 201 spin_lock_bh(p_ptr->lock);
dc1aed37 202 str_len += port_print(p_ptr, pb, pb_len, 0);
23dd4cce 203 spin_unlock_bh(p_ptr->lock);
b97bf3fd 204 }
4323add6 205 spin_unlock_bh(&tipc_port_list_lock);
dc1aed37 206 str_len += 1; /* for "\0" */
b97bf3fd
PL
207 skb_put(buf, TLV_SPACE(str_len));
208 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
209
210 return buf;
211}
212
4323add6 213void tipc_port_reinit(void)
b97bf3fd 214{
23dd4cce 215 struct tipc_port *p_ptr;
b97bf3fd
PL
216 struct tipc_msg *msg;
217
4323add6 218 spin_lock_bh(&tipc_port_list_lock);
b97bf3fd 219 list_for_each_entry(p_ptr, &ports, port_list) {
23dd4cce 220 msg = &p_ptr->phdr;
6d4a6672 221 msg_set_prevnode(msg, tipc_own_addr);
b97bf3fd
PL
222 msg_set_orignode(msg, tipc_own_addr);
223 }
4323add6 224 spin_unlock_bh(&tipc_port_list_lock);
b97bf3fd
PL
225}
226
b97bf3fd
PL
227void tipc_acknowledge(u32 ref, u32 ack)
228{
23dd4cce 229 struct tipc_port *p_ptr;
1fc54d8f 230 struct sk_buff *buf = NULL;
b786e2b0 231 struct tipc_msg *msg;
b97bf3fd 232
4323add6 233 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
234 if (!p_ptr)
235 return;
60120526 236 if (p_ptr->connected)
57289015
JPM
237 buf = tipc_msg_create(CONN_MANAGER, CONN_ACK, INT_H_SIZE,
238 0, tipc_port_peernode(p_ptr),
239 tipc_own_addr, tipc_port_peerport(p_ptr),
240 p_ptr->ref, TIPC_OK);
4323add6 241 tipc_port_unlock(p_ptr);
b786e2b0
JPM
242 if (!buf)
243 return;
244 msg = buf_msg(buf);
57289015 245 msg_set_msgcnt(msg, ack);
9fbfb8b1 246 tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg));
b97bf3fd
PL
247}
248
84602761
YX
249int tipc_publish(struct tipc_port *p_ptr, unsigned int scope,
250 struct tipc_name_seq const *seq)
b97bf3fd 251{
b97bf3fd
PL
252 struct publication *publ;
253 u32 key;
b97bf3fd 254
84602761 255 if (p_ptr->connected)
d55b4c63 256 return -EINVAL;
84602761
YX
257 key = p_ptr->ref + p_ptr->pub_count + 1;
258 if (key == p_ptr->ref)
259 return -EADDRINUSE;
d55b4c63 260
4323add6 261 publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
23dd4cce 262 scope, p_ptr->ref, key);
b97bf3fd
PL
263 if (publ) {
264 list_add(&publ->pport_list, &p_ptr->publications);
265 p_ptr->pub_count++;
23dd4cce 266 p_ptr->published = 1;
84602761 267 return 0;
b97bf3fd 268 }
84602761 269 return -EINVAL;
b97bf3fd
PL
270}
271
84602761
YX
272int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope,
273 struct tipc_name_seq const *seq)
b97bf3fd 274{
b97bf3fd
PL
275 struct publication *publ;
276 struct publication *tpubl;
277 int res = -EINVAL;
c4307285 278
b97bf3fd 279 if (!seq) {
c4307285 280 list_for_each_entry_safe(publ, tpubl,
b97bf3fd 281 &p_ptr->publications, pport_list) {
c4307285 282 tipc_nametbl_withdraw(publ->type, publ->lower,
4323add6 283 publ->ref, publ->key);
b97bf3fd 284 }
0e35fd5e 285 res = 0;
b97bf3fd 286 } else {
c4307285 287 list_for_each_entry_safe(publ, tpubl,
b97bf3fd
PL
288 &p_ptr->publications, pport_list) {
289 if (publ->scope != scope)
290 continue;
291 if (publ->type != seq->type)
292 continue;
293 if (publ->lower != seq->lower)
294 continue;
295 if (publ->upper != seq->upper)
296 break;
c4307285 297 tipc_nametbl_withdraw(publ->type, publ->lower,
4323add6 298 publ->ref, publ->key);
0e35fd5e 299 res = 0;
b97bf3fd
PL
300 break;
301 }
302 }
303 if (list_empty(&p_ptr->publications))
23dd4cce 304 p_ptr->published = 0;
b97bf3fd
PL
305 return res;
306}
307
247f0f3c 308int tipc_port_connect(u32 ref, struct tipc_portid const *peer)
b97bf3fd 309{
23dd4cce 310 struct tipc_port *p_ptr;
bc879117 311 int res;
b97bf3fd 312
4323add6 313 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
314 if (!p_ptr)
315 return -EINVAL;
247f0f3c 316 res = __tipc_port_connect(ref, p_ptr, peer);
bc879117
PG
317 tipc_port_unlock(p_ptr);
318 return res;
319}
320
321/*
247f0f3c 322 * __tipc_port_connect - connect to a remote peer
bc879117
PG
323 *
324 * Port must be locked.
325 */
247f0f3c 326int __tipc_port_connect(u32 ref, struct tipc_port *p_ptr,
bc879117
PG
327 struct tipc_portid const *peer)
328{
329 struct tipc_msg *msg;
330 int res = -EINVAL;
331
23dd4cce 332 if (p_ptr->published || p_ptr->connected)
b97bf3fd
PL
333 goto exit;
334 if (!peer->ref)
335 goto exit;
336
23dd4cce 337 msg = &p_ptr->phdr;
b97bf3fd
PL
338 msg_set_destnode(msg, peer->node);
339 msg_set_destport(msg, peer->ref);
b97bf3fd 340 msg_set_type(msg, TIPC_CONN_MSG);
53b94364 341 msg_set_lookup_scope(msg, 0);
08c80e9a 342 msg_set_hdr_sz(msg, SHORT_H_SIZE);
b97bf3fd
PL
343
344 p_ptr->probing_interval = PROBING_INTERVAL;
ac0074ee 345 p_ptr->probing_state = TIPC_CONN_OK;
23dd4cce 346 p_ptr->connected = 1;
b97bf3fd 347 k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
02be61a9
JPM
348 res = tipc_node_add_conn(tipc_port_peernode(p_ptr), p_ptr->ref,
349 tipc_port_peerport(p_ptr));
b97bf3fd 350exit:
4ccfe5e0 351 p_ptr->max_pkt = tipc_node_get_mtu(peer->node, ref);
b97bf3fd
PL
352 return res;
353}
354
bc879117
PG
355/*
356 * __tipc_disconnect - disconnect port from peer
0c3141e9
AS
357 *
358 * Port must be locked.
359 */
247f0f3c 360int __tipc_port_disconnect(struct tipc_port *tp_ptr)
0c3141e9 361{
0c3141e9
AS
362 if (tp_ptr->connected) {
363 tp_ptr->connected = 0;
364 /* let timer expire on it's own to avoid deadlock! */
02be61a9 365 tipc_node_remove_conn(tipc_port_peernode(tp_ptr), tp_ptr->ref);
0cee6bbe 366 return 0;
0c3141e9 367 }
0cee6bbe 368
369 return -ENOTCONN;
0c3141e9
AS
370}
371
b97bf3fd 372/*
247f0f3c 373 * tipc_port_disconnect(): Disconnect port form peer.
b97bf3fd
PL
374 * This is a node local operation.
375 */
247f0f3c 376int tipc_port_disconnect(u32 ref)
b97bf3fd 377{
23dd4cce 378 struct tipc_port *p_ptr;
0c3141e9 379 int res;
b97bf3fd 380
4323add6 381 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
382 if (!p_ptr)
383 return -EINVAL;
247f0f3c 384 res = __tipc_port_disconnect(p_ptr);
4323add6 385 tipc_port_unlock(p_ptr);
b97bf3fd
PL
386 return res;
387}
388
389/*
247f0f3c 390 * tipc_port_shutdown(): Send a SHUTDOWN msg to peer and disconnect
b97bf3fd 391 */
247f0f3c 392int tipc_port_shutdown(u32 ref)
b97bf3fd 393{
b786e2b0 394 struct tipc_msg *msg;
23dd4cce 395 struct tipc_port *p_ptr;
1fc54d8f 396 struct sk_buff *buf = NULL;
57289015 397 u32 peer_node;
b97bf3fd 398
4323add6 399 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
400 if (!p_ptr)
401 return -EINVAL;
57289015
JPM
402 peer_node = tipc_port_peernode(p_ptr);
403 buf = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG,
404 SHORT_H_SIZE, 0, peer_node,
405 tipc_own_addr, tipc_port_peerport(p_ptr),
406 p_ptr->ref, TIPC_CONN_SHUTDOWN);
4323add6 407 tipc_port_unlock(p_ptr);
b786e2b0 408 msg = buf_msg(buf);
57289015 409 tipc_link_xmit(buf, peer_node, msg_link_selector(msg));
247f0f3c 410 return tipc_port_disconnect(ref);
b97bf3fd 411}
This page took 0.701288 seconds and 5 git commands to generate.