.. | .. |
---|
43 | 43 | #include "monitor.h" |
---|
44 | 44 | #include "discover.h" |
---|
45 | 45 | #include "netlink.h" |
---|
| 46 | +#include "trace.h" |
---|
| 47 | +#include "crypto.h" |
---|
46 | 48 | |
---|
47 | 49 | #define INVALID_NODE_SIG 0x10000 |
---|
48 | 50 | #define NODE_CLEANUP_AFTER 300000 |
---|
.. | .. |
---|
73 | 75 | struct sk_buff_head arrvq; |
---|
74 | 76 | struct sk_buff_head inputq2; |
---|
75 | 77 | struct sk_buff_head namedq; |
---|
| 78 | + u16 named_rcv_nxt; |
---|
| 79 | + bool named_open; |
---|
76 | 80 | }; |
---|
77 | 81 | |
---|
78 | 82 | /** |
---|
.. | .. |
---|
88 | 92 | * @links: array containing references to all links to node |
---|
89 | 93 | * @action_flags: bit mask of different types of node actions |
---|
90 | 94 | * @state: connectivity state vs peer node |
---|
| 95 | + * @preliminary: a preliminary node or not |
---|
91 | 96 | * @sync_point: sequence number where synch/failover is finished |
---|
92 | 97 | * @list: links to adjacent nodes in sorted list of cluster's nodes |
---|
93 | 98 | * @working_links: number of working links to node (both active and standby) |
---|
.. | .. |
---|
98 | 103 | * @publ_list: list of publications |
---|
99 | 104 | * @rcu: rcu struct for tipc_node |
---|
100 | 105 | * @delete_at: indicates the time for deleting a down node |
---|
| 106 | + * @crypto_rx: RX crypto handler |
---|
101 | 107 | */ |
---|
102 | 108 | struct tipc_node { |
---|
103 | 109 | u32 addr; |
---|
.. | .. |
---|
111 | 117 | int action_flags; |
---|
112 | 118 | struct list_head list; |
---|
113 | 119 | int state; |
---|
| 120 | + bool preliminary; |
---|
114 | 121 | bool failover_sent; |
---|
115 | 122 | u16 sync_point; |
---|
116 | 123 | int link_cnt; |
---|
.. | .. |
---|
119 | 126 | u32 signature; |
---|
120 | 127 | u32 link_id; |
---|
121 | 128 | u8 peer_id[16]; |
---|
| 129 | + char peer_id_string[NODE_ID_STR_LEN]; |
---|
122 | 130 | struct list_head publ_list; |
---|
123 | 131 | struct list_head conn_sks; |
---|
124 | 132 | unsigned long keepalive_intv; |
---|
125 | 133 | struct timer_list timer; |
---|
126 | 134 | struct rcu_head rcu; |
---|
127 | 135 | unsigned long delete_at; |
---|
| 136 | + struct net *peer_net; |
---|
| 137 | + u32 peer_hash_mix; |
---|
| 138 | +#ifdef CONFIG_TIPC_CRYPTO |
---|
| 139 | + struct tipc_crypto *crypto_rx; |
---|
| 140 | +#endif |
---|
128 | 141 | }; |
---|
129 | 142 | |
---|
130 | 143 | /* Node FSM states and events: |
---|
.. | .. |
---|
162 | 175 | static void tipc_node_fsm_evt(struct tipc_node *n, int evt); |
---|
163 | 176 | static struct tipc_node *tipc_node_find(struct net *net, u32 addr); |
---|
164 | 177 | static struct tipc_node *tipc_node_find_by_id(struct net *net, u8 *id); |
---|
165 | | -static void tipc_node_put(struct tipc_node *node); |
---|
166 | 178 | static bool node_is_up(struct tipc_node *n); |
---|
167 | 179 | static void tipc_node_delete_from_list(struct tipc_node *node); |
---|
168 | 180 | |
---|
.. | .. |
---|
183 | 195 | return n->links[bearer_id].link; |
---|
184 | 196 | } |
---|
185 | 197 | |
---|
186 | | -int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel) |
---|
| 198 | +int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel, bool connected) |
---|
187 | 199 | { |
---|
188 | 200 | struct tipc_node *n; |
---|
189 | 201 | int bearer_id; |
---|
.. | .. |
---|
192 | 204 | n = tipc_node_find(net, addr); |
---|
193 | 205 | if (unlikely(!n)) |
---|
194 | 206 | return mtu; |
---|
| 207 | + |
---|
| 208 | + /* Allow MAX_MSG_SIZE when building connection oriented message |
---|
| 209 | + * if they are in the same core network |
---|
| 210 | + */ |
---|
| 211 | + if (n->peer_net && connected) { |
---|
| 212 | + tipc_node_put(n); |
---|
| 213 | + return mtu; |
---|
| 214 | + } |
---|
195 | 215 | |
---|
196 | 216 | bearer_id = n->active_links[sel & 1]; |
---|
197 | 217 | if (likely(bearer_id != INVALID_BEARER_ID)) |
---|
.. | .. |
---|
234 | 254 | return caps; |
---|
235 | 255 | } |
---|
236 | 256 | |
---|
| 257 | +u32 tipc_node_get_addr(struct tipc_node *node) |
---|
| 258 | +{ |
---|
| 259 | + return (node) ? node->addr : 0; |
---|
| 260 | +} |
---|
| 261 | + |
---|
| 262 | +char *tipc_node_get_id_str(struct tipc_node *node) |
---|
| 263 | +{ |
---|
| 264 | + return node->peer_id_string; |
---|
| 265 | +} |
---|
| 266 | + |
---|
| 267 | +#ifdef CONFIG_TIPC_CRYPTO |
---|
| 268 | +/** |
---|
| 269 | + * tipc_node_crypto_rx - Retrieve crypto RX handle from node |
---|
| 270 | + * Note: node ref counter must be held first! |
---|
| 271 | + */ |
---|
| 272 | +struct tipc_crypto *tipc_node_crypto_rx(struct tipc_node *__n) |
---|
| 273 | +{ |
---|
| 274 | + return (__n) ? __n->crypto_rx : NULL; |
---|
| 275 | +} |
---|
| 276 | + |
---|
| 277 | +struct tipc_crypto *tipc_node_crypto_rx_by_list(struct list_head *pos) |
---|
| 278 | +{ |
---|
| 279 | + return container_of(pos, struct tipc_node, list)->crypto_rx; |
---|
| 280 | +} |
---|
| 281 | + |
---|
| 282 | +struct tipc_crypto *tipc_node_crypto_rx_by_addr(struct net *net, u32 addr) |
---|
| 283 | +{ |
---|
| 284 | + struct tipc_node *n; |
---|
| 285 | + |
---|
| 286 | + n = tipc_node_find(net, addr); |
---|
| 287 | + return (n) ? n->crypto_rx : NULL; |
---|
| 288 | +} |
---|
| 289 | +#endif |
---|
| 290 | + |
---|
| 291 | +static void tipc_node_free(struct rcu_head *rp) |
---|
| 292 | +{ |
---|
| 293 | + struct tipc_node *n = container_of(rp, struct tipc_node, rcu); |
---|
| 294 | + |
---|
| 295 | +#ifdef CONFIG_TIPC_CRYPTO |
---|
| 296 | + tipc_crypto_stop(&n->crypto_rx); |
---|
| 297 | +#endif |
---|
| 298 | + kfree(n); |
---|
| 299 | +} |
---|
| 300 | + |
---|
237 | 301 | static void tipc_node_kref_release(struct kref *kref) |
---|
238 | 302 | { |
---|
239 | 303 | struct tipc_node *n = container_of(kref, struct tipc_node, kref); |
---|
240 | 304 | |
---|
241 | 305 | kfree(n->bc_entry.link); |
---|
242 | | - kfree_rcu(n, rcu); |
---|
| 306 | + call_rcu(&n->rcu, tipc_node_free); |
---|
243 | 307 | } |
---|
244 | 308 | |
---|
245 | | -static void tipc_node_put(struct tipc_node *node) |
---|
| 309 | +void tipc_node_put(struct tipc_node *node) |
---|
246 | 310 | { |
---|
247 | 311 | kref_put(&node->kref, tipc_node_kref_release); |
---|
248 | 312 | } |
---|
249 | 313 | |
---|
250 | | -static void tipc_node_get(struct tipc_node *node) |
---|
| 314 | +void tipc_node_get(struct tipc_node *node) |
---|
251 | 315 | { |
---|
252 | 316 | kref_get(&node->kref); |
---|
253 | 317 | } |
---|
.. | .. |
---|
263 | 327 | |
---|
264 | 328 | rcu_read_lock(); |
---|
265 | 329 | hlist_for_each_entry_rcu(node, &tn->node_htable[thash], hash) { |
---|
266 | | - if (node->addr != addr) |
---|
| 330 | + if (node->addr != addr || node->preliminary) |
---|
267 | 331 | continue; |
---|
268 | 332 | if (!kref_get_unless_zero(&node->kref)) |
---|
269 | 333 | node = NULL; |
---|
.. | .. |
---|
342 | 406 | write_unlock_bh(&n->lock); |
---|
343 | 407 | |
---|
344 | 408 | if (flags & TIPC_NOTIFY_NODE_DOWN) |
---|
345 | | - tipc_publ_notify(net, publ_list, addr); |
---|
| 409 | + tipc_publ_notify(net, publ_list, addr, n->capabilities); |
---|
346 | 410 | |
---|
347 | 411 | if (flags & TIPC_NOTIFY_NODE_UP) |
---|
348 | | - tipc_named_node_up(net, addr); |
---|
| 412 | + tipc_named_node_up(net, addr, n->capabilities); |
---|
349 | 413 | |
---|
350 | 414 | if (flags & TIPC_NOTIFY_LINK_UP) { |
---|
351 | 415 | tipc_mon_peer_up(net, addr, bearer_id); |
---|
.. | .. |
---|
359 | 423 | } |
---|
360 | 424 | } |
---|
361 | 425 | |
---|
362 | | -static struct tipc_node *tipc_node_create(struct net *net, u32 addr, |
---|
363 | | - u8 *peer_id, u16 capabilities) |
---|
| 426 | +static void tipc_node_assign_peer_net(struct tipc_node *n, u32 hash_mixes) |
---|
| 427 | +{ |
---|
| 428 | + int net_id = tipc_netid(n->net); |
---|
| 429 | + struct tipc_net *tn_peer; |
---|
| 430 | + struct net *tmp; |
---|
| 431 | + u32 hash_chk; |
---|
| 432 | + |
---|
| 433 | + if (n->peer_net) |
---|
| 434 | + return; |
---|
| 435 | + |
---|
| 436 | + for_each_net_rcu(tmp) { |
---|
| 437 | + tn_peer = tipc_net(tmp); |
---|
| 438 | + if (!tn_peer) |
---|
| 439 | + continue; |
---|
| 440 | + /* Integrity checking whether node exists in namespace or not */ |
---|
| 441 | + if (tn_peer->net_id != net_id) |
---|
| 442 | + continue; |
---|
| 443 | + if (memcmp(n->peer_id, tn_peer->node_id, NODE_ID_LEN)) |
---|
| 444 | + continue; |
---|
| 445 | + hash_chk = tipc_net_hash_mixes(tmp, tn_peer->random); |
---|
| 446 | + if (hash_mixes ^ hash_chk) |
---|
| 447 | + continue; |
---|
| 448 | + n->peer_net = tmp; |
---|
| 449 | + n->peer_hash_mix = hash_mixes; |
---|
| 450 | + break; |
---|
| 451 | + } |
---|
| 452 | +} |
---|
| 453 | + |
---|
| 454 | +struct tipc_node *tipc_node_create(struct net *net, u32 addr, u8 *peer_id, |
---|
| 455 | + u16 capabilities, u32 hash_mixes, |
---|
| 456 | + bool preliminary) |
---|
364 | 457 | { |
---|
365 | 458 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
---|
| 459 | + struct tipc_link *l, *snd_l = tipc_bc_sndlink(net); |
---|
366 | 460 | struct tipc_node *n, *temp_node; |
---|
367 | | - struct tipc_link *l; |
---|
| 461 | + unsigned long intv; |
---|
368 | 462 | int bearer_id; |
---|
369 | 463 | int i; |
---|
370 | 464 | |
---|
371 | 465 | spin_lock_bh(&tn->node_list_lock); |
---|
372 | | - n = tipc_node_find(net, addr); |
---|
| 466 | + n = tipc_node_find(net, addr) ?: |
---|
| 467 | + tipc_node_find_by_id(net, peer_id); |
---|
373 | 468 | if (n) { |
---|
| 469 | + if (!n->preliminary) |
---|
| 470 | + goto update; |
---|
| 471 | + if (preliminary) |
---|
| 472 | + goto exit; |
---|
| 473 | + /* A preliminary node becomes "real" now, refresh its data */ |
---|
| 474 | + tipc_node_write_lock(n); |
---|
| 475 | + if (!tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX, |
---|
| 476 | + tipc_link_min_win(snd_l), tipc_link_max_win(snd_l), |
---|
| 477 | + n->capabilities, &n->bc_entry.inputq1, |
---|
| 478 | + &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) { |
---|
| 479 | + pr_warn("Broadcast rcv link refresh failed, no memory\n"); |
---|
| 480 | + tipc_node_write_unlock_fast(n); |
---|
| 481 | + tipc_node_put(n); |
---|
| 482 | + n = NULL; |
---|
| 483 | + goto exit; |
---|
| 484 | + } |
---|
| 485 | + n->preliminary = false; |
---|
| 486 | + n->addr = addr; |
---|
| 487 | + hlist_del_rcu(&n->hash); |
---|
| 488 | + hlist_add_head_rcu(&n->hash, |
---|
| 489 | + &tn->node_htable[tipc_hashfn(addr)]); |
---|
| 490 | + list_del_rcu(&n->list); |
---|
| 491 | + list_for_each_entry_rcu(temp_node, &tn->node_list, list) { |
---|
| 492 | + if (n->addr < temp_node->addr) |
---|
| 493 | + break; |
---|
| 494 | + } |
---|
| 495 | + list_add_tail_rcu(&n->list, &temp_node->list); |
---|
| 496 | + tipc_node_write_unlock_fast(n); |
---|
| 497 | + |
---|
| 498 | +update: |
---|
| 499 | + if (n->peer_hash_mix ^ hash_mixes) |
---|
| 500 | + tipc_node_assign_peer_net(n, hash_mixes); |
---|
374 | 501 | if (n->capabilities == capabilities) |
---|
375 | 502 | goto exit; |
---|
376 | 503 | /* Same node may come back with new capabilities */ |
---|
377 | | - write_lock_bh(&n->lock); |
---|
| 504 | + tipc_node_write_lock(n); |
---|
378 | 505 | n->capabilities = capabilities; |
---|
379 | 506 | for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) { |
---|
380 | 507 | l = n->links[bearer_id].link; |
---|
381 | 508 | if (l) |
---|
382 | 509 | tipc_link_update_caps(l, capabilities); |
---|
383 | 510 | } |
---|
384 | | - write_unlock_bh(&n->lock); |
---|
| 511 | + tipc_node_write_unlock_fast(n); |
---|
| 512 | + |
---|
| 513 | + /* Calculate cluster capabilities */ |
---|
| 514 | + tn->capabilities = TIPC_NODE_CAPABILITIES; |
---|
| 515 | + list_for_each_entry_rcu(temp_node, &tn->node_list, list) { |
---|
| 516 | + tn->capabilities &= temp_node->capabilities; |
---|
| 517 | + } |
---|
| 518 | + |
---|
| 519 | + tipc_bcast_toggle_rcast(net, |
---|
| 520 | + (tn->capabilities & TIPC_BCAST_RCAST)); |
---|
| 521 | + |
---|
385 | 522 | goto exit; |
---|
386 | 523 | } |
---|
387 | 524 | n = kzalloc(sizeof(*n), GFP_ATOMIC); |
---|
.. | .. |
---|
389 | 526 | pr_warn("Node creation failed, no memory\n"); |
---|
390 | 527 | goto exit; |
---|
391 | 528 | } |
---|
| 529 | + tipc_nodeid2string(n->peer_id_string, peer_id); |
---|
| 530 | +#ifdef CONFIG_TIPC_CRYPTO |
---|
| 531 | + if (unlikely(tipc_crypto_start(&n->crypto_rx, net, n))) { |
---|
| 532 | + pr_warn("Failed to start crypto RX(%s)!\n", n->peer_id_string); |
---|
| 533 | + kfree(n); |
---|
| 534 | + n = NULL; |
---|
| 535 | + goto exit; |
---|
| 536 | + } |
---|
| 537 | +#endif |
---|
392 | 538 | n->addr = addr; |
---|
| 539 | + n->preliminary = preliminary; |
---|
393 | 540 | memcpy(&n->peer_id, peer_id, 16); |
---|
394 | 541 | n->net = net; |
---|
| 542 | + n->peer_net = NULL; |
---|
| 543 | + n->peer_hash_mix = 0; |
---|
| 544 | + /* Assign kernel local namespace if exists */ |
---|
| 545 | + tipc_node_assign_peer_net(n, hash_mixes); |
---|
395 | 546 | n->capabilities = capabilities; |
---|
396 | 547 | kref_init(&n->kref); |
---|
397 | 548 | rwlock_init(&n->lock); |
---|
.. | .. |
---|
410 | 561 | n->signature = INVALID_NODE_SIG; |
---|
411 | 562 | n->active_links[0] = INVALID_BEARER_ID; |
---|
412 | 563 | n->active_links[1] = INVALID_BEARER_ID; |
---|
413 | | - if (!tipc_link_bc_create(net, tipc_own_addr(net), |
---|
414 | | - addr, U16_MAX, |
---|
415 | | - tipc_link_window(tipc_bc_sndlink(net)), |
---|
416 | | - n->capabilities, |
---|
417 | | - &n->bc_entry.inputq1, |
---|
418 | | - &n->bc_entry.namedq, |
---|
419 | | - tipc_bc_sndlink(net), |
---|
420 | | - &n->bc_entry.link)) { |
---|
| 564 | + if (!preliminary && |
---|
| 565 | + !tipc_link_bc_create(net, tipc_own_addr(net), addr, peer_id, U16_MAX, |
---|
| 566 | + tipc_link_min_win(snd_l), tipc_link_max_win(snd_l), |
---|
| 567 | + n->capabilities, &n->bc_entry.inputq1, |
---|
| 568 | + &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) { |
---|
421 | 569 | pr_warn("Broadcast rcv link creation failed, no memory\n"); |
---|
422 | | - kfree(n); |
---|
| 570 | + tipc_node_put(n); |
---|
423 | 571 | n = NULL; |
---|
424 | 572 | goto exit; |
---|
425 | 573 | } |
---|
426 | 574 | tipc_node_get(n); |
---|
427 | 575 | timer_setup(&n->timer, tipc_node_timeout, 0); |
---|
428 | | - n->keepalive_intv = U32_MAX; |
---|
| 576 | + /* Start a slow timer anyway, crypto needs it */ |
---|
| 577 | + n->keepalive_intv = 10000; |
---|
| 578 | + intv = jiffies + msecs_to_jiffies(n->keepalive_intv); |
---|
| 579 | + if (!mod_timer(&n->timer, intv)) |
---|
| 580 | + tipc_node_get(n); |
---|
429 | 581 | hlist_add_head_rcu(&n->hash, &tn->node_htable[tipc_hashfn(addr)]); |
---|
430 | 582 | list_for_each_entry_rcu(temp_node, &tn->node_list, list) { |
---|
431 | 583 | if (n->addr < temp_node->addr) |
---|
432 | 584 | break; |
---|
433 | 585 | } |
---|
434 | 586 | list_add_tail_rcu(&n->list, &temp_node->list); |
---|
| 587 | + /* Calculate cluster capabilities */ |
---|
| 588 | + tn->capabilities = TIPC_NODE_CAPABILITIES; |
---|
| 589 | + list_for_each_entry_rcu(temp_node, &tn->node_list, list) { |
---|
| 590 | + tn->capabilities &= temp_node->capabilities; |
---|
| 591 | + } |
---|
| 592 | + tipc_bcast_toggle_rcast(net, (tn->capabilities & TIPC_BCAST_RCAST)); |
---|
| 593 | + trace_tipc_node_create(n, true, " "); |
---|
435 | 594 | exit: |
---|
436 | 595 | spin_unlock_bh(&tn->node_list_lock); |
---|
437 | 596 | return n; |
---|
.. | .. |
---|
452 | 611 | |
---|
453 | 612 | static void tipc_node_delete_from_list(struct tipc_node *node) |
---|
454 | 613 | { |
---|
| 614 | +#ifdef CONFIG_TIPC_CRYPTO |
---|
| 615 | + tipc_crypto_key_flush(node->crypto_rx); |
---|
| 616 | +#endif |
---|
455 | 617 | list_del_rcu(&node->list); |
---|
456 | 618 | hlist_del_rcu(&node->hash); |
---|
457 | 619 | tipc_node_put(node); |
---|
.. | .. |
---|
459 | 621 | |
---|
460 | 622 | static void tipc_node_delete(struct tipc_node *node) |
---|
461 | 623 | { |
---|
| 624 | + trace_tipc_node_delete(node, true, " "); |
---|
462 | 625 | tipc_node_delete_from_list(node); |
---|
463 | 626 | |
---|
464 | 627 | del_timer_sync(&node->timer); |
---|
.. | .. |
---|
586 | 749 | */ |
---|
587 | 750 | static bool tipc_node_cleanup(struct tipc_node *peer) |
---|
588 | 751 | { |
---|
| 752 | + struct tipc_node *temp_node; |
---|
589 | 753 | struct tipc_net *tn = tipc_net(peer->net); |
---|
590 | 754 | bool deleted = false; |
---|
591 | 755 | |
---|
.. | .. |
---|
601 | 765 | deleted = true; |
---|
602 | 766 | } |
---|
603 | 767 | tipc_node_write_unlock(peer); |
---|
| 768 | + |
---|
| 769 | + if (!deleted) { |
---|
| 770 | + spin_unlock_bh(&tn->node_list_lock); |
---|
| 771 | + return deleted; |
---|
| 772 | + } |
---|
| 773 | + |
---|
| 774 | + /* Calculate cluster capabilities */ |
---|
| 775 | + tn->capabilities = TIPC_NODE_CAPABILITIES; |
---|
| 776 | + list_for_each_entry_rcu(temp_node, &tn->node_list, list) { |
---|
| 777 | + tn->capabilities &= temp_node->capabilities; |
---|
| 778 | + } |
---|
| 779 | + tipc_bcast_toggle_rcast(peer->net, |
---|
| 780 | + (tn->capabilities & TIPC_BCAST_RCAST)); |
---|
604 | 781 | spin_unlock_bh(&tn->node_list_lock); |
---|
605 | 782 | return deleted; |
---|
606 | 783 | } |
---|
.. | .. |
---|
616 | 793 | int bearer_id; |
---|
617 | 794 | int rc = 0; |
---|
618 | 795 | |
---|
| 796 | + trace_tipc_node_timeout(n, false, " "); |
---|
619 | 797 | if (!node_is_up(n) && tipc_node_cleanup(n)) { |
---|
620 | 798 | /*Removing the reference of Timer*/ |
---|
621 | 799 | tipc_node_put(n); |
---|
622 | 800 | return; |
---|
623 | 801 | } |
---|
624 | 802 | |
---|
| 803 | +#ifdef CONFIG_TIPC_CRYPTO |
---|
| 804 | + /* Take any crypto key related actions first */ |
---|
| 805 | + tipc_crypto_timeout(n->crypto_rx); |
---|
| 806 | +#endif |
---|
625 | 807 | __skb_queue_head_init(&xmitq); |
---|
626 | 808 | |
---|
627 | 809 | /* Initial node interval to value larger (10 seconds), then it will be |
---|
.. | .. |
---|
642 | 824 | remains--; |
---|
643 | 825 | } |
---|
644 | 826 | tipc_node_read_unlock(n); |
---|
645 | | - tipc_bearer_xmit(n->net, bearer_id, &xmitq, &le->maddr); |
---|
| 827 | + tipc_bearer_xmit(n->net, bearer_id, &xmitq, &le->maddr, n); |
---|
646 | 828 | if (rc & TIPC_LINK_DOWN_EVT) |
---|
647 | 829 | tipc_node_link_down(n, bearer_id, false); |
---|
648 | 830 | } |
---|
.. | .. |
---|
674 | 856 | n->link_id = tipc_link_id(nl); |
---|
675 | 857 | |
---|
676 | 858 | /* Leave room for tunnel header when returning 'mtu' to users: */ |
---|
677 | | - n->links[bearer_id].mtu = tipc_link_mtu(nl) - INT_H_SIZE; |
---|
| 859 | + n->links[bearer_id].mtu = tipc_link_mss(nl); |
---|
678 | 860 | |
---|
679 | 861 | tipc_bearer_add_dest(n->net, bearer_id, n->addr); |
---|
680 | 862 | tipc_bcast_inc_bearer_dst_cnt(n->net, bearer_id); |
---|
681 | 863 | |
---|
682 | 864 | pr_debug("Established link <%s> on network plane %c\n", |
---|
683 | 865 | tipc_link_name(nl), tipc_link_plane(nl)); |
---|
| 866 | + trace_tipc_node_link_up(n, true, " "); |
---|
684 | 867 | |
---|
685 | 868 | /* Ensure that a STATE message goes first */ |
---|
686 | 869 | tipc_link_build_state_msg(nl, xmitq); |
---|
.. | .. |
---|
690 | 873 | *slot0 = bearer_id; |
---|
691 | 874 | *slot1 = bearer_id; |
---|
692 | 875 | tipc_node_fsm_evt(n, SELF_ESTABL_CONTACT_EVT); |
---|
693 | | - n->failover_sent = false; |
---|
694 | 876 | n->action_flags |= TIPC_NOTIFY_NODE_UP; |
---|
695 | 877 | tipc_link_set_active(nl, true); |
---|
696 | 878 | tipc_bcast_add_peer(n->net, nl, xmitq); |
---|
.. | .. |
---|
728 | 910 | tipc_node_write_lock(n); |
---|
729 | 911 | __tipc_node_link_up(n, bearer_id, xmitq); |
---|
730 | 912 | maddr = &n->links[bearer_id].maddr; |
---|
731 | | - tipc_bearer_xmit(n->net, bearer_id, xmitq, maddr); |
---|
| 913 | + tipc_bearer_xmit(n->net, bearer_id, xmitq, maddr, n); |
---|
732 | 914 | tipc_node_write_unlock(n); |
---|
| 915 | +} |
---|
| 916 | + |
---|
| 917 | +/** |
---|
| 918 | + * tipc_node_link_failover() - start failover in case "half-failover" |
---|
| 919 | + * |
---|
| 920 | + * This function is only called in a very special situation where link |
---|
| 921 | + * failover can be already started on peer node but not on this node. |
---|
| 922 | + * This can happen when e.g. |
---|
| 923 | + * 1. Both links <1A-2A>, <1B-2B> down |
---|
| 924 | + * 2. Link endpoint 2A up, but 1A still down (e.g. due to network |
---|
| 925 | + * disturbance, wrong session, etc.) |
---|
| 926 | + * 3. Link <1B-2B> up |
---|
| 927 | + * 4. Link endpoint 2A down (e.g. due to link tolerance timeout) |
---|
| 928 | + * 5. Node 2 starts failover onto link <1B-2B> |
---|
| 929 | + * |
---|
| 930 | + * ==> Node 1 does never start link/node failover! |
---|
| 931 | + * |
---|
| 932 | + * @n: tipc node structure |
---|
| 933 | + * @l: link peer endpoint failingover (- can be NULL) |
---|
| 934 | + * @tnl: tunnel link |
---|
| 935 | + * @xmitq: queue for messages to be xmited on tnl link later |
---|
| 936 | + */ |
---|
| 937 | +static void tipc_node_link_failover(struct tipc_node *n, struct tipc_link *l, |
---|
| 938 | + struct tipc_link *tnl, |
---|
| 939 | + struct sk_buff_head *xmitq) |
---|
| 940 | +{ |
---|
| 941 | + /* Avoid to be "self-failover" that can never end */ |
---|
| 942 | + if (!tipc_link_is_up(tnl)) |
---|
| 943 | + return; |
---|
| 944 | + |
---|
| 945 | + /* Don't rush, failure link may be in the process of resetting */ |
---|
| 946 | + if (l && !tipc_link_is_reset(l)) |
---|
| 947 | + return; |
---|
| 948 | + |
---|
| 949 | + tipc_link_fsm_evt(tnl, LINK_SYNCH_END_EVT); |
---|
| 950 | + tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT); |
---|
| 951 | + |
---|
| 952 | + n->sync_point = tipc_link_rcv_nxt(tnl) + (U16_MAX / 2 - 1); |
---|
| 953 | + tipc_link_failover_prepare(l, tnl, xmitq); |
---|
| 954 | + |
---|
| 955 | + if (l) |
---|
| 956 | + tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT); |
---|
| 957 | + tipc_node_fsm_evt(n, NODE_FAILOVER_BEGIN_EVT); |
---|
733 | 958 | } |
---|
734 | 959 | |
---|
735 | 960 | /** |
---|
.. | .. |
---|
783 | 1008 | if (tipc_link_peer_is_down(l)) |
---|
784 | 1009 | tipc_node_fsm_evt(n, PEER_LOST_CONTACT_EVT); |
---|
785 | 1010 | tipc_node_fsm_evt(n, SELF_LOST_CONTACT_EVT); |
---|
| 1011 | + trace_tipc_link_reset(l, TIPC_DUMP_ALL, "link down!"); |
---|
786 | 1012 | tipc_link_fsm_evt(l, LINK_RESET_EVT); |
---|
787 | 1013 | tipc_link_reset(l); |
---|
788 | 1014 | tipc_link_build_reset_msg(l, xmitq); |
---|
.. | .. |
---|
800 | 1026 | tipc_node_fsm_evt(n, NODE_SYNCH_END_EVT); |
---|
801 | 1027 | n->sync_point = tipc_link_rcv_nxt(tnl) + (U16_MAX / 2 - 1); |
---|
802 | 1028 | tipc_link_tnl_prepare(l, tnl, FAILOVER_MSG, xmitq); |
---|
| 1029 | + trace_tipc_link_reset(l, TIPC_DUMP_ALL, "link down -> failover!"); |
---|
803 | 1030 | tipc_link_reset(l); |
---|
804 | 1031 | tipc_link_fsm_evt(l, LINK_RESET_EVT); |
---|
805 | 1032 | tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT); |
---|
.. | .. |
---|
823 | 1050 | tipc_node_write_lock(n); |
---|
824 | 1051 | if (!tipc_link_is_establishing(l)) { |
---|
825 | 1052 | __tipc_node_link_down(n, &bearer_id, &xmitq, &maddr); |
---|
826 | | - if (delete) { |
---|
827 | | - kfree(l); |
---|
828 | | - le->link = NULL; |
---|
829 | | - n->link_cnt--; |
---|
830 | | - } |
---|
831 | 1053 | } else { |
---|
832 | 1054 | /* Defuse pending tipc_node_link_up() */ |
---|
| 1055 | + tipc_link_reset(l); |
---|
833 | 1056 | tipc_link_fsm_evt(l, LINK_RESET_EVT); |
---|
834 | 1057 | } |
---|
| 1058 | + if (delete) { |
---|
| 1059 | + kfree(l); |
---|
| 1060 | + le->link = NULL; |
---|
| 1061 | + n->link_cnt--; |
---|
| 1062 | + } |
---|
| 1063 | + trace_tipc_node_link_down(n, true, "node link down or deleted!"); |
---|
835 | 1064 | tipc_node_write_unlock(n); |
---|
836 | 1065 | if (delete) |
---|
837 | 1066 | tipc_mon_remove_peer(n->net, n->addr, old_bearer_id); |
---|
838 | 1067 | if (!skb_queue_empty(&xmitq)) |
---|
839 | | - tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr); |
---|
| 1068 | + tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr, n); |
---|
840 | 1069 | tipc_sk_rcv(n->net, &le->inputq); |
---|
841 | 1070 | } |
---|
842 | 1071 | |
---|
.. | .. |
---|
880 | 1109 | { |
---|
881 | 1110 | struct tipc_net *tn = tipc_net(net); |
---|
882 | 1111 | struct tipc_node *n; |
---|
| 1112 | + bool preliminary; |
---|
| 1113 | + u32 sugg_addr; |
---|
883 | 1114 | |
---|
884 | 1115 | /* Suggest new address if some other peer is using this one */ |
---|
885 | 1116 | n = tipc_node_find(net, addr); |
---|
.. | .. |
---|
895 | 1126 | /* Suggest previously used address if peer is known */ |
---|
896 | 1127 | n = tipc_node_find_by_id(net, id); |
---|
897 | 1128 | if (n) { |
---|
898 | | - addr = n->addr; |
---|
| 1129 | + sugg_addr = n->addr; |
---|
| 1130 | + preliminary = n->preliminary; |
---|
899 | 1131 | tipc_node_put(n); |
---|
900 | | - return addr; |
---|
| 1132 | + if (!preliminary) |
---|
| 1133 | + return sugg_addr; |
---|
901 | 1134 | } |
---|
902 | 1135 | |
---|
903 | 1136 | /* Even this node may be in conflict */ |
---|
.. | .. |
---|
909 | 1142 | |
---|
910 | 1143 | void tipc_node_check_dest(struct net *net, u32 addr, |
---|
911 | 1144 | u8 *peer_id, struct tipc_bearer *b, |
---|
912 | | - u16 capabilities, u32 signature, |
---|
| 1145 | + u16 capabilities, u32 signature, u32 hash_mixes, |
---|
913 | 1146 | struct tipc_media_addr *maddr, |
---|
914 | 1147 | bool *respond, bool *dupl_addr) |
---|
915 | 1148 | { |
---|
.. | .. |
---|
919 | 1152 | bool addr_match = false; |
---|
920 | 1153 | bool sign_match = false; |
---|
921 | 1154 | bool link_up = false; |
---|
| 1155 | + bool link_is_reset = false; |
---|
922 | 1156 | bool accept_addr = false; |
---|
923 | | - bool reset = true; |
---|
| 1157 | + bool reset = false; |
---|
924 | 1158 | char *if_name; |
---|
925 | 1159 | unsigned long intv; |
---|
926 | 1160 | u16 session; |
---|
.. | .. |
---|
928 | 1162 | *dupl_addr = false; |
---|
929 | 1163 | *respond = false; |
---|
930 | 1164 | |
---|
931 | | - n = tipc_node_create(net, addr, peer_id, capabilities); |
---|
| 1165 | + n = tipc_node_create(net, addr, peer_id, capabilities, hash_mixes, |
---|
| 1166 | + false); |
---|
932 | 1167 | if (!n) |
---|
933 | 1168 | return; |
---|
934 | 1169 | |
---|
.. | .. |
---|
939 | 1174 | /* Prepare to validate requesting node's signature and media address */ |
---|
940 | 1175 | l = le->link; |
---|
941 | 1176 | link_up = l && tipc_link_is_up(l); |
---|
| 1177 | + link_is_reset = l && tipc_link_is_reset(l); |
---|
942 | 1178 | addr_match = l && !memcmp(&le->maddr, maddr, sizeof(*maddr)); |
---|
943 | 1179 | sign_match = (signature == n->signature); |
---|
944 | 1180 | |
---|
945 | 1181 | /* These three flags give us eight permutations: */ |
---|
946 | 1182 | |
---|
947 | 1183 | if (sign_match && addr_match && link_up) { |
---|
948 | | - /* All is fine. Do nothing. */ |
---|
949 | | - reset = false; |
---|
| 1184 | + /* All is fine. Ignore requests. */ |
---|
| 1185 | + /* Peer node is not a container/local namespace */ |
---|
| 1186 | + if (!n->peer_hash_mix) |
---|
| 1187 | + n->peer_hash_mix = hash_mixes; |
---|
950 | 1188 | } else if (sign_match && addr_match && !link_up) { |
---|
951 | 1189 | /* Respond. The link will come up in due time */ |
---|
952 | 1190 | *respond = true; |
---|
.. | .. |
---|
968 | 1206 | */ |
---|
969 | 1207 | accept_addr = true; |
---|
970 | 1208 | *respond = true; |
---|
| 1209 | + reset = true; |
---|
971 | 1210 | } else if (!sign_match && addr_match && link_up) { |
---|
972 | 1211 | /* Peer node rebooted. Two possibilities: |
---|
973 | 1212 | * - Delayed re-discovery; this link endpoint has already |
---|
.. | .. |
---|
999 | 1238 | n->signature = signature; |
---|
1000 | 1239 | accept_addr = true; |
---|
1001 | 1240 | *respond = true; |
---|
| 1241 | + reset = true; |
---|
1002 | 1242 | } |
---|
1003 | 1243 | |
---|
1004 | 1244 | if (!accept_addr) |
---|
.. | .. |
---|
1013 | 1253 | get_random_bytes(&session, sizeof(u16)); |
---|
1014 | 1254 | if (!tipc_link_create(net, if_name, b->identity, b->tolerance, |
---|
1015 | 1255 | b->net_plane, b->mtu, b->priority, |
---|
1016 | | - b->window, session, |
---|
| 1256 | + b->min_win, b->max_win, session, |
---|
1017 | 1257 | tipc_own_addr(net), addr, peer_id, |
---|
1018 | 1258 | n->capabilities, |
---|
1019 | 1259 | tipc_bc_sndlink(n->net), n->bc_entry.link, |
---|
.. | .. |
---|
1022 | 1262 | *respond = false; |
---|
1023 | 1263 | goto exit; |
---|
1024 | 1264 | } |
---|
| 1265 | + trace_tipc_link_reset(l, TIPC_DUMP_ALL, "link created!"); |
---|
1025 | 1266 | tipc_link_reset(l); |
---|
1026 | 1267 | tipc_link_fsm_evt(l, LINK_RESET_EVT); |
---|
1027 | 1268 | if (n->state == NODE_FAILINGOVER) |
---|
1028 | 1269 | tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT); |
---|
| 1270 | + link_is_reset = tipc_link_is_reset(l); |
---|
1029 | 1271 | le->link = l; |
---|
1030 | 1272 | n->link_cnt++; |
---|
1031 | 1273 | tipc_node_calculate_timer(n, l); |
---|
.. | .. |
---|
1038 | 1280 | memcpy(&le->maddr, maddr, sizeof(*maddr)); |
---|
1039 | 1281 | exit: |
---|
1040 | 1282 | tipc_node_write_unlock(n); |
---|
1041 | | - if (reset && l && !tipc_link_is_reset(l)) |
---|
| 1283 | + if (reset && !link_is_reset) |
---|
1042 | 1284 | tipc_node_link_down(n, b->identity, false); |
---|
1043 | 1285 | tipc_node_put(n); |
---|
1044 | 1286 | } |
---|
.. | .. |
---|
1061 | 1303 | |
---|
1062 | 1304 | pr_warn("Resetting all links to %x\n", n->addr); |
---|
1063 | 1305 | |
---|
| 1306 | + trace_tipc_node_reset_links(n, true, " "); |
---|
1064 | 1307 | for (i = 0; i < MAX_BEARERS; i++) { |
---|
1065 | 1308 | tipc_node_link_down(n, i, false); |
---|
1066 | 1309 | } |
---|
.. | .. |
---|
1236 | 1479 | pr_err("Unknown node fsm state %x\n", state); |
---|
1237 | 1480 | break; |
---|
1238 | 1481 | } |
---|
| 1482 | + trace_tipc_node_fsm(n->peer_id, n->state, state, evt); |
---|
1239 | 1483 | n->state = state; |
---|
1240 | 1484 | return; |
---|
1241 | 1485 | |
---|
1242 | 1486 | illegal_evt: |
---|
1243 | 1487 | pr_err("Illegal node fsm evt %x in state %x\n", evt, state); |
---|
| 1488 | + trace_tipc_node_fsm(n->peer_id, n->state, state, evt); |
---|
1244 | 1489 | } |
---|
1245 | 1490 | |
---|
1246 | 1491 | static void node_lost_contact(struct tipc_node *n, |
---|
.. | .. |
---|
1254 | 1499 | |
---|
1255 | 1500 | pr_debug("Lost contact with %x\n", n->addr); |
---|
1256 | 1501 | n->delete_at = jiffies + msecs_to_jiffies(NODE_CLEANUP_AFTER); |
---|
| 1502 | + trace_tipc_node_lost_contact(n, true, " "); |
---|
1257 | 1503 | |
---|
1258 | 1504 | /* Clean up broadcast state */ |
---|
1259 | 1505 | tipc_bcast_remove_peer(n->net, n->bc_entry.link); |
---|
| 1506 | + skb_queue_purge(&n->bc_entry.namedq); |
---|
1260 | 1507 | |
---|
1261 | 1508 | /* Abort any ongoing link failover */ |
---|
1262 | 1509 | for (i = 0; i < MAX_BEARERS; i++) { |
---|
.. | .. |
---|
1267 | 1514 | |
---|
1268 | 1515 | /* Notify publications from this node */ |
---|
1269 | 1516 | n->action_flags |= TIPC_NOTIFY_NODE_DOWN; |
---|
1270 | | - |
---|
| 1517 | + n->peer_net = NULL; |
---|
| 1518 | + n->peer_hash_mix = 0; |
---|
1271 | 1519 | /* Notify sockets connected to node */ |
---|
1272 | 1520 | list_for_each_entry_safe(conn, safe, conns, list) { |
---|
1273 | 1521 | skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG, |
---|
.. | .. |
---|
1285 | 1533 | * tipc_node_get_linkname - get the name of a link |
---|
1286 | 1534 | * |
---|
1287 | 1535 | * @bearer_id: id of the bearer |
---|
1288 | | - * @node: peer node address |
---|
| 1536 | + * @addr: peer node address |
---|
1289 | 1537 | * @linkname: link name output buffer |
---|
1290 | 1538 | * |
---|
1291 | 1539 | * Returns 0 on success |
---|
.. | .. |
---|
1326 | 1574 | if (!hdr) |
---|
1327 | 1575 | return -EMSGSIZE; |
---|
1328 | 1576 | |
---|
1329 | | - attrs = nla_nest_start(msg->skb, TIPC_NLA_NODE); |
---|
| 1577 | + attrs = nla_nest_start_noflag(msg->skb, TIPC_NLA_NODE); |
---|
1330 | 1578 | if (!attrs) |
---|
1331 | 1579 | goto msg_full; |
---|
1332 | 1580 | |
---|
.. | .. |
---|
1349 | 1597 | return -EMSGSIZE; |
---|
1350 | 1598 | } |
---|
1351 | 1599 | |
---|
| 1600 | +static void tipc_lxc_xmit(struct net *peer_net, struct sk_buff_head *list) |
---|
| 1601 | +{ |
---|
| 1602 | + struct tipc_msg *hdr = buf_msg(skb_peek(list)); |
---|
| 1603 | + struct sk_buff_head inputq; |
---|
| 1604 | + |
---|
| 1605 | + switch (msg_user(hdr)) { |
---|
| 1606 | + case TIPC_LOW_IMPORTANCE: |
---|
| 1607 | + case TIPC_MEDIUM_IMPORTANCE: |
---|
| 1608 | + case TIPC_HIGH_IMPORTANCE: |
---|
| 1609 | + case TIPC_CRITICAL_IMPORTANCE: |
---|
| 1610 | + if (msg_connected(hdr) || msg_named(hdr) || |
---|
| 1611 | + msg_direct(hdr)) { |
---|
| 1612 | + tipc_loopback_trace(peer_net, list); |
---|
| 1613 | + spin_lock_init(&list->lock); |
---|
| 1614 | + tipc_sk_rcv(peer_net, list); |
---|
| 1615 | + return; |
---|
| 1616 | + } |
---|
| 1617 | + if (msg_mcast(hdr)) { |
---|
| 1618 | + tipc_loopback_trace(peer_net, list); |
---|
| 1619 | + skb_queue_head_init(&inputq); |
---|
| 1620 | + tipc_sk_mcast_rcv(peer_net, list, &inputq); |
---|
| 1621 | + __skb_queue_purge(list); |
---|
| 1622 | + skb_queue_purge(&inputq); |
---|
| 1623 | + return; |
---|
| 1624 | + } |
---|
| 1625 | + return; |
---|
| 1626 | + case MSG_FRAGMENTER: |
---|
| 1627 | + if (tipc_msg_assemble(list)) { |
---|
| 1628 | + tipc_loopback_trace(peer_net, list); |
---|
| 1629 | + skb_queue_head_init(&inputq); |
---|
| 1630 | + tipc_sk_mcast_rcv(peer_net, list, &inputq); |
---|
| 1631 | + __skb_queue_purge(list); |
---|
| 1632 | + skb_queue_purge(&inputq); |
---|
| 1633 | + } |
---|
| 1634 | + return; |
---|
| 1635 | + case GROUP_PROTOCOL: |
---|
| 1636 | + case CONN_MANAGER: |
---|
| 1637 | + tipc_loopback_trace(peer_net, list); |
---|
| 1638 | + spin_lock_init(&list->lock); |
---|
| 1639 | + tipc_sk_rcv(peer_net, list); |
---|
| 1640 | + return; |
---|
| 1641 | + case LINK_PROTOCOL: |
---|
| 1642 | + case NAME_DISTRIBUTOR: |
---|
| 1643 | + case TUNNEL_PROTOCOL: |
---|
| 1644 | + case BCAST_PROTOCOL: |
---|
| 1645 | + return; |
---|
| 1646 | + default: |
---|
| 1647 | + return; |
---|
| 1648 | + }; |
---|
| 1649 | +} |
---|
| 1650 | + |
---|
1352 | 1651 | /** |
---|
1353 | 1652 | * tipc_node_xmit() is the general link level function for message sending |
---|
1354 | 1653 | * @net: the applicable net namespace |
---|
.. | .. |
---|
1364 | 1663 | struct tipc_link_entry *le = NULL; |
---|
1365 | 1664 | struct tipc_node *n; |
---|
1366 | 1665 | struct sk_buff_head xmitq; |
---|
| 1666 | + bool node_up = false; |
---|
| 1667 | + struct net *peer_net; |
---|
1367 | 1668 | int bearer_id; |
---|
1368 | 1669 | int rc; |
---|
1369 | 1670 | |
---|
1370 | 1671 | if (in_own_node(net, dnode)) { |
---|
| 1672 | + tipc_loopback_trace(net, list); |
---|
1371 | 1673 | spin_lock_init(&list->lock); |
---|
1372 | 1674 | tipc_sk_rcv(net, list); |
---|
1373 | 1675 | return 0; |
---|
.. | .. |
---|
1378 | 1680 | __skb_queue_purge(list); |
---|
1379 | 1681 | return -EHOSTUNREACH; |
---|
1380 | 1682 | } |
---|
| 1683 | + |
---|
| 1684 | + rcu_read_lock(); |
---|
| 1685 | + tipc_node_read_lock(n); |
---|
| 1686 | + node_up = node_is_up(n); |
---|
| 1687 | + peer_net = n->peer_net; |
---|
| 1688 | + tipc_node_read_unlock(n); |
---|
| 1689 | + if (node_up && peer_net && check_net(peer_net)) { |
---|
| 1690 | + /* xmit inner linux container */ |
---|
| 1691 | + tipc_lxc_xmit(peer_net, list); |
---|
| 1692 | + if (likely(skb_queue_empty(list))) { |
---|
| 1693 | + rcu_read_unlock(); |
---|
| 1694 | + tipc_node_put(n); |
---|
| 1695 | + return 0; |
---|
| 1696 | + } |
---|
| 1697 | + } |
---|
| 1698 | + rcu_read_unlock(); |
---|
1381 | 1699 | |
---|
1382 | 1700 | tipc_node_read_lock(n); |
---|
1383 | 1701 | bearer_id = n->active_links[selector & 1]; |
---|
.. | .. |
---|
1398 | 1716 | if (unlikely(rc == -ENOBUFS)) |
---|
1399 | 1717 | tipc_node_link_down(n, bearer_id, false); |
---|
1400 | 1718 | else |
---|
1401 | | - tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr); |
---|
| 1719 | + tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr, n); |
---|
1402 | 1720 | |
---|
1403 | 1721 | tipc_node_put(n); |
---|
1404 | 1722 | |
---|
.. | .. |
---|
1438 | 1756 | return 0; |
---|
1439 | 1757 | } |
---|
1440 | 1758 | |
---|
1441 | | -void tipc_node_broadcast(struct net *net, struct sk_buff *skb) |
---|
| 1759 | +void tipc_node_broadcast(struct net *net, struct sk_buff *skb, int rc_dests) |
---|
1442 | 1760 | { |
---|
| 1761 | + struct sk_buff_head xmitq; |
---|
1443 | 1762 | struct sk_buff *txskb; |
---|
1444 | 1763 | struct tipc_node *n; |
---|
| 1764 | + u16 dummy; |
---|
1445 | 1765 | u32 dst; |
---|
1446 | 1766 | |
---|
| 1767 | + /* Use broadcast if all nodes support it */ |
---|
| 1768 | + if (!rc_dests && tipc_bcast_get_mode(net) != BCLINK_MODE_RCAST) { |
---|
| 1769 | + __skb_queue_head_init(&xmitq); |
---|
| 1770 | + __skb_queue_tail(&xmitq, skb); |
---|
| 1771 | + tipc_bcast_xmit(net, &xmitq, &dummy); |
---|
| 1772 | + return; |
---|
| 1773 | + } |
---|
| 1774 | + |
---|
| 1775 | + /* Otherwise use legacy replicast method */ |
---|
1447 | 1776 | rcu_read_lock(); |
---|
1448 | 1777 | list_for_each_entry_rcu(n, tipc_nodes(net), list) { |
---|
1449 | 1778 | dst = n->addr; |
---|
.. | .. |
---|
1458 | 1787 | tipc_node_xmit_skb(net, txskb, dst, 0); |
---|
1459 | 1788 | } |
---|
1460 | 1789 | rcu_read_unlock(); |
---|
1461 | | - |
---|
1462 | 1790 | kfree_skb(skb); |
---|
1463 | 1791 | } |
---|
1464 | 1792 | |
---|
.. | .. |
---|
1481 | 1809 | struct tipc_link *ucl; |
---|
1482 | 1810 | int rc; |
---|
1483 | 1811 | |
---|
1484 | | - rc = tipc_bcast_sync_rcv(n->net, n->bc_entry.link, hdr); |
---|
| 1812 | + rc = tipc_bcast_sync_rcv(n->net, n->bc_entry.link, hdr, xmitq); |
---|
1485 | 1813 | |
---|
1486 | 1814 | if (rc & TIPC_LINK_DOWN_EVT) { |
---|
1487 | 1815 | tipc_node_reset_links(n); |
---|
.. | .. |
---|
1546 | 1874 | } |
---|
1547 | 1875 | |
---|
1548 | 1876 | if (!skb_queue_empty(&xmitq)) |
---|
1549 | | - tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr); |
---|
| 1877 | + tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr, n); |
---|
1550 | 1878 | |
---|
1551 | 1879 | if (!skb_queue_empty(&be->inputq1)) |
---|
1552 | 1880 | tipc_node_mcast_rcv(n); |
---|
| 1881 | + |
---|
| 1882 | + /* Handle NAME_DISTRIBUTOR messages sent from 1.7 nodes */ |
---|
| 1883 | + if (!skb_queue_empty(&n->bc_entry.namedq)) |
---|
| 1884 | + tipc_named_rcv(net, &n->bc_entry.namedq, |
---|
| 1885 | + &n->bc_entry.named_rcv_nxt, |
---|
| 1886 | + &n->bc_entry.named_open); |
---|
1553 | 1887 | |
---|
1554 | 1888 | /* If reassembly or retransmission failure => reset all links to peer */ |
---|
1555 | 1889 | if (rc & TIPC_LINK_DOWN_EVT) |
---|
.. | .. |
---|
1571 | 1905 | int usr = msg_user(hdr); |
---|
1572 | 1906 | int mtyp = msg_type(hdr); |
---|
1573 | 1907 | u16 oseqno = msg_seqno(hdr); |
---|
1574 | | - u16 iseqno = msg_seqno(msg_get_wrapped(hdr)); |
---|
1575 | 1908 | u16 exp_pkts = msg_msgcnt(hdr); |
---|
1576 | 1909 | u16 rcv_nxt, syncpt, dlv_nxt, inputq_len; |
---|
1577 | 1910 | int state = n->state; |
---|
.. | .. |
---|
1579 | 1912 | struct tipc_media_addr *maddr; |
---|
1580 | 1913 | int pb_id; |
---|
1581 | 1914 | |
---|
| 1915 | + if (trace_tipc_node_check_state_enabled()) { |
---|
| 1916 | + trace_tipc_skb_dump(skb, false, "skb for node state check"); |
---|
| 1917 | + trace_tipc_node_check_state(n, true, " "); |
---|
| 1918 | + } |
---|
1582 | 1919 | l = n->links[bearer_id].link; |
---|
1583 | 1920 | if (!l) |
---|
1584 | 1921 | return false; |
---|
.. | .. |
---|
1596 | 1933 | } |
---|
1597 | 1934 | } |
---|
1598 | 1935 | |
---|
1599 | | - if (!tipc_link_validate_msg(l, hdr)) |
---|
| 1936 | + if (!tipc_link_validate_msg(l, hdr)) { |
---|
| 1937 | + trace_tipc_skb_dump(skb, false, "PROTO invalid (2)!"); |
---|
| 1938 | + trace_tipc_link_dump(l, TIPC_DUMP_NONE, "PROTO invalid (2)!"); |
---|
1600 | 1939 | return false; |
---|
| 1940 | + } |
---|
1601 | 1941 | |
---|
1602 | 1942 | /* Check and update node accesibility if applicable */ |
---|
1603 | 1943 | if (state == SELF_UP_PEER_COMING) { |
---|
.. | .. |
---|
1625 | 1965 | /* Initiate or update failover mode if applicable */ |
---|
1626 | 1966 | if ((usr == TUNNEL_PROTOCOL) && (mtyp == FAILOVER_MSG)) { |
---|
1627 | 1967 | syncpt = oseqno + exp_pkts - 1; |
---|
1628 | | - if (pl && tipc_link_is_up(pl)) { |
---|
| 1968 | + if (pl && !tipc_link_is_reset(pl)) { |
---|
1629 | 1969 | __tipc_node_link_down(n, &pb_id, xmitq, &maddr); |
---|
| 1970 | + trace_tipc_node_link_down(n, true, |
---|
| 1971 | + "node link down <- failover!"); |
---|
1630 | 1972 | tipc_skb_queue_splice_tail_init(tipc_link_inputq(pl), |
---|
1631 | 1973 | tipc_link_inputq(l)); |
---|
1632 | 1974 | } |
---|
| 1975 | + |
---|
1633 | 1976 | /* If parallel link was already down, and this happened before |
---|
1634 | | - * the tunnel link came up, FAILOVER was never sent. Ensure that |
---|
1635 | | - * FAILOVER is sent to get peer out of NODE_FAILINGOVER state. |
---|
| 1977 | + * the tunnel link came up, node failover was never started. |
---|
| 1978 | + * Ensure that a FAILOVER_MSG is sent to get peer out of |
---|
| 1979 | + * NODE_FAILINGOVER state, also this node must accept |
---|
| 1980 | + * TUNNEL_MSGs from peer. |
---|
1636 | 1981 | */ |
---|
1637 | | - if (n->state != NODE_FAILINGOVER && !n->failover_sent) { |
---|
1638 | | - tipc_link_create_dummy_tnl_msg(l, xmitq); |
---|
1639 | | - n->failover_sent = true; |
---|
1640 | | - } |
---|
| 1982 | + if (n->state != NODE_FAILINGOVER) |
---|
| 1983 | + tipc_node_link_failover(n, pl, l, xmitq); |
---|
| 1984 | + |
---|
1641 | 1985 | /* If pkts arrive out of order, use lowest calculated syncpt */ |
---|
1642 | 1986 | if (less(syncpt, n->sync_point)) |
---|
1643 | 1987 | n->sync_point = syncpt; |
---|
.. | .. |
---|
1659 | 2003 | |
---|
1660 | 2004 | /* Initiate synch mode if applicable */ |
---|
1661 | 2005 | if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG) && (oseqno == 1)) { |
---|
1662 | | - syncpt = iseqno + exp_pkts - 1; |
---|
| 2006 | + if (n->capabilities & TIPC_TUNNEL_ENHANCED) |
---|
| 2007 | + syncpt = msg_syncpt(hdr); |
---|
| 2008 | + else |
---|
| 2009 | + syncpt = msg_seqno(msg_inner_hdr(hdr)) + exp_pkts - 1; |
---|
1663 | 2010 | if (!tipc_link_is_up(l)) |
---|
1664 | 2011 | __tipc_node_link_up(n, bearer_id, xmitq); |
---|
1665 | 2012 | if (n->state == SELF_UP_PEER_UP) { |
---|
.. | .. |
---|
1699 | 2046 | * tipc_rcv - process TIPC packets/messages arriving from off-node |
---|
1700 | 2047 | * @net: the applicable net namespace |
---|
1701 | 2048 | * @skb: TIPC packet |
---|
1702 | | - * @bearer: pointer to bearer message arrived on |
---|
| 2049 | + * @b: pointer to bearer message arrived on |
---|
1703 | 2050 | * |
---|
1704 | 2051 | * Invoked with no locks held. Bearer pointer must point to a valid bearer |
---|
1705 | 2052 | * structure (i.e. cannot be NULL), but bearer can be inactive. |
---|
.. | .. |
---|
1707 | 2054 | void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) |
---|
1708 | 2055 | { |
---|
1709 | 2056 | struct sk_buff_head xmitq; |
---|
1710 | | - struct tipc_node *n; |
---|
1711 | | - struct tipc_msg *hdr; |
---|
1712 | | - int bearer_id = b->identity; |
---|
1713 | 2057 | struct tipc_link_entry *le; |
---|
| 2058 | + struct tipc_msg *hdr; |
---|
| 2059 | + struct tipc_node *n; |
---|
| 2060 | + int bearer_id = b->identity; |
---|
1714 | 2061 | u32 self = tipc_own_addr(net); |
---|
1715 | 2062 | int usr, rc = 0; |
---|
1716 | 2063 | u16 bc_ack; |
---|
| 2064 | +#ifdef CONFIG_TIPC_CRYPTO |
---|
| 2065 | + struct tipc_ehdr *ehdr; |
---|
1717 | 2066 | |
---|
1718 | | - __skb_queue_head_init(&xmitq); |
---|
| 2067 | + /* Check if message must be decrypted first */ |
---|
| 2068 | + if (TIPC_SKB_CB(skb)->decrypted || !tipc_ehdr_validate(skb)) |
---|
| 2069 | + goto rcv; |
---|
1719 | 2070 | |
---|
| 2071 | + ehdr = (struct tipc_ehdr *)skb->data; |
---|
| 2072 | + if (likely(ehdr->user != LINK_CONFIG)) { |
---|
| 2073 | + n = tipc_node_find(net, ntohl(ehdr->addr)); |
---|
| 2074 | + if (unlikely(!n)) |
---|
| 2075 | + goto discard; |
---|
| 2076 | + } else { |
---|
| 2077 | + n = tipc_node_find_by_id(net, ehdr->id); |
---|
| 2078 | + } |
---|
| 2079 | + tipc_crypto_rcv(net, (n) ? n->crypto_rx : NULL, &skb, b); |
---|
| 2080 | + if (!skb) |
---|
| 2081 | + return; |
---|
| 2082 | + |
---|
| 2083 | +rcv: |
---|
| 2084 | +#endif |
---|
1720 | 2085 | /* Ensure message is well-formed before touching the header */ |
---|
1721 | 2086 | if (unlikely(!tipc_msg_validate(&skb))) |
---|
1722 | 2087 | goto discard; |
---|
| 2088 | + __skb_queue_head_init(&xmitq); |
---|
1723 | 2089 | hdr = buf_msg(skb); |
---|
1724 | 2090 | usr = msg_user(hdr); |
---|
1725 | 2091 | bc_ack = msg_bcast_ack(hdr); |
---|
.. | .. |
---|
1743 | 2109 | le = &n->links[bearer_id]; |
---|
1744 | 2110 | |
---|
1745 | 2111 | /* Ensure broadcast reception is in synch with peer's send state */ |
---|
1746 | | - if (unlikely(usr == LINK_PROTOCOL)) |
---|
| 2112 | + if (unlikely(usr == LINK_PROTOCOL)) { |
---|
| 2113 | + if (unlikely(skb_linearize(skb))) { |
---|
| 2114 | + tipc_node_put(n); |
---|
| 2115 | + goto discard; |
---|
| 2116 | + } |
---|
| 2117 | + hdr = buf_msg(skb); |
---|
1747 | 2118 | tipc_node_bc_sync_rcv(n, hdr, bearer_id, &xmitq); |
---|
1748 | | - else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack)) |
---|
| 2119 | + } else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack)) { |
---|
1749 | 2120 | tipc_bcast_ack_rcv(net, n->bc_entry.link, hdr); |
---|
| 2121 | + } |
---|
1750 | 2122 | |
---|
1751 | 2123 | /* Receive packet directly if conditions permit */ |
---|
1752 | 2124 | tipc_node_read_lock(n); |
---|
.. | .. |
---|
1763 | 2135 | /* Check/update node state before receiving */ |
---|
1764 | 2136 | if (unlikely(skb)) { |
---|
1765 | 2137 | if (unlikely(skb_linearize(skb))) |
---|
1766 | | - goto discard; |
---|
| 2138 | + goto out_node_put; |
---|
1767 | 2139 | tipc_node_write_lock(n); |
---|
1768 | 2140 | if (tipc_node_check_state(n, skb, bearer_id, &xmitq)) { |
---|
1769 | 2141 | if (le->link) { |
---|
.. | .. |
---|
1781 | 2153 | tipc_node_link_down(n, bearer_id, false); |
---|
1782 | 2154 | |
---|
1783 | 2155 | if (unlikely(!skb_queue_empty(&n->bc_entry.namedq))) |
---|
1784 | | - tipc_named_rcv(net, &n->bc_entry.namedq); |
---|
| 2156 | + tipc_named_rcv(net, &n->bc_entry.namedq, |
---|
| 2157 | + &n->bc_entry.named_rcv_nxt, |
---|
| 2158 | + &n->bc_entry.named_open); |
---|
1785 | 2159 | |
---|
1786 | 2160 | if (unlikely(!skb_queue_empty(&n->bc_entry.inputq1))) |
---|
1787 | 2161 | tipc_node_mcast_rcv(n); |
---|
.. | .. |
---|
1790 | 2164 | tipc_sk_rcv(net, &le->inputq); |
---|
1791 | 2165 | |
---|
1792 | 2166 | if (!skb_queue_empty(&xmitq)) |
---|
1793 | | - tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr); |
---|
| 2167 | + tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr, n); |
---|
1794 | 2168 | |
---|
| 2169 | +out_node_put: |
---|
1795 | 2170 | tipc_node_put(n); |
---|
1796 | 2171 | discard: |
---|
1797 | 2172 | kfree_skb(skb); |
---|
.. | .. |
---|
1819 | 2194 | &xmitq); |
---|
1820 | 2195 | else if (prop == TIPC_NLA_PROP_MTU) |
---|
1821 | 2196 | tipc_link_set_mtu(e->link, b->mtu); |
---|
| 2197 | + |
---|
| 2198 | + /* Update MTU for node link entry */ |
---|
| 2199 | + e->mtu = tipc_link_mss(e->link); |
---|
1822 | 2200 | } |
---|
| 2201 | + |
---|
1823 | 2202 | tipc_node_write_unlock(n); |
---|
1824 | | - tipc_bearer_xmit(net, bearer_id, &xmitq, &e->maddr); |
---|
| 2203 | + tipc_bearer_xmit(net, bearer_id, &xmitq, &e->maddr, NULL); |
---|
1825 | 2204 | } |
---|
1826 | 2205 | |
---|
1827 | 2206 | rcu_read_unlock(); |
---|
.. | .. |
---|
1832 | 2211 | struct net *net = sock_net(skb->sk); |
---|
1833 | 2212 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
---|
1834 | 2213 | struct nlattr *attrs[TIPC_NLA_NET_MAX + 1]; |
---|
1835 | | - struct tipc_node *peer; |
---|
| 2214 | + struct tipc_node *peer, *temp_node; |
---|
1836 | 2215 | u32 addr; |
---|
1837 | 2216 | int err; |
---|
1838 | 2217 | |
---|
.. | .. |
---|
1840 | 2219 | if (!info->attrs[TIPC_NLA_NET]) |
---|
1841 | 2220 | return -EINVAL; |
---|
1842 | 2221 | |
---|
1843 | | - err = nla_parse_nested(attrs, TIPC_NLA_NET_MAX, |
---|
1844 | | - info->attrs[TIPC_NLA_NET], tipc_nl_net_policy, |
---|
1845 | | - info->extack); |
---|
| 2222 | + err = nla_parse_nested_deprecated(attrs, TIPC_NLA_NET_MAX, |
---|
| 2223 | + info->attrs[TIPC_NLA_NET], |
---|
| 2224 | + tipc_nl_net_policy, info->extack); |
---|
1846 | 2225 | if (err) |
---|
1847 | 2226 | return err; |
---|
1848 | 2227 | |
---|
.. | .. |
---|
1873 | 2252 | tipc_node_write_unlock(peer); |
---|
1874 | 2253 | tipc_node_delete(peer); |
---|
1875 | 2254 | |
---|
| 2255 | + /* Calculate cluster capabilities */ |
---|
| 2256 | + tn->capabilities = TIPC_NODE_CAPABILITIES; |
---|
| 2257 | + list_for_each_entry_rcu(temp_node, &tn->node_list, list) { |
---|
| 2258 | + tn->capabilities &= temp_node->capabilities; |
---|
| 2259 | + } |
---|
| 2260 | + tipc_bcast_toggle_rcast(net, (tn->capabilities & TIPC_BCAST_RCAST)); |
---|
1876 | 2261 | err = 0; |
---|
1877 | 2262 | err_out: |
---|
1878 | 2263 | tipc_node_put(peer); |
---|
.. | .. |
---|
1917 | 2302 | } |
---|
1918 | 2303 | |
---|
1919 | 2304 | list_for_each_entry_rcu(node, &tn->node_list, list) { |
---|
| 2305 | + if (node->preliminary) |
---|
| 2306 | + continue; |
---|
1920 | 2307 | if (last_addr) { |
---|
1921 | 2308 | if (node->addr == last_addr) |
---|
1922 | 2309 | last_addr = 0; |
---|
.. | .. |
---|
1998 | 2385 | if (!info->attrs[TIPC_NLA_LINK]) |
---|
1999 | 2386 | return -EINVAL; |
---|
2000 | 2387 | |
---|
2001 | | - err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX, |
---|
2002 | | - info->attrs[TIPC_NLA_LINK], |
---|
2003 | | - tipc_nl_link_policy, info->extack); |
---|
| 2388 | + err = nla_parse_nested_deprecated(attrs, TIPC_NLA_LINK_MAX, |
---|
| 2389 | + info->attrs[TIPC_NLA_LINK], |
---|
| 2390 | + tipc_nl_link_policy, info->extack); |
---|
2004 | 2391 | if (err) |
---|
2005 | 2392 | return err; |
---|
2006 | 2393 | |
---|
.. | .. |
---|
2027 | 2414 | if (attrs[TIPC_NLA_LINK_PROP]) { |
---|
2028 | 2415 | struct nlattr *props[TIPC_NLA_PROP_MAX + 1]; |
---|
2029 | 2416 | |
---|
2030 | | - err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP], |
---|
2031 | | - props); |
---|
| 2417 | + err = tipc_nl_parse_link_prop(attrs[TIPC_NLA_LINK_PROP], props); |
---|
2032 | 2418 | if (err) { |
---|
2033 | 2419 | res = err; |
---|
2034 | 2420 | goto out; |
---|
.. | .. |
---|
2047 | 2433 | tipc_link_set_prio(link, prio, &xmitq); |
---|
2048 | 2434 | } |
---|
2049 | 2435 | if (props[TIPC_NLA_PROP_WIN]) { |
---|
2050 | | - u32 win; |
---|
| 2436 | + u32 max_win; |
---|
2051 | 2437 | |
---|
2052 | | - win = nla_get_u32(props[TIPC_NLA_PROP_WIN]); |
---|
2053 | | - tipc_link_set_queue_limits(link, win); |
---|
| 2438 | + max_win = nla_get_u32(props[TIPC_NLA_PROP_WIN]); |
---|
| 2439 | + tipc_link_set_queue_limits(link, |
---|
| 2440 | + tipc_link_min_win(link), |
---|
| 2441 | + max_win); |
---|
2054 | 2442 | } |
---|
2055 | 2443 | } |
---|
2056 | 2444 | |
---|
2057 | 2445 | out: |
---|
2058 | 2446 | tipc_node_read_unlock(node); |
---|
2059 | | - tipc_bearer_xmit(net, bearer_id, &xmitq, &node->links[bearer_id].maddr); |
---|
| 2447 | + tipc_bearer_xmit(net, bearer_id, &xmitq, &node->links[bearer_id].maddr, |
---|
| 2448 | + NULL); |
---|
2060 | 2449 | return res; |
---|
2061 | 2450 | } |
---|
2062 | 2451 | |
---|
.. | .. |
---|
2074 | 2463 | if (!info->attrs[TIPC_NLA_LINK]) |
---|
2075 | 2464 | return -EINVAL; |
---|
2076 | 2465 | |
---|
2077 | | - err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX, |
---|
2078 | | - info->attrs[TIPC_NLA_LINK], |
---|
2079 | | - tipc_nl_link_policy, info->extack); |
---|
| 2466 | + err = nla_parse_nested_deprecated(attrs, TIPC_NLA_LINK_MAX, |
---|
| 2467 | + info->attrs[TIPC_NLA_LINK], |
---|
| 2468 | + tipc_nl_link_policy, info->extack); |
---|
2080 | 2469 | if (err) |
---|
2081 | 2470 | return err; |
---|
2082 | 2471 | |
---|
.. | .. |
---|
2090 | 2479 | return -ENOMEM; |
---|
2091 | 2480 | |
---|
2092 | 2481 | if (strcmp(name, tipc_bclink_name) == 0) { |
---|
2093 | | - err = tipc_nl_add_bc_link(net, &msg); |
---|
| 2482 | + err = tipc_nl_add_bc_link(net, &msg, tipc_net(net)->bcl); |
---|
2094 | 2483 | if (err) |
---|
2095 | 2484 | goto err_free; |
---|
2096 | 2485 | } else { |
---|
.. | .. |
---|
2134 | 2523 | struct tipc_node *node; |
---|
2135 | 2524 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; |
---|
2136 | 2525 | struct net *net = sock_net(skb->sk); |
---|
| 2526 | + struct tipc_net *tn = tipc_net(net); |
---|
2137 | 2527 | struct tipc_link_entry *le; |
---|
2138 | 2528 | |
---|
2139 | 2529 | if (!info->attrs[TIPC_NLA_LINK]) |
---|
2140 | 2530 | return -EINVAL; |
---|
2141 | 2531 | |
---|
2142 | | - err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX, |
---|
2143 | | - info->attrs[TIPC_NLA_LINK], |
---|
2144 | | - tipc_nl_link_policy, info->extack); |
---|
| 2532 | + err = nla_parse_nested_deprecated(attrs, TIPC_NLA_LINK_MAX, |
---|
| 2533 | + info->attrs[TIPC_NLA_LINK], |
---|
| 2534 | + tipc_nl_link_policy, info->extack); |
---|
2145 | 2535 | if (err) |
---|
2146 | 2536 | return err; |
---|
2147 | 2537 | |
---|
.. | .. |
---|
2150 | 2540 | |
---|
2151 | 2541 | link_name = nla_data(attrs[TIPC_NLA_LINK_NAME]); |
---|
2152 | 2542 | |
---|
2153 | | - if (strcmp(link_name, tipc_bclink_name) == 0) { |
---|
2154 | | - err = tipc_bclink_reset_stats(net); |
---|
| 2543 | + err = -EINVAL; |
---|
| 2544 | + if (!strcmp(link_name, tipc_bclink_name)) { |
---|
| 2545 | + err = tipc_bclink_reset_stats(net, tipc_bc_sndlink(net)); |
---|
2155 | 2546 | if (err) |
---|
2156 | 2547 | return err; |
---|
2157 | 2548 | return 0; |
---|
| 2549 | + } else if (strstr(link_name, tipc_bclink_name)) { |
---|
| 2550 | + rcu_read_lock(); |
---|
| 2551 | + list_for_each_entry_rcu(node, &tn->node_list, list) { |
---|
| 2552 | + tipc_node_read_lock(node); |
---|
| 2553 | + link = node->bc_entry.link; |
---|
| 2554 | + if (link && !strcmp(link_name, tipc_link_name(link))) { |
---|
| 2555 | + err = tipc_bclink_reset_stats(net, link); |
---|
| 2556 | + tipc_node_read_unlock(node); |
---|
| 2557 | + break; |
---|
| 2558 | + } |
---|
| 2559 | + tipc_node_read_unlock(node); |
---|
| 2560 | + } |
---|
| 2561 | + rcu_read_unlock(); |
---|
| 2562 | + return err; |
---|
2158 | 2563 | } |
---|
2159 | 2564 | |
---|
2160 | 2565 | node = tipc_node_find_by_name(net, link_name, &bearer_id); |
---|
.. | .. |
---|
2178 | 2583 | |
---|
2179 | 2584 | /* Caller should hold node lock */ |
---|
2180 | 2585 | static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg, |
---|
2181 | | - struct tipc_node *node, u32 *prev_link) |
---|
| 2586 | + struct tipc_node *node, u32 *prev_link, |
---|
| 2587 | + bool bc_link) |
---|
2182 | 2588 | { |
---|
2183 | 2589 | u32 i; |
---|
2184 | 2590 | int err; |
---|
.. | .. |
---|
2194 | 2600 | if (err) |
---|
2195 | 2601 | return err; |
---|
2196 | 2602 | } |
---|
| 2603 | + |
---|
| 2604 | + if (bc_link) { |
---|
| 2605 | + *prev_link = i; |
---|
| 2606 | + err = tipc_nl_add_bc_link(net, msg, node->bc_entry.link); |
---|
| 2607 | + if (err) |
---|
| 2608 | + return err; |
---|
| 2609 | + } |
---|
| 2610 | + |
---|
2197 | 2611 | *prev_link = 0; |
---|
2198 | 2612 | |
---|
2199 | 2613 | return 0; |
---|
.. | .. |
---|
2202 | 2616 | int tipc_nl_node_dump_link(struct sk_buff *skb, struct netlink_callback *cb) |
---|
2203 | 2617 | { |
---|
2204 | 2618 | struct net *net = sock_net(skb->sk); |
---|
| 2619 | + struct nlattr **attrs = genl_dumpit_info(cb)->attrs; |
---|
| 2620 | + struct nlattr *link[TIPC_NLA_LINK_MAX + 1]; |
---|
2205 | 2621 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
---|
2206 | 2622 | struct tipc_node *node; |
---|
2207 | 2623 | struct tipc_nl_msg msg; |
---|
2208 | 2624 | u32 prev_node = cb->args[0]; |
---|
2209 | 2625 | u32 prev_link = cb->args[1]; |
---|
2210 | 2626 | int done = cb->args[2]; |
---|
| 2627 | + bool bc_link = cb->args[3]; |
---|
2211 | 2628 | int err; |
---|
2212 | 2629 | |
---|
2213 | 2630 | if (done) |
---|
2214 | 2631 | return 0; |
---|
| 2632 | + |
---|
| 2633 | + if (!prev_node) { |
---|
| 2634 | + /* Check if broadcast-receiver links dumping is needed */ |
---|
| 2635 | + if (attrs && attrs[TIPC_NLA_LINK]) { |
---|
| 2636 | + err = nla_parse_nested_deprecated(link, |
---|
| 2637 | + TIPC_NLA_LINK_MAX, |
---|
| 2638 | + attrs[TIPC_NLA_LINK], |
---|
| 2639 | + tipc_nl_link_policy, |
---|
| 2640 | + NULL); |
---|
| 2641 | + if (unlikely(err)) |
---|
| 2642 | + return err; |
---|
| 2643 | + if (unlikely(!link[TIPC_NLA_LINK_BROADCAST])) |
---|
| 2644 | + return -EINVAL; |
---|
| 2645 | + bc_link = true; |
---|
| 2646 | + } |
---|
| 2647 | + } |
---|
2215 | 2648 | |
---|
2216 | 2649 | msg.skb = skb; |
---|
2217 | 2650 | msg.portid = NETLINK_CB(cb->skb).portid; |
---|
.. | .. |
---|
2236 | 2669 | list) { |
---|
2237 | 2670 | tipc_node_read_lock(node); |
---|
2238 | 2671 | err = __tipc_nl_add_node_links(net, &msg, node, |
---|
2239 | | - &prev_link); |
---|
| 2672 | + &prev_link, bc_link); |
---|
2240 | 2673 | tipc_node_read_unlock(node); |
---|
2241 | 2674 | if (err) |
---|
2242 | 2675 | goto out; |
---|
.. | .. |
---|
2244 | 2677 | prev_node = node->addr; |
---|
2245 | 2678 | } |
---|
2246 | 2679 | } else { |
---|
2247 | | - err = tipc_nl_add_bc_link(net, &msg); |
---|
| 2680 | + err = tipc_nl_add_bc_link(net, &msg, tn->bcl); |
---|
2248 | 2681 | if (err) |
---|
2249 | 2682 | goto out; |
---|
2250 | 2683 | |
---|
2251 | 2684 | list_for_each_entry_rcu(node, &tn->node_list, list) { |
---|
2252 | 2685 | tipc_node_read_lock(node); |
---|
2253 | 2686 | err = __tipc_nl_add_node_links(net, &msg, node, |
---|
2254 | | - &prev_link); |
---|
| 2687 | + &prev_link, bc_link); |
---|
2255 | 2688 | tipc_node_read_unlock(node); |
---|
2256 | 2689 | if (err) |
---|
2257 | 2690 | goto out; |
---|
.. | .. |
---|
2266 | 2699 | cb->args[0] = prev_node; |
---|
2267 | 2700 | cb->args[1] = prev_link; |
---|
2268 | 2701 | cb->args[2] = done; |
---|
| 2702 | + cb->args[3] = bc_link; |
---|
2269 | 2703 | |
---|
2270 | 2704 | return skb->len; |
---|
2271 | 2705 | } |
---|
.. | .. |
---|
2279 | 2713 | if (!info->attrs[TIPC_NLA_MON]) |
---|
2280 | 2714 | return -EINVAL; |
---|
2281 | 2715 | |
---|
2282 | | - err = nla_parse_nested(attrs, TIPC_NLA_MON_MAX, |
---|
2283 | | - info->attrs[TIPC_NLA_MON], |
---|
2284 | | - tipc_nl_monitor_policy, info->extack); |
---|
| 2716 | + err = nla_parse_nested_deprecated(attrs, TIPC_NLA_MON_MAX, |
---|
| 2717 | + info->attrs[TIPC_NLA_MON], |
---|
| 2718 | + tipc_nl_monitor_policy, |
---|
| 2719 | + info->extack); |
---|
2285 | 2720 | if (err) |
---|
2286 | 2721 | return err; |
---|
2287 | 2722 | |
---|
.. | .. |
---|
2308 | 2743 | if (!hdr) |
---|
2309 | 2744 | return -EMSGSIZE; |
---|
2310 | 2745 | |
---|
2311 | | - attrs = nla_nest_start(msg->skb, TIPC_NLA_MON); |
---|
| 2746 | + attrs = nla_nest_start_noflag(msg->skb, TIPC_NLA_MON); |
---|
2312 | 2747 | if (!attrs) |
---|
2313 | 2748 | goto msg_full; |
---|
2314 | 2749 | |
---|
.. | .. |
---|
2389 | 2824 | int err; |
---|
2390 | 2825 | |
---|
2391 | 2826 | if (!prev_node) { |
---|
2392 | | - struct nlattr **attrs; |
---|
| 2827 | + struct nlattr **attrs = genl_dumpit_info(cb)->attrs; |
---|
2393 | 2828 | struct nlattr *mon[TIPC_NLA_MON_MAX + 1]; |
---|
2394 | | - |
---|
2395 | | - err = tipc_nlmsg_parse(cb->nlh, &attrs); |
---|
2396 | | - if (err) |
---|
2397 | | - return err; |
---|
2398 | 2829 | |
---|
2399 | 2830 | if (!attrs[TIPC_NLA_MON]) |
---|
2400 | 2831 | return -EINVAL; |
---|
2401 | 2832 | |
---|
2402 | | - err = nla_parse_nested(mon, TIPC_NLA_MON_MAX, |
---|
2403 | | - attrs[TIPC_NLA_MON], |
---|
2404 | | - tipc_nl_monitor_policy, NULL); |
---|
| 2833 | + err = nla_parse_nested_deprecated(mon, TIPC_NLA_MON_MAX, |
---|
| 2834 | + attrs[TIPC_NLA_MON], |
---|
| 2835 | + tipc_nl_monitor_policy, |
---|
| 2836 | + NULL); |
---|
2405 | 2837 | if (err) |
---|
2406 | 2838 | return err; |
---|
2407 | 2839 | |
---|
.. | .. |
---|
2433 | 2865 | |
---|
2434 | 2866 | return skb->len; |
---|
2435 | 2867 | } |
---|
| 2868 | + |
---|
| 2869 | +#ifdef CONFIG_TIPC_CRYPTO |
---|
| 2870 | +static int tipc_nl_retrieve_key(struct nlattr **attrs, |
---|
| 2871 | + struct tipc_aead_key **pkey) |
---|
| 2872 | +{ |
---|
| 2873 | + struct nlattr *attr = attrs[TIPC_NLA_NODE_KEY]; |
---|
| 2874 | + struct tipc_aead_key *key; |
---|
| 2875 | + |
---|
| 2876 | + if (!attr) |
---|
| 2877 | + return -ENODATA; |
---|
| 2878 | + |
---|
| 2879 | + if (nla_len(attr) < sizeof(*key)) |
---|
| 2880 | + return -EINVAL; |
---|
| 2881 | + key = (struct tipc_aead_key *)nla_data(attr); |
---|
| 2882 | + if (key->keylen > TIPC_AEAD_KEYLEN_MAX || |
---|
| 2883 | + nla_len(attr) < tipc_aead_key_size(key)) |
---|
| 2884 | + return -EINVAL; |
---|
| 2885 | + |
---|
| 2886 | + *pkey = key; |
---|
| 2887 | + return 0; |
---|
| 2888 | +} |
---|
| 2889 | + |
---|
| 2890 | +static int tipc_nl_retrieve_nodeid(struct nlattr **attrs, u8 **node_id) |
---|
| 2891 | +{ |
---|
| 2892 | + struct nlattr *attr = attrs[TIPC_NLA_NODE_ID]; |
---|
| 2893 | + |
---|
| 2894 | + if (!attr) |
---|
| 2895 | + return -ENODATA; |
---|
| 2896 | + |
---|
| 2897 | + if (nla_len(attr) < TIPC_NODEID_LEN) |
---|
| 2898 | + return -EINVAL; |
---|
| 2899 | + |
---|
| 2900 | + *node_id = (u8 *)nla_data(attr); |
---|
| 2901 | + return 0; |
---|
| 2902 | +} |
---|
| 2903 | + |
---|
| 2904 | +static int tipc_nl_retrieve_rekeying(struct nlattr **attrs, u32 *intv) |
---|
| 2905 | +{ |
---|
| 2906 | + struct nlattr *attr = attrs[TIPC_NLA_NODE_REKEYING]; |
---|
| 2907 | + |
---|
| 2908 | + if (!attr) |
---|
| 2909 | + return -ENODATA; |
---|
| 2910 | + |
---|
| 2911 | + *intv = nla_get_u32(attr); |
---|
| 2912 | + return 0; |
---|
| 2913 | +} |
---|
| 2914 | + |
---|
| 2915 | +static int __tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info) |
---|
| 2916 | +{ |
---|
| 2917 | + struct nlattr *attrs[TIPC_NLA_NODE_MAX + 1]; |
---|
| 2918 | + struct net *net = sock_net(skb->sk); |
---|
| 2919 | + struct tipc_crypto *tx = tipc_net(net)->crypto_tx, *c = tx; |
---|
| 2920 | + struct tipc_node *n = NULL; |
---|
| 2921 | + struct tipc_aead_key *ukey; |
---|
| 2922 | + bool rekeying = true, master_key = false; |
---|
| 2923 | + u8 *id, *own_id, mode; |
---|
| 2924 | + u32 intv = 0; |
---|
| 2925 | + int rc = 0; |
---|
| 2926 | + |
---|
| 2927 | + if (!info->attrs[TIPC_NLA_NODE]) |
---|
| 2928 | + return -EINVAL; |
---|
| 2929 | + |
---|
| 2930 | + rc = nla_parse_nested(attrs, TIPC_NLA_NODE_MAX, |
---|
| 2931 | + info->attrs[TIPC_NLA_NODE], |
---|
| 2932 | + tipc_nl_node_policy, info->extack); |
---|
| 2933 | + if (rc) |
---|
| 2934 | + return rc; |
---|
| 2935 | + |
---|
| 2936 | + own_id = tipc_own_id(net); |
---|
| 2937 | + if (!own_id) { |
---|
| 2938 | + GENL_SET_ERR_MSG(info, "not found own node identity (set id?)"); |
---|
| 2939 | + return -EPERM; |
---|
| 2940 | + } |
---|
| 2941 | + |
---|
| 2942 | + rc = tipc_nl_retrieve_rekeying(attrs, &intv); |
---|
| 2943 | + if (rc == -ENODATA) |
---|
| 2944 | + rekeying = false; |
---|
| 2945 | + |
---|
| 2946 | + rc = tipc_nl_retrieve_key(attrs, &ukey); |
---|
| 2947 | + if (rc == -ENODATA && rekeying) |
---|
| 2948 | + goto rekeying; |
---|
| 2949 | + else if (rc) |
---|
| 2950 | + return rc; |
---|
| 2951 | + |
---|
| 2952 | + rc = tipc_aead_key_validate(ukey, info); |
---|
| 2953 | + if (rc) |
---|
| 2954 | + return rc; |
---|
| 2955 | + |
---|
| 2956 | + rc = tipc_nl_retrieve_nodeid(attrs, &id); |
---|
| 2957 | + switch (rc) { |
---|
| 2958 | + case -ENODATA: |
---|
| 2959 | + mode = CLUSTER_KEY; |
---|
| 2960 | + master_key = !!(attrs[TIPC_NLA_NODE_KEY_MASTER]); |
---|
| 2961 | + break; |
---|
| 2962 | + case 0: |
---|
| 2963 | + mode = PER_NODE_KEY; |
---|
| 2964 | + if (memcmp(id, own_id, NODE_ID_LEN)) { |
---|
| 2965 | + n = tipc_node_find_by_id(net, id) ?: |
---|
| 2966 | + tipc_node_create(net, 0, id, 0xffffu, 0, true); |
---|
| 2967 | + if (unlikely(!n)) |
---|
| 2968 | + return -ENOMEM; |
---|
| 2969 | + c = n->crypto_rx; |
---|
| 2970 | + } |
---|
| 2971 | + break; |
---|
| 2972 | + default: |
---|
| 2973 | + return rc; |
---|
| 2974 | + } |
---|
| 2975 | + |
---|
| 2976 | + /* Initiate the TX/RX key */ |
---|
| 2977 | + rc = tipc_crypto_key_init(c, ukey, mode, master_key); |
---|
| 2978 | + if (n) |
---|
| 2979 | + tipc_node_put(n); |
---|
| 2980 | + |
---|
| 2981 | + if (unlikely(rc < 0)) { |
---|
| 2982 | + GENL_SET_ERR_MSG(info, "unable to initiate or attach new key"); |
---|
| 2983 | + return rc; |
---|
| 2984 | + } else if (c == tx) { |
---|
| 2985 | + /* Distribute TX key but not master one */ |
---|
| 2986 | + if (!master_key && tipc_crypto_key_distr(tx, rc, NULL)) |
---|
| 2987 | + GENL_SET_ERR_MSG(info, "failed to replicate new key"); |
---|
| 2988 | +rekeying: |
---|
| 2989 | + /* Schedule TX rekeying if needed */ |
---|
| 2990 | + tipc_crypto_rekeying_sched(tx, rekeying, intv); |
---|
| 2991 | + } |
---|
| 2992 | + |
---|
| 2993 | + return 0; |
---|
| 2994 | +} |
---|
| 2995 | + |
---|
| 2996 | +int tipc_nl_node_set_key(struct sk_buff *skb, struct genl_info *info) |
---|
| 2997 | +{ |
---|
| 2998 | + int err; |
---|
| 2999 | + |
---|
| 3000 | + rtnl_lock(); |
---|
| 3001 | + err = __tipc_nl_node_set_key(skb, info); |
---|
| 3002 | + rtnl_unlock(); |
---|
| 3003 | + |
---|
| 3004 | + return err; |
---|
| 3005 | +} |
---|
| 3006 | + |
---|
| 3007 | +static int __tipc_nl_node_flush_key(struct sk_buff *skb, |
---|
| 3008 | + struct genl_info *info) |
---|
| 3009 | +{ |
---|
| 3010 | + struct net *net = sock_net(skb->sk); |
---|
| 3011 | + struct tipc_net *tn = tipc_net(net); |
---|
| 3012 | + struct tipc_node *n; |
---|
| 3013 | + |
---|
| 3014 | + tipc_crypto_key_flush(tn->crypto_tx); |
---|
| 3015 | + rcu_read_lock(); |
---|
| 3016 | + list_for_each_entry_rcu(n, &tn->node_list, list) |
---|
| 3017 | + tipc_crypto_key_flush(n->crypto_rx); |
---|
| 3018 | + rcu_read_unlock(); |
---|
| 3019 | + |
---|
| 3020 | + return 0; |
---|
| 3021 | +} |
---|
| 3022 | + |
---|
| 3023 | +int tipc_nl_node_flush_key(struct sk_buff *skb, struct genl_info *info) |
---|
| 3024 | +{ |
---|
| 3025 | + int err; |
---|
| 3026 | + |
---|
| 3027 | + rtnl_lock(); |
---|
| 3028 | + err = __tipc_nl_node_flush_key(skb, info); |
---|
| 3029 | + rtnl_unlock(); |
---|
| 3030 | + |
---|
| 3031 | + return err; |
---|
| 3032 | +} |
---|
| 3033 | +#endif |
---|
| 3034 | + |
---|
| 3035 | +/** |
---|
| 3036 | + * tipc_node_dump - dump TIPC node data |
---|
| 3037 | + * @n: tipc node to be dumped |
---|
| 3038 | + * @more: dump more? |
---|
| 3039 | + * - false: dump only tipc node data |
---|
| 3040 | + * - true: dump node link data as well |
---|
| 3041 | + * @buf: returned buffer of dump data in format |
---|
| 3042 | + */ |
---|
| 3043 | +int tipc_node_dump(struct tipc_node *n, bool more, char *buf) |
---|
| 3044 | +{ |
---|
| 3045 | + int i = 0; |
---|
| 3046 | + size_t sz = (more) ? NODE_LMAX : NODE_LMIN; |
---|
| 3047 | + |
---|
| 3048 | + if (!n) { |
---|
| 3049 | + i += scnprintf(buf, sz, "node data: (null)\n"); |
---|
| 3050 | + return i; |
---|
| 3051 | + } |
---|
| 3052 | + |
---|
| 3053 | + i += scnprintf(buf, sz, "node data: %x", n->addr); |
---|
| 3054 | + i += scnprintf(buf + i, sz - i, " %x", n->state); |
---|
| 3055 | + i += scnprintf(buf + i, sz - i, " %d", n->active_links[0]); |
---|
| 3056 | + i += scnprintf(buf + i, sz - i, " %d", n->active_links[1]); |
---|
| 3057 | + i += scnprintf(buf + i, sz - i, " %x", n->action_flags); |
---|
| 3058 | + i += scnprintf(buf + i, sz - i, " %u", n->failover_sent); |
---|
| 3059 | + i += scnprintf(buf + i, sz - i, " %u", n->sync_point); |
---|
| 3060 | + i += scnprintf(buf + i, sz - i, " %d", n->link_cnt); |
---|
| 3061 | + i += scnprintf(buf + i, sz - i, " %u", n->working_links); |
---|
| 3062 | + i += scnprintf(buf + i, sz - i, " %x", n->capabilities); |
---|
| 3063 | + i += scnprintf(buf + i, sz - i, " %lu\n", n->keepalive_intv); |
---|
| 3064 | + |
---|
| 3065 | + if (!more) |
---|
| 3066 | + return i; |
---|
| 3067 | + |
---|
| 3068 | + i += scnprintf(buf + i, sz - i, "link_entry[0]:\n"); |
---|
| 3069 | + i += scnprintf(buf + i, sz - i, " mtu: %u\n", n->links[0].mtu); |
---|
| 3070 | + i += scnprintf(buf + i, sz - i, " media: "); |
---|
| 3071 | + i += tipc_media_addr_printf(buf + i, sz - i, &n->links[0].maddr); |
---|
| 3072 | + i += scnprintf(buf + i, sz - i, "\n"); |
---|
| 3073 | + i += tipc_link_dump(n->links[0].link, TIPC_DUMP_NONE, buf + i); |
---|
| 3074 | + i += scnprintf(buf + i, sz - i, " inputq: "); |
---|
| 3075 | + i += tipc_list_dump(&n->links[0].inputq, false, buf + i); |
---|
| 3076 | + |
---|
| 3077 | + i += scnprintf(buf + i, sz - i, "link_entry[1]:\n"); |
---|
| 3078 | + i += scnprintf(buf + i, sz - i, " mtu: %u\n", n->links[1].mtu); |
---|
| 3079 | + i += scnprintf(buf + i, sz - i, " media: "); |
---|
| 3080 | + i += tipc_media_addr_printf(buf + i, sz - i, &n->links[1].maddr); |
---|
| 3081 | + i += scnprintf(buf + i, sz - i, "\n"); |
---|
| 3082 | + i += tipc_link_dump(n->links[1].link, TIPC_DUMP_NONE, buf + i); |
---|
| 3083 | + i += scnprintf(buf + i, sz - i, " inputq: "); |
---|
| 3084 | + i += tipc_list_dump(&n->links[1].inputq, false, buf + i); |
---|
| 3085 | + |
---|
| 3086 | + i += scnprintf(buf + i, sz - i, "bclink:\n "); |
---|
| 3087 | + i += tipc_link_dump(n->bc_entry.link, TIPC_DUMP_NONE, buf + i); |
---|
| 3088 | + |
---|
| 3089 | + return i; |
---|
| 3090 | +} |
---|
| 3091 | + |
---|
| 3092 | +void tipc_node_pre_cleanup_net(struct net *exit_net) |
---|
| 3093 | +{ |
---|
| 3094 | + struct tipc_node *n; |
---|
| 3095 | + struct tipc_net *tn; |
---|
| 3096 | + struct net *tmp; |
---|
| 3097 | + |
---|
| 3098 | + rcu_read_lock(); |
---|
| 3099 | + for_each_net_rcu(tmp) { |
---|
| 3100 | + if (tmp == exit_net) |
---|
| 3101 | + continue; |
---|
| 3102 | + tn = tipc_net(tmp); |
---|
| 3103 | + if (!tn) |
---|
| 3104 | + continue; |
---|
| 3105 | + spin_lock_bh(&tn->node_list_lock); |
---|
| 3106 | + list_for_each_entry_rcu(n, &tn->node_list, list) { |
---|
| 3107 | + if (!n->peer_net) |
---|
| 3108 | + continue; |
---|
| 3109 | + if (n->peer_net != exit_net) |
---|
| 3110 | + continue; |
---|
| 3111 | + tipc_node_write_lock(n); |
---|
| 3112 | + n->peer_net = NULL; |
---|
| 3113 | + n->peer_hash_mix = 0; |
---|
| 3114 | + tipc_node_write_unlock_fast(n); |
---|
| 3115 | + break; |
---|
| 3116 | + } |
---|
| 3117 | + spin_unlock_bh(&tn->node_list_lock); |
---|
| 3118 | + } |
---|
| 3119 | + rcu_read_unlock(); |
---|
| 3120 | +} |
---|