Beispiel #1
0
/*
 * State machine for state 4, Awaiting Reset Confirmation State.
 * 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_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{
	switch (frametype) {

		case X25_RESET_REQUEST:
			x25_write_internal(sk, X25_RESET_CONFIRMATION);
		case X25_RESET_CONFIRMATION: {
			struct x25_sock *x25 = x25_sk(sk);

			x25_stop_timer(sk);
			x25->condition = 0x00;
			x25->va        = 0;
			x25->vr        = 0;
			x25->vs        = 0;
			x25->vl        = 0;
			x25->state     = X25_STATE_3;
			x25_requeue_frames(sk);
			break;
		}
		case X25_CLEAR_REQUEST:
			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
			x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
			break;

		default:
			break;
	}

	return 0;
}
void x25_kick(struct sock *sk)
{
	struct sk_buff *skb, *skbn;
	unsigned short start, end;
	int modulus;
	struct x25_sock *x25 = x25_sk(sk);

	if (x25->state != X25_STATE_3)
		return;

	if (skb_peek(&x25->interrupt_out_queue) != NULL &&
		!test_and_set_bit(X25_INTERRUPT_FLAG, &x25->flags)) {

		skb = skb_dequeue(&x25->interrupt_out_queue);
		x25_transmit_link(skb, x25->neighbour);
	}

	if (x25->condition & X25_COND_PEER_RX_BUSY)
		return;

	if (!skb_peek(&sk->sk_write_queue))
		return;

	modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS;

	start   = skb_peek(&x25->ack_queue) ? x25->vs : x25->va;
	end     = (x25->va + x25->facilities.winsize_out) % modulus;

	if (start == end)
		return;

	x25->vs = start;


	skb = skb_dequeue(&sk->sk_write_queue);

	do {
		if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
			skb_queue_head(&sk->sk_write_queue, skb);
			break;
		}

		skb_set_owner_w(skbn, sk);

		x25_send_iframe(sk, skbn);

		x25->vs = (x25->vs + 1) % modulus;

		skb_queue_tail(&x25->ack_queue, skb);

	} while (x25->vs != end &&
		 (skb = skb_dequeue(&sk->sk_write_queue)) != NULL);

	x25->vl         = x25->vr;
	x25->condition &= ~X25_COND_ACK_PENDING;

	x25_stop_timer(sk);
}
Beispiel #3
0
void x25_enquiry_response(struct sock *sk)
{
	if (sk->protinfo.x25->condition & X25_COND_OWN_RX_BUSY)
		x25_write_internal(sk, X25_RNR);
	else
		x25_write_internal(sk, X25_RR);

	sk->protinfo.x25->vl         = sk->protinfo.x25->vr;
	sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING;

	x25_stop_timer(sk);
}
void x25_enquiry_response(struct sock *sk)
{
	struct x25_opt *x25 = x25_sk(sk);

	if (x25->condition & X25_COND_OWN_RX_BUSY)
		x25_write_internal(sk, X25_RNR);
	else
		x25_write_internal(sk, X25_RR);

	x25->vl         = x25->vr;
	x25->condition &= ~X25_COND_ACK_PENDING;

	x25_stop_timer(sk);
}
Beispiel #5
0
/*
 * State machine for state 1, Awaiting Call Accepted State.
 * 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_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{
	struct x25_address source_addr, dest_addr;

	switch (frametype) {
		case X25_CALL_ACCEPTED: {
			struct x25_sock *x25 = x25_sk(sk);

			x25_stop_timer(sk);
			x25->condition = 0x00;
			x25->vs        = 0;
			x25->va        = 0;
			x25->vr        = 0;
			x25->vl        = 0;
			x25->state     = X25_STATE_3;
			sk->sk_state   = TCP_ESTABLISHED;
			/*
			 *	Parse the data in the frame.
			 */
			skb_pull(skb, X25_STD_MIN_LEN);
			skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
			skb_pull(skb,
				 x25_parse_facilities(skb, &x25->facilities,
						&x25->dte_facilities,
						&x25->vc_facil_mask));
			/*
			 *	Copy any Call User Data.
			 */
			if (skb->len >= 0) {
				memcpy(x25->calluserdata.cuddata, skb->data,
				       skb->len);
				x25->calluserdata.cudlength = skb->len;
			}
			if (!sock_flag(sk, SOCK_DEAD))
				sk->sk_state_change(sk);
			break;
		}
		case X25_CLEAR_REQUEST:
			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
			x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]);
			break;

		default:
			break;
	}

	return 0;
}
Beispiel #6
0
/*
 * State machine for state 3, Connected State.
 * 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_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m)
{
	int queued = 0;
	int modulus;
	struct x25_sock *x25 = x25_sk(sk);

	modulus = (x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS;

	switch (frametype) {

		case X25_RESET_REQUEST:
			x25_write_internal(sk, X25_RESET_CONFIRMATION);
			x25_stop_timer(sk);
			x25->condition = 0x00;
			x25->vs        = 0;
			x25->vr        = 0;
			x25->va        = 0;
			x25->vl        = 0;
			x25_requeue_frames(sk);
			break;

		case X25_CLEAR_REQUEST:
			x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
			x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
			break;

		case X25_RR:
		case X25_RNR:
			if (!x25_validate_nr(sk, nr)) {
				x25_clear_queues(sk);
				x25_write_internal(sk, X25_RESET_REQUEST);
				x25_start_t22timer(sk);
				x25->condition = 0x00;
				x25->vs        = 0;
				x25->vr        = 0;
				x25->va        = 0;
				x25->vl        = 0;
				x25->state     = X25_STATE_4;
			} else {
				x25_frames_acked(sk, nr);
				if (frametype == X25_RNR) {
					x25->condition |= X25_COND_PEER_RX_BUSY;
				} else {
					x25->condition &= ~X25_COND_PEER_RX_BUSY;
				}
			}
			break;

		case X25_DATA:	/* XXX */
			x25->condition &= ~X25_COND_PEER_RX_BUSY;
			if ((ns != x25->vr) || !x25_validate_nr(sk, nr)) {
				x25_clear_queues(sk);
				x25_write_internal(sk, X25_RESET_REQUEST);
				x25_start_t22timer(sk);
				x25->condition = 0x00;
				x25->vs        = 0;
				x25->vr        = 0;
				x25->va        = 0;
				x25->vl        = 0;
				x25->state     = X25_STATE_4;
				break;
			}
			x25_frames_acked(sk, nr);
			if (ns == x25->vr) {
				if (x25_queue_rx_frame(sk, skb, m) == 0) {
					x25->vr = (x25->vr + 1) % modulus;
					queued = 1;
				} else {
					/* Should never happen */
					x25_clear_queues(sk);
					x25_write_internal(sk, X25_RESET_REQUEST);
					x25_start_t22timer(sk);
					x25->condition = 0x00;
					x25->vs        = 0;
					x25->vr        = 0;
					x25->va        = 0;
					x25->vl        = 0;
					x25->state     = X25_STATE_4;
					break;
				}
				if (atomic_read(&sk->sk_rmem_alloc) >
				    (sk->sk_rcvbuf / 2))
					x25->condition |= X25_COND_OWN_RX_BUSY;
			}
			/*
			 *	If the window is full Ack it immediately, else
			 *	start the holdback timer.
			 */
			if (((x25->vl + x25->facilities.winsize_in) % modulus) == x25->vr) {
				x25->condition &= ~X25_COND_ACK_PENDING;
				x25_stop_timer(sk);
				x25_enquiry_response(sk);
			} else {
				x25->condition |= X25_COND_ACK_PENDING;
				x25_start_t2timer(sk);
			}
			break;

		case X25_INTERRUPT_CONFIRMATION:
			x25->intflag = 0;
			break;

		case X25_INTERRUPT:
			if (sock_flag(sk, SOCK_URGINLINE))
				queued = !sock_queue_rcv_skb(sk, skb);
			else {
				skb_set_owner_r(skb, sk);
				skb_queue_tail(&x25->interrupt_in_queue, skb);
				queued = 1;
			}
			sk_send_sigurg(sk);
			x25_write_internal(sk, X25_INTERRUPT_CONFIRMATION);
			break;

		default:
			printk(KERN_WARNING "x25: unknown %02X in state 3\n", frametype);
			break;
	}

	return queued;
}
void x25_kick(struct sock *sk)
{
	struct sk_buff *skb, *skbn;
	unsigned short start, end;
	int modulus;
	struct x25_opt *x25 = x25_sk(sk);

	if (x25->state != X25_STATE_3)
		return;

	/*
	 *	Transmit interrupt data.
	 */
	if (!x25->intflag && skb_peek(&x25->interrupt_out_queue) != NULL) {
		x25->intflag = 1;
		skb = skb_dequeue(&x25->interrupt_out_queue);
		x25_transmit_link(skb, x25->neighbour);
	}

	if (x25->condition & X25_COND_PEER_RX_BUSY)
		return;

	if (!skb_peek(&sk->sk_write_queue))
		return;

	modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS;

	start   = skb_peek(&x25->ack_queue) ? x25->vs : x25->va;
	end     = (x25->va + x25->facilities.winsize_out) % modulus;

	if (start == end)
		return;

	x25->vs = start;

	/*
	 * Transmit data until either we're out of data to send or
	 * the window is full.
	 */

	skb = skb_dequeue(&sk->sk_write_queue);

	do {
		if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
			skb_queue_head(&sk->sk_write_queue, skb);
			break;
		}

		skb_set_owner_w(skbn, sk);

		/*
		 * Transmit the frame copy.
		 */
		x25_send_iframe(sk, skbn);

		x25->vs = (x25->vs + 1) % modulus;

		/*
		 * Requeue the original data frame.
		 */
		skb_queue_tail(&x25->ack_queue, skb);

	} while (x25->vs != end &&
		 (skb = skb_dequeue(&sk->sk_write_queue)) != NULL);

	x25->vl         = x25->vr;
	x25->condition &= ~X25_COND_ACK_PENDING;

	x25_stop_timer(sk);
}
Beispiel #8
0
int x25_set_params(struct x25_cs * x25, struct x25_params *params) {
	int res = X25_BADTOKEN;
	if (!x25 || !params)
		goto out;

	res = X25_INVALUE;
	struct x25_cs_internal * x25_int = x25_get_internal(x25);

	/* Check and correct timers params */
	if (params->RestartTimerInterval < 10000)	params->RestartTimerInterval = X25_DEFAULT_RESTART_TIMER;
	if (params->CallTimerInterval < 10000)		params->CallTimerInterval = X25_DEFAULT_CALL_TIMER;
	if (params->ResetTimerInterval < 10000)		params->ResetTimerInterval = X25_DEFAULT_RESET_TIMER;
	if (params->ClearTimerInterval < 10000)		params->ClearTimerInterval = X25_DEFAULT_CLEAR_TIMER;
	if (params->AckTimerInterval < 10000)		params->AckTimerInterval = X25_DEFAULT_ACK_TIMER;
	if (params->DataTimerInterval < 10000)		params->DataTimerInterval = X25_DEFAULT_DATA_TIMER;

	if (params->RestartTimerInterval > 300000)	params->RestartTimerInterval = X25_DEFAULT_RESTART_TIMER;
	if (params->CallTimerInterval > 300000)		params->CallTimerInterval = X25_DEFAULT_CALL_TIMER;
	if (params->ResetTimerInterval > 300000)	params->ResetTimerInterval = X25_DEFAULT_RESET_TIMER;
	if (params->ClearTimerInterval > 300000)	params->ClearTimerInterval = X25_DEFAULT_CLEAR_TIMER;
	if (params->AckTimerInterval > 300000)		params->AckTimerInterval = X25_DEFAULT_ACK_TIMER;
	if (params->DataTimerInterval > 300000)		params->DataTimerInterval = X25_DEFAULT_DATA_TIMER;

	if ((params->RestartTimerNR < 1) || (params->RestartTimerNR > 10))
		params->RestartTimerNR = 2;
	if ((params->CallTimerNR < 1) || (params->CallTimerNR > 10))
		params->CallTimerNR = 2;
	if ((params->ResetTimerNR < 1) || (params->ResetTimerNR > 10))
		params->ResetTimerNR = 2;
	if ((params->ClearTimerNR < 1) || (params->ClearTimerNR > 10))
		params->ClearTimerNR = 2;
	if ((params->AckTimerNR < 1) || (params->AckTimerNR > 10))
		params->AckTimerNR = 2;
	if ((params->DataTimerNR < 1) || (params->DataTimerNR > 10))
		params->DataTimerNR = 2;

	/* Apply new values */
	if (x25_int->RestartTimer.interval != params->RestartTimerInterval) {
		x25_stop_timer(x25, &x25_int->RestartTimer);
		x25->callbacks->del_timer(x25_int->RestartTimer.timer_ptr);
		x25_int->RestartTimer.interval = params->RestartTimerInterval;
		x25_int->RestartTimer.timer_ptr  = x25->callbacks->add_timer(x25_int->RestartTimer.interval, x25, x25_timer_expiry);
	};
	x25->RestartTimer_NR = params->RestartTimerNR;

	if (x25_int->CallTimer.interval	!= params->CallTimerInterval) {
		x25_stop_timer(x25, &x25_int->CallTimer);
		x25->callbacks->del_timer(x25_int->CallTimer.timer_ptr);
		x25_int->CallTimer.interval = params->CallTimerInterval;
		x25_int->CallTimer.timer_ptr = x25->callbacks->add_timer(x25_int->CallTimer.interval, x25, x25_timer_expiry);
	};
	x25->CallTimer_NR = params->CallTimerNR;

	if (x25_int->ResetTimer.interval != params->ResetTimerInterval) {
		x25_stop_timer(x25, &x25_int->ResetTimer);
		x25->callbacks->del_timer(x25_int->ResetTimer.timer_ptr);
		x25_int->ResetTimer.interval = params->ResetTimerInterval;
		x25_int->ResetTimer.timer_ptr = x25->callbacks->add_timer(x25_int->ResetTimer.interval, x25, x25_timer_expiry);
	};
	x25->ResetTimer_NR = params->ResetTimerNR;

	if (x25_int->ClearTimer.interval != params->ClearTimerInterval) {
		x25_stop_timer(x25, &x25_int->ClearTimer);
		x25->callbacks->del_timer(x25_int->ClearTimer.timer_ptr);
		x25_int->ClearTimer.interval = params->ClearTimerInterval;
		x25_int->ClearTimer.timer_ptr = x25->callbacks->add_timer(x25_int->ClearTimer.interval, x25, x25_timer_expiry);
	};
	x25->ClearTimer_NR = params->ClearTimerNR;

	if (x25_int->AckTimer.interval != params->AckTimerInterval) {
		x25_stop_timer(x25, &x25_int->AckTimer);
		x25->callbacks->del_timer(x25_int->AckTimer.timer_ptr);
		x25_int->AckTimer.interval = params->AckTimerInterval;
		x25_int->AckTimer.timer_ptr = x25->callbacks->add_timer(x25_int->AckTimer.interval, x25, x25_timer_expiry);
	};
	x25->AckTimer_NR = params->AckTimerNR;

	if (x25_int->DataTimer.interval != params->DataTimerInterval) {
		x25_stop_timer(x25, &x25_int->AckTimer);
		x25->callbacks->del_timer(x25_int->DataTimer.timer_ptr);
		x25_int->DataTimer.interval = params->DataTimerInterval;
		x25_int->DataTimer.timer_ptr = x25->callbacks->add_timer(x25_int->DataTimer.interval, x25, x25_timer_expiry);
	};
	x25->DataTimer_NR = params->DataTimerNR;


	/* Check and correct facilities values */
	if (x25_is_extended(x25)) {
		if ((params->WinsizeIn < 1) || (params->WinsizeIn > 127))
			params->WinsizeIn = X25_DEFAULT_WINDOW_SIZE;
		if ((params->WinsizeOut < 1) || (params->WinsizeOut > 127))
			params->WinsizeOut = X25_DEFAULT_WINDOW_SIZE;
	} else {
		if ((params->WinsizeIn < 1) || (params->WinsizeIn > 7))
			params->WinsizeIn = X25_DEFAULT_WINDOW_SIZE;
		if ((params->WinsizeOut < 1) || (params->WinsizeOut > 7))
			params->WinsizeOut = X25_DEFAULT_WINDOW_SIZE;
	};
	if ((params->PacsizeIn < X25_PS16) || (params->PacsizeIn > X25_PS4096))
		params->PacsizeIn = X25_DEFAULT_PACKET_SIZE;
	if ((params->PacsizeOut < X25_PS16) || (params->PacsizeOut > X25_PS4096))
		params->PacsizeOut = X25_DEFAULT_PACKET_SIZE;

	/* Apply new facilites */
	x25_int->facilities.winsize_in	= params->WinsizeIn;
	x25_int->facilities.winsize_out	= params->WinsizeOut;
	x25_int->facilities.pacsize_in	= params->PacsizeIn;
	x25_int->facilities.pacsize_out	= params->PacsizeOut;

out:
	return res;
}