diff options
Diffstat (limited to 'net/tipc/discover.c')
| -rw-r--r-- | net/tipc/discover.c | 79 | 
1 files changed, 63 insertions, 16 deletions
| diff --git a/net/tipc/discover.c b/net/tipc/discover.c index a00e5f811569..c630a21b2bed 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
| @@ -82,6 +82,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type, | |||
| 82 | msg = buf_msg(buf); | 82 | msg = buf_msg(buf); | 
| 83 | tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain); | 83 | tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain); | 
| 84 | msg_set_non_seq(msg, 1); | 84 | msg_set_non_seq(msg, 1); | 
| 85 | msg_set_node_sig(msg, tipc_random); | ||
| 85 | msg_set_dest_domain(msg, dest_domain); | 86 | msg_set_dest_domain(msg, dest_domain); | 
| 86 | msg_set_bc_netid(msg, tipc_net_id); | 87 | msg_set_bc_netid(msg, tipc_net_id); | 
| 87 | b_ptr->media->addr2msg(&b_ptr->addr, msg_media_addr(msg)); | 88 | b_ptr->media->addr2msg(&b_ptr->addr, msg_media_addr(msg)); | 
| @@ -121,20 +122,22 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
| 121 | { | 122 | { | 
| 122 | struct tipc_node *n_ptr; | 123 | struct tipc_node *n_ptr; | 
| 123 | struct tipc_link *link; | 124 | struct tipc_link *link; | 
| 124 | struct tipc_media_addr media_addr, *addr; | 125 | struct tipc_media_addr media_addr; | 
| 125 | struct sk_buff *rbuf; | 126 | struct sk_buff *rbuf; | 
| 126 | struct tipc_msg *msg = buf_msg(buf); | 127 | struct tipc_msg *msg = buf_msg(buf); | 
| 127 | u32 dest = msg_dest_domain(msg); | 128 | u32 dest = msg_dest_domain(msg); | 
| 128 | u32 orig = msg_prevnode(msg); | 129 | u32 orig = msg_prevnode(msg); | 
| 129 | u32 net_id = msg_bc_netid(msg); | 130 | u32 net_id = msg_bc_netid(msg); | 
| 130 | u32 type = msg_type(msg); | 131 | u32 type = msg_type(msg); | 
| 132 | u32 signature = msg_node_sig(msg); | ||
| 133 | int addr_mismatch; | ||
| 131 | int link_fully_up; | 134 | int link_fully_up; | 
| 132 | 135 | ||
| 133 | media_addr.broadcast = 1; | 136 | media_addr.broadcast = 1; | 
| 134 | b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg)); | 137 | b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg)); | 
| 135 | buf_discard(buf); | 138 | kfree_skb(buf); | 
| 136 | 139 | ||
| 137 | /* Validate discovery message from requesting node */ | 140 | /* Ensure message from node is valid and communication is permitted */ | 
| 138 | if (net_id != tipc_net_id) | 141 | if (net_id != tipc_net_id) | 
| 139 | return; | 142 | return; | 
| 140 | if (media_addr.broadcast) | 143 | if (media_addr.broadcast) | 
| @@ -162,15 +165,50 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
| 162 | } | 165 | } | 
| 163 | tipc_node_lock(n_ptr); | 166 | tipc_node_lock(n_ptr); | 
| 164 | 167 | ||
| 168 | /* Prepare to validate requesting node's signature and media address */ | ||
| 165 | link = n_ptr->links[b_ptr->identity]; | 169 | link = n_ptr->links[b_ptr->identity]; | 
| 170 | addr_mismatch = (link != NULL) && | ||
| 171 | memcmp(&link->media_addr, &media_addr, sizeof(media_addr)); | ||
| 166 | 172 | ||
| 167 | /* Create a link endpoint for this bearer, if necessary */ | 173 | /* | 
| 168 | if (!link) { | 174 | * Ensure discovery message's signature is correct | 
| 169 | link = tipc_link_create(n_ptr, b_ptr, &media_addr); | 175 | * | 
| 170 | if (!link) { | 176 | * If signature is incorrect and there is no working link to the node, | 
| 177 | * accept the new signature but invalidate all existing links to the | ||
| 178 | * node so they won't re-activate without a new discovery message. | ||
| 179 | * | ||
| 180 | * If signature is incorrect and the requested link to the node is | ||
| 181 | * working, accept the new signature. (This is an instance of delayed | ||
| 182 | * rediscovery, where a link endpoint was able to re-establish contact | ||
| 183 | * with its peer endpoint on a node that rebooted before receiving a | ||
| 184 | * discovery message from that node.) | ||
| 185 | * | ||
| 186 | * If signature is incorrect and there is a working link to the node | ||
| 187 | * that is not the requested link, reject the request (must be from | ||
| 188 | * a duplicate node). | ||
| 189 | */ | ||
| 190 | if (signature != n_ptr->signature) { | ||
| 191 | if (n_ptr->working_links == 0) { | ||
| 192 | struct tipc_link *curr_link; | ||
| 193 | int i; | ||
| 194 | |||
| 195 | for (i = 0; i < MAX_BEARERS; i++) { | ||
| 196 | curr_link = n_ptr->links[i]; | ||
| 197 | if (curr_link) { | ||
| 198 | memset(&curr_link->media_addr, 0, | ||
| 199 | sizeof(media_addr)); | ||
| 200 | tipc_link_reset(curr_link); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | addr_mismatch = (link != NULL); | ||
| 204 | } else if (tipc_link_is_up(link) && !addr_mismatch) { | ||
| 205 | /* delayed rediscovery */ | ||
| 206 | } else { | ||
| 207 | disc_dupl_alert(b_ptr, orig, &media_addr); | ||
| 171 | tipc_node_unlock(n_ptr); | 208 | tipc_node_unlock(n_ptr); | 
| 172 | return; | 209 | return; | 
| 173 | } | 210 | } | 
| 211 | n_ptr->signature = signature; | ||
| 174 | } | 212 | } | 
| 175 | 213 | ||
| 176 | /* | 214 | /* | 
| @@ -183,17 +221,26 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
| 183 | * the new media address and reset the link to ensure it starts up | 221 | * the new media address and reset the link to ensure it starts up | 
| 184 | * cleanly. | 222 | * cleanly. | 
| 185 | */ | 223 | */ | 
| 186 | addr = &link->media_addr; | 224 | |
| 187 | if (memcmp(addr, &media_addr, sizeof(*addr))) { | 225 | if (addr_mismatch) { | 
| 188 | if (tipc_link_is_up(link) || (!link->started)) { | 226 | if (tipc_link_is_up(link)) { | 
| 189 | disc_dupl_alert(b_ptr, orig, &media_addr); | 227 | disc_dupl_alert(b_ptr, orig, &media_addr); | 
| 190 | tipc_node_unlock(n_ptr); | 228 | tipc_node_unlock(n_ptr); | 
| 191 | return; | 229 | return; | 
| 230 | } else { | ||
| 231 | memcpy(&link->media_addr, &media_addr, | ||
| 232 | sizeof(media_addr)); | ||
| 233 | tipc_link_reset(link); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | /* Create a link endpoint for this bearer, if necessary */ | ||
| 238 | if (!link) { | ||
| 239 | link = tipc_link_create(n_ptr, b_ptr, &media_addr); | ||
| 240 | if (!link) { | ||
| 241 | tipc_node_unlock(n_ptr); | ||
| 242 | return; | ||
| 192 | } | 243 | } | 
| 193 | warn("Resetting link <%s>, peer interface address changed\n", | ||
| 194 | link->name); | ||
| 195 | memcpy(addr, &media_addr, sizeof(*addr)); | ||
| 196 | tipc_link_reset(link); | ||
| 197 | } | 244 | } | 
| 198 | 245 | ||
| 199 | /* Accept discovery message & send response, if necessary */ | 246 | /* Accept discovery message & send response, if necessary */ | 
| @@ -203,7 +250,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
| 203 | rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr); | 250 | rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr); | 
| 204 | if (rbuf) { | 251 | if (rbuf) { | 
| 205 | b_ptr->media->send_msg(rbuf, b_ptr, &media_addr); | 252 | b_ptr->media->send_msg(rbuf, b_ptr, &media_addr); | 
| 206 | buf_discard(rbuf); | 253 | kfree_skb(rbuf); | 
| 207 | } | 254 | } | 
| 208 | } | 255 | } | 
| 209 | 256 | ||
| @@ -349,7 +396,7 @@ void tipc_disc_delete(struct tipc_link_req *req) | |||
| 349 | { | 396 | { | 
| 350 | k_cancel_timer(&req->timer); | 397 | k_cancel_timer(&req->timer); | 
| 351 | k_term_timer(&req->timer); | 398 | k_term_timer(&req->timer); | 
| 352 | buf_discard(req->buf); | 399 | kfree_skb(req->buf); | 
| 353 | kfree(req); | 400 | kfree(req); | 
| 354 | } | 401 | } | 
| 355 | 402 | ||
