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

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
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -62,7 +62,8 @@ enum {
	X25_STATE_1,		/* Awaiting Call Accepted */
	X25_STATE_2,		/* Awaiting Clear Confirmation */
	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 {
+8 −0
Original line number Diff line number Diff line
@@ -659,6 +659,12 @@ static int x25_release(struct socket *sock)
			sock_set_flag(sk, SOCK_DEAD);
			sock_set_flag(sk, SOCK_DESTROY);
			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);
@@ -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)) {
		x25_write_internal(make, X25_CALL_ACCEPTED);
		makex25->state = X25_STATE_3;
	} else {
		makex25->state = X25_STATE_5;
	}

	/*
+32 −0
Original line number Diff line number Diff line
@@ -382,6 +382,35 @@ out_clear:
	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 */
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:
		queued = x25_state4_machine(sk, skb, frametype);
		break;
	case X25_STATE_5:
		queued = x25_state5_machine(sk, skb, frametype);
		break;
	}

	x25_kick(sk);