aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2018-07-09 19:07:35 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-12 02:06:14 -0400
commit9012de5089560136b849b920ad038b96160ed8f6 (patch)
tree20261a0c6e074ca936878835b64a04294ca3af52 /net/tipc
parente32f55f373217001187ff171e75c5dfbb251f633 (diff)
tipc: add sequence number check for link STATE messages
Some switch infrastructures produce huge amounts of packet duplicates. This becomes a problem if those messages are STATE/NACK protocol messages, causing unnecessary retransmissions of already accepted packets. We now introduce a unique sequence number per STATE protocol message so that duplicates can be identified and ignored. This will also be useful when tracing such cases, and to avert replay attacks when TIPC is encrypted. For compatibility reasons we have to introduce a new capability flag TIPC_LINK_PROTO_SEQNO to handle this new feature. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/link.c16
-rw-r--r--net/tipc/link.h1
-rw-r--r--net/tipc/node.c7
-rw-r--r--net/tipc/node.h14
4 files changed, 32 insertions, 6 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index ec4d28328652..065e9e67da5d 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -130,6 +130,8 @@ struct tipc_link {
130 /* Management and link supervision data */ 130 /* Management and link supervision data */
131 u32 peer_session; 131 u32 peer_session;
132 u32 session; 132 u32 session;
133 u16 snd_nxt_state;
134 u16 rcv_nxt_state;
133 u32 peer_bearer_id; 135 u32 peer_bearer_id;
134 u32 bearer_id; 136 u32 bearer_id;
135 u32 tolerance; 137 u32 tolerance;
@@ -339,6 +341,11 @@ char tipc_link_plane(struct tipc_link *l)
339 return l->net_plane; 341 return l->net_plane;
340} 342}
341 343
344void tipc_link_update_caps(struct tipc_link *l, u16 capabilities)
345{
346 l->peer_caps = capabilities;
347}
348
342void tipc_link_add_bc_peer(struct tipc_link *snd_l, 349void tipc_link_add_bc_peer(struct tipc_link *snd_l,
343 struct tipc_link *uc_l, 350 struct tipc_link *uc_l,
344 struct sk_buff_head *xmitq) 351 struct sk_buff_head *xmitq)
@@ -859,6 +866,8 @@ void tipc_link_reset(struct tipc_link *l)
859 l->rcv_unacked = 0; 866 l->rcv_unacked = 0;
860 l->snd_nxt = 1; 867 l->snd_nxt = 1;
861 l->rcv_nxt = 1; 868 l->rcv_nxt = 1;
869 l->snd_nxt_state = 1;
870 l->rcv_nxt_state = 1;
862 l->acked = 0; 871 l->acked = 0;
863 l->silent_intv_cnt = 0; 872 l->silent_intv_cnt = 0;
864 l->rst_cnt = 0; 873 l->rst_cnt = 0;
@@ -1353,6 +1362,8 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
1353 msg_set_seqno(hdr, l->snd_nxt + U16_MAX / 2); 1362 msg_set_seqno(hdr, l->snd_nxt + U16_MAX / 2);
1354 1363
1355 if (mtyp == STATE_MSG) { 1364 if (mtyp == STATE_MSG) {
1365 if (l->peer_caps & TIPC_LINK_PROTO_SEQNO)
1366 msg_set_seqno(hdr, l->snd_nxt_state++);
1356 msg_set_seq_gap(hdr, rcvgap); 1367 msg_set_seq_gap(hdr, rcvgap);
1357 msg_set_bc_gap(hdr, link_bc_rcv_gap(bcl)); 1368 msg_set_bc_gap(hdr, link_bc_rcv_gap(bcl));
1358 msg_set_probe(hdr, probe); 1369 msg_set_probe(hdr, probe);
@@ -1522,6 +1533,11 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
1522 1533
1523 case STATE_MSG: 1534 case STATE_MSG:
1524 1535
1536 if (l->peer_caps & TIPC_LINK_PROTO_SEQNO &&
1537 less(msg_seqno(hdr), l->rcv_nxt_state))
1538 break;
1539 l->rcv_nxt_state = msg_seqno(hdr) + 1;
1540
1525 /* Update own tolerance if peer indicates a non-zero value */ 1541 /* Update own tolerance if peer indicates a non-zero value */
1526 if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL)) 1542 if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL))
1527 l->tolerance = peers_tol; 1543 l->tolerance = peers_tol;
diff --git a/net/tipc/link.h b/net/tipc/link.h
index ec59348a81e8..d56f9c9e5000 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -110,6 +110,7 @@ char *tipc_link_name(struct tipc_link *l);
110char tipc_link_plane(struct tipc_link *l); 110char tipc_link_plane(struct tipc_link *l);
111int tipc_link_prio(struct tipc_link *l); 111int tipc_link_prio(struct tipc_link *l);
112int tipc_link_window(struct tipc_link *l); 112int tipc_link_window(struct tipc_link *l);
113void tipc_link_update_caps(struct tipc_link *l, u16 capabilities);
113unsigned long tipc_link_tolerance(struct tipc_link *l); 114unsigned long tipc_link_tolerance(struct tipc_link *l);
114void tipc_link_set_tolerance(struct tipc_link *l, u32 tol, 115void tipc_link_set_tolerance(struct tipc_link *l, u32 tol,
115 struct sk_buff_head *xmitq); 116 struct sk_buff_head *xmitq);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index cfdbaf479fd1..1cdb176798f7 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -363,6 +363,8 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
363{ 363{
364 struct tipc_net *tn = net_generic(net, tipc_net_id); 364 struct tipc_net *tn = net_generic(net, tipc_net_id);
365 struct tipc_node *n, *temp_node; 365 struct tipc_node *n, *temp_node;
366 struct tipc_link *l;
367 int bearer_id;
366 int i; 368 int i;
367 369
368 spin_lock_bh(&tn->node_list_lock); 370 spin_lock_bh(&tn->node_list_lock);
@@ -370,6 +372,11 @@ static struct tipc_node *tipc_node_create(struct net *net, u32 addr,
370 if (n) { 372 if (n) {
371 /* Same node may come back with new capabilities */ 373 /* Same node may come back with new capabilities */
372 n->capabilities = capabilities; 374 n->capabilities = capabilities;
375 for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) {
376 l = n->links[bearer_id].link;
377 if (l)
378 tipc_link_update_caps(l, capabilities);
379 }
373 goto exit; 380 goto exit;
374 } 381 }
375 n = kzalloc(sizeof(*n), GFP_ATOMIC); 382 n = kzalloc(sizeof(*n), GFP_ATOMIC);
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 846c8f240872..48b3298a248d 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -49,14 +49,16 @@ enum {
49 TIPC_BCAST_STATE_NACK = (1 << 2), 49 TIPC_BCAST_STATE_NACK = (1 << 2),
50 TIPC_BLOCK_FLOWCTL = (1 << 3), 50 TIPC_BLOCK_FLOWCTL = (1 << 3),
51 TIPC_BCAST_RCAST = (1 << 4), 51 TIPC_BCAST_RCAST = (1 << 4),
52 TIPC_NODE_ID128 = (1 << 5) 52 TIPC_NODE_ID128 = (1 << 5),
53 TIPC_LINK_PROTO_SEQNO = (1 << 6)
53}; 54};
54 55
55#define TIPC_NODE_CAPABILITIES (TIPC_BCAST_SYNCH | \ 56#define TIPC_NODE_CAPABILITIES (TIPC_BCAST_SYNCH | \
56 TIPC_BCAST_STATE_NACK | \ 57 TIPC_BCAST_STATE_NACK | \
57 TIPC_BCAST_RCAST | \ 58 TIPC_BCAST_RCAST | \
58 TIPC_BLOCK_FLOWCTL | \ 59 TIPC_BLOCK_FLOWCTL | \
59 TIPC_NODE_ID128) 60 TIPC_NODE_ID128 | \
61 TIPC_LINK_PROTO_SEQNO)
60#define INVALID_BEARER_ID -1 62#define INVALID_BEARER_ID -1
61 63
62void tipc_node_stop(struct net *net); 64void tipc_node_stop(struct net *net);