net/x25/x25_subr.c

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

File Facts

System
Linux kernel
Corpus path
net/x25/x25_subr.c
Extension
.c
Size
9442 bytes
Lines
386
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

while (skb_peek(&x25->ack_queue) && x25->va != nr) {
			skb = skb_dequeue(&x25->ack_queue);
			kfree_skb(skb);
			x25->va = (x25->va + 1) % modulus;
		}
}

void x25_requeue_frames(struct sock *sk)
{
	struct sk_buff *skb, *skb_prev = NULL;

	/*
	 * Requeue all the un-ack-ed frames on the output queue to be picked
	 * up by x25_kick. This arrangement handles the possibility of an empty
	 * output queue.
	 */
	while ((skb = skb_dequeue(&x25_sk(sk)->ack_queue)) != NULL) {
		if (!skb_prev)
			skb_queue_head(&sk->sk_write_queue, skb);
		else
			skb_append(skb_prev, skb, &sk->sk_write_queue);
		skb_prev = skb;
	}
}

/*
 *	Validate that the value of nr is between va and vs. Return true or
 *	false for testing.
 */
int x25_validate_nr(struct sock *sk, unsigned short nr)
{
	struct x25_sock *x25 = x25_sk(sk);
	unsigned short vc = x25->va;
	int modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS;

	while (vc != x25->vs) {
		if (nr == vc)
			return 1;
		vc = (vc + 1) % modulus;
	}

	return nr == x25->vs ? 1 : 0;
}

/*
 *  This routine is called when the packet layer internally generates a
 *  control frame.
 */
void x25_write_internal(struct sock *sk, int frametype)
{
	struct x25_sock *x25 = x25_sk(sk);
	struct sk_buff *skb;
	unsigned char  *dptr;
	unsigned char  facilities[X25_MAX_FAC_LEN];
	unsigned char  addresses[1 + X25_ADDR_LEN];
	unsigned char  lci1, lci2;
	/*
	 *	Default safe frame size.
	 */
	int len = X25_MAX_L2_LEN + X25_EXT_MIN_LEN;

	/*
	 *	Adjust frame size.
	 */
	switch (frametype) {
	case X25_CALL_REQUEST:
		len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
		break;
	case X25_CALL_ACCEPTED: /* fast sel with no restr on resp */
		if (x25->facilities.reverse & 0x80) {
			len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
		} else {
			len += 1 + X25_MAX_FAC_LEN;
		}
		break;
	case X25_CLEAR_REQUEST:
	case X25_RESET_REQUEST:
		len += 2;
		break;
	case X25_RR:
	case X25_RNR:
	case X25_REJ:
	case X25_CLEAR_CONFIRMATION:
	case X25_INTERRUPT_CONFIRMATION:
	case X25_RESET_CONFIRMATION:
		break;
	default:
		pr_err("invalid frame type %02X\n", frametype);
		return;
	}

Annotation

Implementation Notes