aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2012-04-17 18:42:28 -0400
committerPaul Gortmaker <paul.gortmaker@windriver.com>2012-04-19 15:46:45 -0400
commitf0712e86b75f4839773abbc01d5baa7e36e378c2 (patch)
tree7f80147f312d1d7f683b4532d8669a831132246e /net/tipc
parentd0e17fedc2aeb0c4db09434787ef6d432582e050 (diff)
tipc: Ensure network address change doesn't impact local connections
Revises routines that deal with connections between two ports on the same node to ensure the connection is not impacted if the node's network address is changed in mid-operation. The routines now treat the default node address of <0.0.0> as an alias for "this node" in the following situations: 1) Incoming messages destined to a connected port now handle the alias properly when validating that the message was sent by the expected peer port, ensuring that the message will be accepted regardless of whether it specifies the node's old network address or it's current one. 2) The code which completes connection establishment now handles the alias properly when determining if the peer port is on the same node as the connected port. An added benefit of addressing issue 1) is that some peer port validation code has been relocated to TIPC's socket subsystem, which means that validation is no longer done twice when a message is sent to a non-socket port (such as TIPC's configuration service or network topology service). Signed-off-by: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/node_subscr.c2
-rw-r--r--net/tipc/port.c59
-rw-r--r--net/tipc/port.h1
-rw-r--r--net/tipc/socket.c3
4 files changed, 34 insertions, 31 deletions
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
index c3c2815ae630..327ffbbfee00 100644
--- a/net/tipc/node_subscr.c
+++ b/net/tipc/node_subscr.c
@@ -45,7 +45,7 @@
45void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr, 45void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr,
46 void *usr_handle, net_ev_handler handle_down) 46 void *usr_handle, net_ev_handler handle_down)
47{ 47{
48 if (addr == tipc_own_addr) { 48 if (in_own_node(addr)) {
49 node_sub->node = NULL; 49 node_sub->node = NULL;
50 return; 50 return;
51 } 51 }
diff --git a/net/tipc/port.c b/net/tipc/port.c
index f1f6b33f761c..616c72fb9234 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -69,6 +69,28 @@ static inline u32 port_peerport(struct tipc_port *p_ptr)
69 return msg_destport(&p_ptr->phdr); 69 return msg_destport(&p_ptr->phdr);
70} 70}
71 71
72/*
73 * tipc_port_peer_msg - verify message was sent by connected port's peer
74 *
75 * Handles cases where the node's network address has changed from
76 * the default of <0.0.0> to its configured setting.
77 */
78
79int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg)
80{
81 u32 peernode;
82 u32 orignode;
83
84 if (msg_origport(msg) != port_peerport(p_ptr))
85 return 0;
86
87 orignode = msg_orignode(msg);
88 peernode = port_peernode(p_ptr);
89 return (orignode == peernode) ||
90 (!orignode && (peernode == tipc_own_addr)) ||
91 (!peernode && (orignode == tipc_own_addr));
92}
93
72/** 94/**
73 * tipc_multicast - send a multicast message to local and remote destinations 95 * tipc_multicast - send a multicast message to local and remote destinations
74 */ 96 */
@@ -526,25 +548,21 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf)
526 struct tipc_msg *msg = buf_msg(buf); 548 struct tipc_msg *msg = buf_msg(buf);
527 struct tipc_port *p_ptr; 549 struct tipc_port *p_ptr;
528 struct sk_buff *r_buf = NULL; 550 struct sk_buff *r_buf = NULL;
529 u32 orignode = msg_orignode(msg);
530 u32 origport = msg_origport(msg);
531 u32 destport = msg_destport(msg); 551 u32 destport = msg_destport(msg);
532 int wakeable; 552 int wakeable;
533 553
534 /* Validate connection */ 554 /* Validate connection */
535 555
536 p_ptr = tipc_port_lock(destport); 556 p_ptr = tipc_port_lock(destport);
537 if (!p_ptr || !p_ptr->connected || 557 if (!p_ptr || !p_ptr->connected || !tipc_port_peer_msg(p_ptr, msg)) {
538 (port_peernode(p_ptr) != orignode) ||
539 (port_peerport(p_ptr) != origport)) {
540 r_buf = tipc_buf_acquire(BASIC_H_SIZE); 558 r_buf = tipc_buf_acquire(BASIC_H_SIZE);
541 if (r_buf) { 559 if (r_buf) {
542 msg = buf_msg(r_buf); 560 msg = buf_msg(r_buf);
543 tipc_msg_init(msg, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG, 561 tipc_msg_init(msg, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG,
544 BASIC_H_SIZE, orignode); 562 BASIC_H_SIZE, msg_orignode(msg));
545 msg_set_errcode(msg, TIPC_ERR_NO_PORT); 563 msg_set_errcode(msg, TIPC_ERR_NO_PORT);
546 msg_set_origport(msg, destport); 564 msg_set_origport(msg, destport);
547 msg_set_destport(msg, origport); 565 msg_set_destport(msg, msg_origport(msg));
548 } 566 }
549 if (p_ptr) 567 if (p_ptr)
550 tipc_port_unlock(p_ptr); 568 tipc_port_unlock(p_ptr);
@@ -681,6 +699,7 @@ static void port_dispatcher_sigh(void *dummy)
681 struct tipc_name_seq dseq; 699 struct tipc_name_seq dseq;
682 void *usr_handle; 700 void *usr_handle;
683 int connected; 701 int connected;
702 int peer_invalid;
684 int published; 703 int published;
685 u32 message_type; 704 u32 message_type;
686 705
@@ -701,6 +720,7 @@ static void port_dispatcher_sigh(void *dummy)
701 up_ptr = p_ptr->user_port; 720 up_ptr = p_ptr->user_port;
702 usr_handle = up_ptr->usr_handle; 721 usr_handle = up_ptr->usr_handle;
703 connected = p_ptr->connected; 722 connected = p_ptr->connected;
723 peer_invalid = connected && !tipc_port_peer_msg(p_ptr, msg);
704 published = p_ptr->published; 724 published = p_ptr->published;
705 725
706 if (unlikely(msg_errcode(msg))) 726 if (unlikely(msg_errcode(msg)))
@@ -710,8 +730,6 @@ static void port_dispatcher_sigh(void *dummy)
710 730
711 case TIPC_CONN_MSG:{ 731 case TIPC_CONN_MSG:{
712 tipc_conn_msg_event cb = up_ptr->conn_msg_cb; 732 tipc_conn_msg_event cb = up_ptr->conn_msg_cb;
713 u32 peer_port = port_peerport(p_ptr);
714 u32 peer_node = port_peernode(p_ptr);
715 u32 dsz; 733 u32 dsz;
716 734
717 tipc_port_unlock(p_ptr); 735 tipc_port_unlock(p_ptr);
@@ -720,8 +738,7 @@ static void port_dispatcher_sigh(void *dummy)
720 if (unlikely(!connected)) { 738 if (unlikely(!connected)) {
721 if (tipc_connect2port(dref, &orig)) 739 if (tipc_connect2port(dref, &orig))
722 goto reject; 740 goto reject;
723 } else if ((msg_origport(msg) != peer_port) || 741 } else if (peer_invalid)
724 (msg_orignode(msg) != peer_node))
725 goto reject; 742 goto reject;
726 dsz = msg_data_sz(msg); 743 dsz = msg_data_sz(msg);
727 if (unlikely(dsz && 744 if (unlikely(dsz &&
@@ -773,14 +790,9 @@ err:
773 case TIPC_CONN_MSG:{ 790 case TIPC_CONN_MSG:{
774 tipc_conn_shutdown_event cb = 791 tipc_conn_shutdown_event cb =
775 up_ptr->conn_err_cb; 792 up_ptr->conn_err_cb;
776 u32 peer_port = port_peerport(p_ptr);
777 u32 peer_node = port_peernode(p_ptr);
778 793
779 tipc_port_unlock(p_ptr); 794 tipc_port_unlock(p_ptr);
780 if (!cb || !connected) 795 if (!cb || !connected || peer_invalid)
781 break;
782 if ((msg_origport(msg) != peer_port) ||
783 (msg_orignode(msg) != peer_node))
784 break; 796 break;
785 tipc_disconnect(dref); 797 tipc_disconnect(dref);
786 skb_pull(buf, msg_hdr_sz(msg)); 798 skb_pull(buf, msg_hdr_sz(msg));
@@ -1157,17 +1169,6 @@ int tipc_port_recv_msg(struct sk_buff *buf)
1157 /* validate destination & pass to port, otherwise reject message */ 1169 /* validate destination & pass to port, otherwise reject message */
1158 p_ptr = tipc_port_lock(destport); 1170 p_ptr = tipc_port_lock(destport);
1159 if (likely(p_ptr)) { 1171 if (likely(p_ptr)) {
1160 if (likely(p_ptr->connected)) {
1161 if ((unlikely(msg_origport(msg) !=
1162 port_peerport(p_ptr))) ||
1163 (unlikely(msg_orignode(msg) !=
1164 port_peernode(p_ptr))) ||
1165 (unlikely(!msg_connected(msg)))) {
1166 err = TIPC_ERR_NO_PORT;
1167 tipc_port_unlock(p_ptr);
1168 goto reject;
1169 }
1170 }
1171 err = p_ptr->dispatcher(p_ptr, buf); 1172 err = p_ptr->dispatcher(p_ptr, buf);
1172 tipc_port_unlock(p_ptr); 1173 tipc_port_unlock(p_ptr);
1173 if (likely(!err)) 1174 if (likely(!err))
@@ -1175,7 +1176,7 @@ int tipc_port_recv_msg(struct sk_buff *buf)
1175 } else { 1176 } else {
1176 err = TIPC_ERR_NO_PORT; 1177 err = TIPC_ERR_NO_PORT;
1177 } 1178 }
1178reject: 1179
1179 return tipc_reject_msg(buf, err); 1180 return tipc_reject_msg(buf, err);
1180} 1181}
1181 1182
diff --git a/net/tipc/port.h b/net/tipc/port.h
index 0a632a6fc059..301e1bd840d1 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -201,6 +201,7 @@ int tipc_shutdown(u32 ref);
201 * The following routines require that the port be locked on entry 201 * The following routines require that the port be locked on entry
202 */ 202 */
203int tipc_disconnect_port(struct tipc_port *tp_ptr); 203int tipc_disconnect_port(struct tipc_port *tp_ptr);
204int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg);
204 205
205/* 206/*
206 * TIPC messaging routines 207 * TIPC messaging routines
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index bcb3314ef164..c19fc4a228a8 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1236,7 +1236,8 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
1236 if (msg_mcast(msg)) 1236 if (msg_mcast(msg))
1237 return TIPC_ERR_NO_PORT; 1237 return TIPC_ERR_NO_PORT;
1238 if (sock->state == SS_CONNECTED) { 1238 if (sock->state == SS_CONNECTED) {
1239 if (!msg_connected(msg)) 1239 if (!msg_connected(msg) ||
1240 !tipc_port_peer_msg(tipc_sk_port(sk), msg))
1240 return TIPC_ERR_NO_PORT; 1241 return TIPC_ERR_NO_PORT;
1241 } else if (sock->state == SS_CONNECTING) { 1242 } else if (sock->state == SS_CONNECTING) {
1242 if (!msg_connected(msg) && (msg_errcode(msg) == 0)) 1243 if (!msg_connected(msg) && (msg_errcode(msg) == 0))