|
@@ -128,8 +128,8 @@ struct tipc_link {
|
|
|
struct net *net;
|
|
|
|
|
|
/* Management and link supervision data */
|
|
|
- u32 peer_session;
|
|
|
- u32 session;
|
|
|
+ u16 peer_session;
|
|
|
+ u16 session;
|
|
|
u16 snd_nxt_state;
|
|
|
u16 rcv_nxt_state;
|
|
|
u32 peer_bearer_id;
|
|
@@ -138,6 +138,7 @@ struct tipc_link {
|
|
|
u32 abort_limit;
|
|
|
u32 state;
|
|
|
u16 peer_caps;
|
|
|
+ bool in_session;
|
|
|
bool active;
|
|
|
u32 silent_intv_cnt;
|
|
|
char if_name[TIPC_MAX_IF_NAME];
|
|
@@ -216,11 +217,6 @@ enum {
|
|
|
*/
|
|
|
#define TIPC_NACK_INTV (TIPC_MIN_LINK_WIN * 2)
|
|
|
|
|
|
-/* Wildcard value for link session numbers. When it is known that
|
|
|
- * peer endpoint is down, any session number must be accepted.
|
|
|
- */
|
|
|
-#define ANY_SESSION 0x10000
|
|
|
-
|
|
|
/* Link FSM states:
|
|
|
*/
|
|
|
enum {
|
|
@@ -478,7 +474,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
|
|
|
l->addr = peer;
|
|
|
l->peer_caps = peer_caps;
|
|
|
l->net = net;
|
|
|
- l->peer_session = ANY_SESSION;
|
|
|
+ l->in_session = false;
|
|
|
l->bearer_id = bearer_id;
|
|
|
l->tolerance = tolerance;
|
|
|
l->net_plane = net_plane;
|
|
@@ -847,7 +843,7 @@ void link_prepare_wakeup(struct tipc_link *l)
|
|
|
|
|
|
void tipc_link_reset(struct tipc_link *l)
|
|
|
{
|
|
|
- l->peer_session = ANY_SESSION;
|
|
|
+ l->in_session = false;
|
|
|
l->session++;
|
|
|
l->mtu = l->advertised_mtu;
|
|
|
__skb_queue_purge(&l->transmq);
|
|
@@ -1455,6 +1451,44 @@ tnl:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/* tipc_link_validate_msg(): validate message against current link state
|
|
|
+ * Returns true if message should be accepted, otherwise false
|
|
|
+ */
|
|
|
+bool tipc_link_validate_msg(struct tipc_link *l, struct tipc_msg *hdr)
|
|
|
+{
|
|
|
+ u16 curr_session = l->peer_session;
|
|
|
+ u16 session = msg_session(hdr);
|
|
|
+ int mtyp = msg_type(hdr);
|
|
|
+
|
|
|
+ if (msg_user(hdr) != LINK_PROTOCOL)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ switch (mtyp) {
|
|
|
+ case RESET_MSG:
|
|
|
+ if (!l->in_session)
|
|
|
+ return true;
|
|
|
+ /* Accept only RESET with new session number */
|
|
|
+ return more(session, curr_session);
|
|
|
+ case ACTIVATE_MSG:
|
|
|
+ if (!l->in_session)
|
|
|
+ return true;
|
|
|
+ /* Accept only ACTIVATE with new or current session number */
|
|
|
+ return !less(session, curr_session);
|
|
|
+ case STATE_MSG:
|
|
|
+ /* Accept only STATE with current session number */
|
|
|
+ if (!l->in_session)
|
|
|
+ return false;
|
|
|
+ if (session != curr_session)
|
|
|
+ return false;
|
|
|
+ if (!(l->peer_caps & TIPC_LINK_PROTO_SEQNO))
|
|
|
+ return true;
|
|
|
+ /* Accept only STATE with new sequence number */
|
|
|
+ return !less(msg_seqno(hdr), l->rcv_nxt_state);
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* tipc_link_proto_rcv(): receive link level protocol message :
|
|
|
* Note that network plane id propagates through the network, and may
|
|
|
* change at any time. The node with lowest numerical id determines
|
|
@@ -1488,17 +1522,12 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
|
|
|
hdr = buf_msg(skb);
|
|
|
data = msg_data(hdr);
|
|
|
|
|
|
+ if (!tipc_link_validate_msg(l, hdr))
|
|
|
+ goto exit;
|
|
|
+
|
|
|
switch (mtyp) {
|
|
|
case RESET_MSG:
|
|
|
-
|
|
|
- /* Ignore duplicate RESET with old session number */
|
|
|
- if ((less_eq(msg_session(hdr), l->peer_session)) &&
|
|
|
- (l->peer_session != ANY_SESSION))
|
|
|
- break;
|
|
|
- /* fall thru' */
|
|
|
-
|
|
|
case ACTIVATE_MSG:
|
|
|
-
|
|
|
/* Complete own link name with peer's interface name */
|
|
|
if_name = strrchr(l->name, ':') + 1;
|
|
|
if (sizeof(l->name) - (if_name - l->name) <= TIPC_MAX_IF_NAME)
|
|
@@ -1526,16 +1555,13 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
|
|
|
rc = TIPC_LINK_UP_EVT;
|
|
|
|
|
|
l->peer_session = msg_session(hdr);
|
|
|
+ l->in_session = true;
|
|
|
l->peer_bearer_id = msg_bearer_id(hdr);
|
|
|
if (l->mtu > msg_max_pkt(hdr))
|
|
|
l->mtu = msg_max_pkt(hdr);
|
|
|
break;
|
|
|
|
|
|
case STATE_MSG:
|
|
|
-
|
|
|
- if (l->peer_caps & TIPC_LINK_PROTO_SEQNO &&
|
|
|
- less(msg_seqno(hdr), l->rcv_nxt_state))
|
|
|
- break;
|
|
|
l->rcv_nxt_state = msg_seqno(hdr) + 1;
|
|
|
|
|
|
/* Update own tolerance if peer indicates a non-zero value */
|