port.c 13 KB

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