aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/tipc/discover.c103
1 files changed, 59 insertions, 44 deletions
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 09ce2318b89e..2345268ca64b 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -119,17 +119,21 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
119 119
120void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) 120void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
121{ 121{
122 struct tipc_node *n_ptr;
122 struct link *link; 123 struct link *link;
123 struct tipc_media_addr media_addr; 124 struct tipc_media_addr media_addr, *addr;
125 struct sk_buff *rbuf;
124 struct tipc_msg *msg = buf_msg(buf); 126 struct tipc_msg *msg = buf_msg(buf);
125 u32 dest = msg_dest_domain(msg); 127 u32 dest = msg_dest_domain(msg);
126 u32 orig = msg_prevnode(msg); 128 u32 orig = msg_prevnode(msg);
127 u32 net_id = msg_bc_netid(msg); 129 u32 net_id = msg_bc_netid(msg);
128 u32 type = msg_type(msg); 130 u32 type = msg_type(msg);
131 int link_fully_up;
129 132
130 msg_get_media_addr(msg, &media_addr); 133 msg_get_media_addr(msg, &media_addr);
131 buf_discard(buf); 134 buf_discard(buf);
132 135
136 /* Validate discovery message from requesting node */
133 if (net_id != tipc_net_id) 137 if (net_id != tipc_net_id)
134 return; 138 return;
135 if (!tipc_addr_domain_valid(dest)) 139 if (!tipc_addr_domain_valid(dest))
@@ -143,56 +147,67 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
143 } 147 }
144 if (!tipc_in_scope(dest, tipc_own_addr)) 148 if (!tipc_in_scope(dest, tipc_own_addr))
145 return; 149 return;
146 if (in_own_cluster(orig)) { 150 if (!in_own_cluster(orig))
147 /* Always accept link here */ 151 return;
148 struct sk_buff *rbuf;
149 struct tipc_media_addr *addr;
150 struct tipc_node *n_ptr = tipc_node_find(orig);
151 int link_fully_up;
152
153 if (n_ptr == NULL) {
154 n_ptr = tipc_node_create(orig);
155 if (!n_ptr)
156 return;
157 }
158 spin_lock_bh(&n_ptr->lock);
159
160 /* Don't talk to neighbor during cleanup after last session */
161 152
162 if (n_ptr->cleanup_required) { 153 /* Locate structure corresponding to requesting node */
163 spin_unlock_bh(&n_ptr->lock); 154 n_ptr = tipc_node_find(orig);
155 if (!n_ptr) {
156 n_ptr = tipc_node_create(orig);
157 if (!n_ptr)
164 return; 158 return;
165 } 159 }
160 tipc_node_lock(n_ptr);
161
162 /* Don't talk to neighbor during cleanup after last session */
163 if (n_ptr->cleanup_required) {
164 tipc_node_unlock(n_ptr);
165 return;
166 }
166 167
167 link = n_ptr->links[b_ptr->identity]; 168 link = n_ptr->links[b_ptr->identity];
169
170 /* Create a link endpoint for this bearer, if necessary */
171 if (!link) {
172 link = tipc_link_create(b_ptr, orig, &media_addr);
168 if (!link) { 173 if (!link) {
169 link = tipc_link_create(b_ptr, orig, &media_addr); 174 tipc_node_unlock(n_ptr);
170 if (!link) { 175 return;
171 spin_unlock_bh(&n_ptr->lock);
172 return;
173 }
174 }
175 addr = &link->media_addr;
176 if (memcmp(addr, &media_addr, sizeof(*addr))) {
177 if (tipc_link_is_up(link) || (!link->started)) {
178 disc_dupl_alert(b_ptr, orig, &media_addr);
179 spin_unlock_bh(&n_ptr->lock);
180 return;
181 }
182 warn("Resetting link <%s>, peer interface address changed\n",
183 link->name);
184 memcpy(addr, &media_addr, sizeof(*addr));
185 tipc_link_reset(link);
186 } 176 }
187 link_fully_up = link_working_working(link); 177 }
188 spin_unlock_bh(&n_ptr->lock); 178
189 if ((type == DSC_RESP_MSG) || link_fully_up) 179 /*
180 * Ensure requesting node's media address is correct
181 *
182 * If media address doesn't match and the link is working, reject the
183 * request (must be from a duplicate node).
184 *
185 * If media address doesn't match and the link is not working, accept
186 * the new media address and reset the link to ensure it starts up
187 * cleanly.
188 */
189 addr = &link->media_addr;
190 if (memcmp(addr, &media_addr, sizeof(*addr))) {
191 if (tipc_link_is_up(link) || (!link->started)) {
192 disc_dupl_alert(b_ptr, orig, &media_addr);
193 tipc_node_unlock(n_ptr);
190 return; 194 return;
191 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
192 if (rbuf != NULL) {
193 b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);
194 buf_discard(rbuf);
195 } 195 }
196 warn("Resetting link <%s>, peer interface address changed\n",
197 link->name);
198 memcpy(addr, &media_addr, sizeof(*addr));
199 tipc_link_reset(link);
200 }
201
202 /* Accept discovery message & send response, if necessary */
203 link_fully_up = link_working_working(link);
204 tipc_node_unlock(n_ptr);
205 if ((type == DSC_RESP_MSG) || link_fully_up)
206 return;
207 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
208 if (rbuf != NULL) {
209 b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);
210 buf_discard(rbuf);
196 } 211 }
197} 212}
198 213