net/x25/x25_in.c

Source file repositories/reference/linux-study-clean/net/x25/x25_in.c

File Facts

System
Linux kernel
Corpus path
net/x25/x25_in.c
Extension
.c
Size
10872 bytes
Lines
460
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

skb_dequeue(&x25->fragment_queue)) != NULL) {
			skb_pull(skbo, (x25->neighbour->extended) ?
					X25_EXT_MIN_LEN : X25_STD_MIN_LEN);
			skb_copy_from_linear_data(skbo,
						  skb_put(skbn, skbo->len),
						  skbo->len);
			kfree_skb(skbo);
		}

		x25->fraglen = 0;
	}

	skb_set_owner_r(skbn, sk);
	skb_queue_tail(&sk->sk_receive_queue, skbn);
	if (!sock_flag(sk, SOCK_DEAD))
		sk->sk_data_ready(sk);

	return 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;
	int len;
	struct x25_sock *x25 = x25_sk(sk);

	switch (frametype) {
	case X25_CALL_ACCEPTED: {

		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.
		 */
		if (!pskb_may_pull(skb, X25_STD_MIN_LEN))
			goto out_clear;
		skb_pull(skb, X25_STD_MIN_LEN);

		len = x25_parse_address_block(skb, &source_addr,
					      &dest_addr);
		if (len > 0)
			skb_pull(skb, len);
		else if (len < 0)
			goto out_clear;

		len = x25_parse_facilities(skb, &x25->facilities,
					   &x25->dte_facilities,
					   &x25->vc_facil_mask);
		if (len > 0)
			skb_pull(skb, len);
		else if (len < 0)
			goto out_clear;
		/*
		 *	Copy any Call User Data.
		 */
		if (skb->len > 0) {
			if (skb->len > X25_MAX_CUD_LEN)
				goto out_clear;

			skb_copy_bits(skb, 0, x25->calluserdata.cuddata,
				skb->len);
			x25->calluserdata.cudlength = skb->len;
		}
		if (!sock_flag(sk, SOCK_DEAD))
			sk->sk_state_change(sk);
		break;
	}
	case X25_CALL_REQUEST:
		/* call collision */
		x25->causediag.cause      = 0x01;
		x25->causediag.diagnostic = 0x48;

		x25_write_internal(sk, X25_CLEAR_REQUEST);
		x25_disconnect(sk, EISCONN, 0x01, 0x48);
		break;

	case X25_CLEAR_REQUEST:
		if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2))
			goto out_clear;

Annotation

Implementation Notes