Commit f8fc57e8 authored by Martin Schiller's avatar Martin Schiller Committed by David S. Miller

net/x25: add new state X25_STATE_5

This is needed, because if the flag X25_ACCPT_APPRV_FLAG is not set on a
socket (manual call confirmation) and the channel is cleared by remote
before the manual call confirmation was sent, this situation needs to
be handled.
Signed-off-by: default avatarMartin Schiller <ms@dev.tdt.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 65cb1398
...@@ -62,7 +62,8 @@ enum { ...@@ -62,7 +62,8 @@ enum {
X25_STATE_1, /* Awaiting Call Accepted */ X25_STATE_1, /* Awaiting Call Accepted */
X25_STATE_2, /* Awaiting Clear Confirmation */ X25_STATE_2, /* Awaiting Clear Confirmation */
X25_STATE_3, /* Data Transfer */ X25_STATE_3, /* Data Transfer */
X25_STATE_4 /* Awaiting Reset Confirmation */ X25_STATE_4, /* Awaiting Reset Confirmation */
X25_STATE_5 /* Call Accepted / Call Connected pending */
}; };
enum { enum {
......
...@@ -659,6 +659,12 @@ static int x25_release(struct socket *sock) ...@@ -659,6 +659,12 @@ static int x25_release(struct socket *sock)
sock_set_flag(sk, SOCK_DEAD); sock_set_flag(sk, SOCK_DEAD);
sock_set_flag(sk, SOCK_DESTROY); sock_set_flag(sk, SOCK_DESTROY);
break; break;
case X25_STATE_5:
x25_write_internal(sk, X25_CLEAR_REQUEST);
x25_disconnect(sk, 0, 0, 0);
__x25_destroy_socket(sk);
goto out;
} }
sock_orphan(sk); sock_orphan(sk);
...@@ -1054,6 +1060,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, ...@@ -1054,6 +1060,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
if (test_bit(X25_ACCPT_APPRV_FLAG, &makex25->flags)) { if (test_bit(X25_ACCPT_APPRV_FLAG, &makex25->flags)) {
x25_write_internal(make, X25_CALL_ACCEPTED); x25_write_internal(make, X25_CALL_ACCEPTED);
makex25->state = X25_STATE_3; makex25->state = X25_STATE_3;
} else {
makex25->state = X25_STATE_5;
} }
/* /*
......
...@@ -382,6 +382,35 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp ...@@ -382,6 +382,35 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp
return 0; return 0;
} }
/*
* State machine for state 5, Call Accepted / Call Connected pending (X25_ACCPT_APPRV_FLAG).
* The handling of the timer(s) is in file x25_timer.c
* Handling of state 0 and connection release is in af_x25.c.
*/
static int x25_state5_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{
struct x25_sock *x25 = x25_sk(sk);
switch (frametype) {
case X25_CLEAR_REQUEST:
if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) {
x25_write_internal(sk, X25_CLEAR_REQUEST);
x25->state = X25_STATE_2;
x25_start_t23timer(sk);
return 0;
}
x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
break;
default:
break;
}
return 0;
}
/* Higher level upcall for a LAPB frame */ /* Higher level upcall for a LAPB frame */
int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb) int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
{ {
...@@ -406,6 +435,9 @@ int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb) ...@@ -406,6 +435,9 @@ int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
case X25_STATE_4: case X25_STATE_4:
queued = x25_state4_machine(sk, skb, frametype); queued = x25_state4_machine(sk, skb, frametype);
break; break;
case X25_STATE_5:
queued = x25_state5_machine(sk, skb, frametype);
break;
} }
x25_kick(sk); x25_kick(sk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment