net/ipv4/syncookies.c

Source file repositories/reference/linux-study-clean/net/ipv4/syncookies.c

File Facts

System
Linux kernel
Corpus path
net/ipv4/syncookies.c
Extension
.c
Size
14283 bytes
Lines
513
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

if (rsk_drop_req(req)) {
			reqsk_put(req);
			return child;
		}

		if (inet_csk_reqsk_queue_add(sk, req, child))
			return child;

		bh_unlock_sock(child);
		sock_put(child);
	}
	__reqsk_free(req);

	return NULL;
}

/*
 * when syncookies are in effect and tcp timestamps are enabled we stored
 * additional tcp options in the timestamp.
 * This extracts these options from the timestamp echo.
 *
 * return false if we decode a tcp option that is disabled
 * on the host.
 */
bool cookie_timestamp_decode(const struct net *net,
			     struct tcp_options_received *tcp_opt)
{
	/* echoed timestamp, lowest bits contain options */
	u32 options = tcp_opt->rcv_tsecr;

	if (!tcp_opt->saw_tstamp)  {
		tcp_clear_options(tcp_opt);
		return true;
	}

	if (!READ_ONCE(net->ipv4.sysctl_tcp_timestamps))
		return false;

	tcp_opt->sack_ok = (options & TS_OPT_SACK) ? TCP_SACK_SEEN : 0;

	if (tcp_opt->sack_ok && !READ_ONCE(net->ipv4.sysctl_tcp_sack))
		return false;

	if ((options & TS_OPT_WSCALE_MASK) == TS_OPT_WSCALE_MASK)
		return true; /* no window scaling */

	tcp_opt->wscale_ok = 1;
	tcp_opt->snd_wscale = options & TS_OPT_WSCALE_MASK;

	return READ_ONCE(net->ipv4.sysctl_tcp_window_scaling) != 0;
}

static int cookie_tcp_reqsk_init(struct sock *sk, struct sk_buff *skb,
				 struct request_sock *req)
{
	struct inet_request_sock *ireq = inet_rsk(req);
	struct tcp_request_sock *treq = tcp_rsk(req);
	const struct tcphdr *th = tcp_hdr(skb);

	req->num_retrans = 0;

	ireq->ir_num = ntohs(th->dest);
	ireq->ir_rmt_port = th->source;
	ireq->ir_iif = inet_request_bound_dev_if(sk, skb);
	ireq->ir_mark = inet_request_mark(sk, skb);

	if (IS_ENABLED(CONFIG_SMC))
		ireq->smc_ok = 0;

	treq->snt_synack = 0;
	treq->snt_tsval_first = 0;
	treq->tfo_listener = false;
	treq->rcv_isn = ntohl(th->seq) - 1;
	treq->snt_isn = ntohl(th->ack_seq) - 1;
	/* The request socket was freed after the SYN-ACK; use the cookie
	 * (snt_isn) as txhash so the full socket and the SYN-ACK make the
	 * same egress choice (IPv6 ECMP path; IPv4 TX queue).
	 */
	treq->txhash = treq->snt_isn;
	treq->syn_tos = TCP_SKB_CB(skb)->ip_dsfield;

#if IS_ENABLED(CONFIG_MPTCP)
	treq->is_mptcp = sk_is_mptcp(sk);
	if (treq->is_mptcp)
		return mptcp_subflow_init_cookie_req(req, sk, skb);
#endif

	return 0;
}

Annotation

Implementation Notes