net/tipc/msg.c

Source file repositories/reference/linux-study-clean/net/tipc/msg.c

File Facts

System
Linux kernel
Corpus path
net/tipc/msg.c
Extension
.c
Size
23500 bytes
Lines
868
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

if (unlikely(!tipc_msg_validate(&head))) {
			if (head != *headbuf)
				*headbuf = head;
			goto err;
		}

		*buf = head;
		TIPC_SKB_CB(head)->tail = NULL;
		*headbuf = NULL;
		return 1;
	}
	return 0;
err:
	kfree_skb(*buf);
	kfree_skb(*headbuf);
	*buf = *headbuf = NULL;
	return 0;
}

/**
 * tipc_msg_append(): Append data to tail of an existing buffer queue
 * @_hdr: header to be used
 * @m: the data to be appended
 * @mss: max allowable size of buffer
 * @dlen: size of data to be appended
 * @txq: queue to append to
 *
 * Return: the number of 1k blocks appended or errno value
 */
int tipc_msg_append(struct tipc_msg *_hdr, struct msghdr *m, int dlen,
		    int mss, struct sk_buff_head *txq)
{
	struct sk_buff *skb;
	int accounted, total, curr;
	int mlen, cpy, rem = dlen;
	struct tipc_msg *hdr;

	skb = skb_peek_tail(txq);
	accounted = skb ? msg_blocks(buf_msg(skb)) : 0;
	total = accounted;

	do {
		if (!skb || skb->len >= mss) {
			skb = tipc_buf_acquire(mss, GFP_KERNEL);
			if (unlikely(!skb))
				return -ENOMEM;
			skb_orphan(skb);
			skb_trim(skb, MIN_H_SIZE);
			hdr = buf_msg(skb);
			skb_copy_to_linear_data(skb, _hdr, MIN_H_SIZE);
			msg_set_hdr_sz(hdr, MIN_H_SIZE);
			msg_set_size(hdr, MIN_H_SIZE);
			__skb_queue_tail(txq, skb);
			total += 1;
		}
		hdr = buf_msg(skb);
		curr = msg_blocks(hdr);
		mlen = msg_size(hdr);
		cpy = min_t(size_t, rem, mss - mlen);
		if (cpy != copy_from_iter(skb->data + mlen, cpy, &m->msg_iter))
			return -EFAULT;
		msg_set_size(hdr, mlen + cpy);
		skb_put(skb, cpy);
		rem -= cpy;
		total += msg_blocks(hdr) - curr;
	} while (rem > 0);
	return total - accounted;
}

/* tipc_msg_validate - validate basic format of received message
 *
 * This routine ensures a TIPC message has an acceptable header, and at least
 * as much data as the header indicates it should.  The routine also ensures
 * that the entire message header is stored in the main fragment of the message
 * buffer, to simplify future access to message header fields.
 *
 * Note: Having extra info present in the message header or data areas is OK.
 * TIPC will ignore the excess, under the assumption that it is optional info
 * introduced by a later release of the protocol.
 */
bool tipc_msg_validate(struct sk_buff **_skb)
{
	struct sk_buff *skb = *_skb;
	struct tipc_msg *hdr;
	int msz, hsz;

	/* Ensure that flow control ratio condition is satisfied */
	if (unlikely(skb->truesize / buf_roundup_len(skb) >= 4)) {
		skb = skb_copy_expand(skb, BUF_HEADROOM, 0, GFP_ATOMIC);
		if (!skb)

Annotation

Implementation Notes