net/rxrpc/rxgk.c

Source file repositories/reference/linux-study-clean/net/rxrpc/rxgk.c

File Facts

System
Linux kernel
Corpus path
net/rxrpc/rxgk.c
Extension
.c
Size
34434 bytes
Lines
1356
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration 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

ntohl(hdr->data_len)	> len) {
		ret = rxrpc_abort_eproto(call, skb, RXGK_SEALEDINCON,
					 rxgk_abort_2_short_data);
		goto error;
	}

	call->rx_dec_offset = offset;
	call->rx_dec_len = ntohl(hdr->data_len);
	ret = 0;
error:
	rxgk_put(gk);
	_leave(" = %d", ret);
	return ret;
}

/*
 * Verify the security on a received packet or subpacket (if part of a
 * jumbo packet).
 */
static int rxgk_verify_packet(struct rxrpc_call *call, struct sk_buff *skb)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	struct rxgk_context *gk;
	u16 key_number = sp->hdr.cksum;

	_enter("{%d{%x}},{#%u}",
	       call->debug_id, key_serial(call->conn->key), sp->hdr.seq);

	gk = rxgk_get_key(call->conn, &key_number);
	if (IS_ERR(gk)) {
		switch (PTR_ERR(gk)) {
		case -ESTALE:
			return rxrpc_abort_eproto(call, skb, RXGK_BADKEYNO,
						  rxgk_abort_bad_key_number);
		default:
			return PTR_ERR(gk);
		}
	}

	call->security_enctype = gk->krb5->etype;
	switch (call->conn->security_level) {
	case RXRPC_SECURITY_PLAIN:
		rxgk_put(gk);
		return 0;
	case RXRPC_SECURITY_AUTH:
		return rxgk_verify_packet_integrity(call, gk, skb);
	case RXRPC_SECURITY_ENCRYPT:
		return rxgk_verify_packet_encrypted(call, gk, skb);
	default:
		rxgk_put(gk);
		return -ENOANO;
	}
}

/*
 * Allocate memory to hold a challenge or a response packet.  We're not running
 * in the io_thread, so we can't use ->tx_alloc.
 */
static struct page *rxgk_alloc_packet(size_t total_len)
{
	gfp_t gfp = GFP_NOFS;
	int order;

	order = get_order(total_len);
	if (order > 0)
		gfp |= __GFP_COMP;
	return alloc_pages(gfp, order);
}

/*
 * Issue a challenge.
 */
static int rxgk_issue_challenge(struct rxrpc_connection *conn)
{
	struct rxrpc_wire_header *whdr;
	struct bio_vec bvec[1];
	struct msghdr msg;
	struct page *page;
	size_t len = sizeof(*whdr) + sizeof(conn->rxgk.nonce);
	u32 serial;
	int ret;

	_enter("{%d}", conn->debug_id);

	get_random_bytes(&conn->rxgk.nonce, sizeof(conn->rxgk.nonce));

	/* We can't use conn->tx_alloc without a lock */
	page = rxgk_alloc_packet(sizeof(*whdr) + sizeof(conn->rxgk.nonce));
	if (!page)
		return -ENOMEM;

Annotation

Implementation Notes