1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * net/dccp/minisocks.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * An implementation of the DCCP protocol
6*4882a593Smuzhiyun * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/dccp.h>
10*4882a593Smuzhiyun #include <linux/gfp.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/skbuff.h>
13*4882a593Smuzhiyun #include <linux/timer.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <net/sock.h>
16*4882a593Smuzhiyun #include <net/xfrm.h>
17*4882a593Smuzhiyun #include <net/inet_timewait_sock.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include "ackvec.h"
20*4882a593Smuzhiyun #include "ccid.h"
21*4882a593Smuzhiyun #include "dccp.h"
22*4882a593Smuzhiyun #include "feat.h"
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun struct inet_timewait_death_row dccp_death_row = {
25*4882a593Smuzhiyun .sysctl_max_tw_buckets = NR_FILE * 2,
26*4882a593Smuzhiyun .hashinfo = &dccp_hashinfo,
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_death_row);
30*4882a593Smuzhiyun
dccp_time_wait(struct sock * sk,int state,int timeo)31*4882a593Smuzhiyun void dccp_time_wait(struct sock *sk, int state, int timeo)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun struct inet_timewait_sock *tw;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun tw = inet_twsk_alloc(sk, &dccp_death_row, state);
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun if (tw != NULL) {
38*4882a593Smuzhiyun const struct inet_connection_sock *icsk = inet_csk(sk);
39*4882a593Smuzhiyun const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
40*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
41*4882a593Smuzhiyun if (tw->tw_family == PF_INET6) {
42*4882a593Smuzhiyun tw->tw_v6_daddr = sk->sk_v6_daddr;
43*4882a593Smuzhiyun tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
44*4882a593Smuzhiyun tw->tw_ipv6only = sk->sk_ipv6only;
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun #endif
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /* Get the TIME_WAIT timeout firing. */
49*4882a593Smuzhiyun if (timeo < rto)
50*4882a593Smuzhiyun timeo = rto;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun if (state == DCCP_TIME_WAIT)
53*4882a593Smuzhiyun timeo = DCCP_TIMEWAIT_LEN;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* tw_timer is pinned, so we need to make sure BH are disabled
56*4882a593Smuzhiyun * in following section, otherwise timer handler could run before
57*4882a593Smuzhiyun * we complete the initialization.
58*4882a593Smuzhiyun */
59*4882a593Smuzhiyun local_bh_disable();
60*4882a593Smuzhiyun inet_twsk_schedule(tw, timeo);
61*4882a593Smuzhiyun /* Linkage updates.
62*4882a593Smuzhiyun * Note that access to tw after this point is illegal.
63*4882a593Smuzhiyun */
64*4882a593Smuzhiyun inet_twsk_hashdance(tw, sk, &dccp_hashinfo);
65*4882a593Smuzhiyun local_bh_enable();
66*4882a593Smuzhiyun } else {
67*4882a593Smuzhiyun /* Sorry, if we're out of memory, just CLOSE this
68*4882a593Smuzhiyun * socket up. We've got bigger problems than
69*4882a593Smuzhiyun * non-graceful socket closings.
70*4882a593Smuzhiyun */
71*4882a593Smuzhiyun DCCP_WARN("time wait bucket table overflow\n");
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun dccp_done(sk);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
dccp_create_openreq_child(const struct sock * sk,const struct request_sock * req,const struct sk_buff * skb)77*4882a593Smuzhiyun struct sock *dccp_create_openreq_child(const struct sock *sk,
78*4882a593Smuzhiyun const struct request_sock *req,
79*4882a593Smuzhiyun const struct sk_buff *skb)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun /*
82*4882a593Smuzhiyun * Step 3: Process LISTEN state
83*4882a593Smuzhiyun *
84*4882a593Smuzhiyun * (* Generate a new socket and switch to that socket *)
85*4882a593Smuzhiyun * Set S := new socket for this port pair
86*4882a593Smuzhiyun */
87*4882a593Smuzhiyun struct sock *newsk = inet_csk_clone_lock(sk, req, GFP_ATOMIC);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun if (newsk != NULL) {
90*4882a593Smuzhiyun struct dccp_request_sock *dreq = dccp_rsk(req);
91*4882a593Smuzhiyun struct inet_connection_sock *newicsk = inet_csk(newsk);
92*4882a593Smuzhiyun struct dccp_sock *newdp = dccp_sk(newsk);
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun newdp->dccps_role = DCCP_ROLE_SERVER;
95*4882a593Smuzhiyun newdp->dccps_hc_rx_ackvec = NULL;
96*4882a593Smuzhiyun newdp->dccps_service_list = NULL;
97*4882a593Smuzhiyun newdp->dccps_hc_rx_ccid = NULL;
98*4882a593Smuzhiyun newdp->dccps_hc_tx_ccid = NULL;
99*4882a593Smuzhiyun newdp->dccps_service = dreq->dreq_service;
100*4882a593Smuzhiyun newdp->dccps_timestamp_echo = dreq->dreq_timestamp_echo;
101*4882a593Smuzhiyun newdp->dccps_timestamp_time = dreq->dreq_timestamp_time;
102*4882a593Smuzhiyun newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun INIT_LIST_HEAD(&newdp->dccps_featneg);
105*4882a593Smuzhiyun /*
106*4882a593Smuzhiyun * Step 3: Process LISTEN state
107*4882a593Smuzhiyun *
108*4882a593Smuzhiyun * Choose S.ISS (initial seqno) or set from Init Cookies
109*4882a593Smuzhiyun * Initialize S.GAR := S.ISS
110*4882a593Smuzhiyun * Set S.ISR, S.GSR from packet (or Init Cookies)
111*4882a593Smuzhiyun *
112*4882a593Smuzhiyun * Setting AWL/AWH and SWL/SWH happens as part of the feature
113*4882a593Smuzhiyun * activation below, as these windows all depend on the local
114*4882a593Smuzhiyun * and remote Sequence Window feature values (7.5.2).
115*4882a593Smuzhiyun */
116*4882a593Smuzhiyun newdp->dccps_iss = dreq->dreq_iss;
117*4882a593Smuzhiyun newdp->dccps_gss = dreq->dreq_gss;
118*4882a593Smuzhiyun newdp->dccps_gar = newdp->dccps_iss;
119*4882a593Smuzhiyun newdp->dccps_isr = dreq->dreq_isr;
120*4882a593Smuzhiyun newdp->dccps_gsr = dreq->dreq_gsr;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /*
123*4882a593Smuzhiyun * Activate features: initialise CCIDs, sequence windows etc.
124*4882a593Smuzhiyun */
125*4882a593Smuzhiyun if (dccp_feat_activate_values(newsk, &dreq->dreq_featneg)) {
126*4882a593Smuzhiyun sk_free_unlock_clone(newsk);
127*4882a593Smuzhiyun return NULL;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun dccp_init_xmit_timers(newsk);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun __DCCP_INC_STATS(DCCP_MIB_PASSIVEOPENS);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun return newsk;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_create_openreq_child);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun /*
139*4882a593Smuzhiyun * Process an incoming packet for RESPOND sockets represented
140*4882a593Smuzhiyun * as an request_sock.
141*4882a593Smuzhiyun */
dccp_check_req(struct sock * sk,struct sk_buff * skb,struct request_sock * req)142*4882a593Smuzhiyun struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
143*4882a593Smuzhiyun struct request_sock *req)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun struct sock *child = NULL;
146*4882a593Smuzhiyun struct dccp_request_sock *dreq = dccp_rsk(req);
147*4882a593Smuzhiyun bool own_req;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun /* TCP/DCCP listeners became lockless.
150*4882a593Smuzhiyun * DCCP stores complex state in its request_sock, so we need
151*4882a593Smuzhiyun * a protection for them, now this code runs without being protected
152*4882a593Smuzhiyun * by the parent (listener) lock.
153*4882a593Smuzhiyun */
154*4882a593Smuzhiyun spin_lock_bh(&dreq->dreq_lock);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /* Check for retransmitted REQUEST */
157*4882a593Smuzhiyun if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) {
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun if (after48(DCCP_SKB_CB(skb)->dccpd_seq, dreq->dreq_gsr)) {
160*4882a593Smuzhiyun dccp_pr_debug("Retransmitted REQUEST\n");
161*4882a593Smuzhiyun dreq->dreq_gsr = DCCP_SKB_CB(skb)->dccpd_seq;
162*4882a593Smuzhiyun /*
163*4882a593Smuzhiyun * Send another RESPONSE packet
164*4882a593Smuzhiyun * To protect against Request floods, increment retrans
165*4882a593Smuzhiyun * counter (backoff, monitored by dccp_response_timer).
166*4882a593Smuzhiyun */
167*4882a593Smuzhiyun inet_rtx_syn_ack(sk, req);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun /* Network Duplicate, discard packet */
170*4882a593Smuzhiyun goto out;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun if (dccp_hdr(skb)->dccph_type != DCCP_PKT_ACK &&
176*4882a593Smuzhiyun dccp_hdr(skb)->dccph_type != DCCP_PKT_DATAACK)
177*4882a593Smuzhiyun goto drop;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /* Invalid ACK */
180*4882a593Smuzhiyun if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
181*4882a593Smuzhiyun dreq->dreq_iss, dreq->dreq_gss)) {
182*4882a593Smuzhiyun dccp_pr_debug("Invalid ACK number: ack_seq=%llu, "
183*4882a593Smuzhiyun "dreq_iss=%llu, dreq_gss=%llu\n",
184*4882a593Smuzhiyun (unsigned long long)
185*4882a593Smuzhiyun DCCP_SKB_CB(skb)->dccpd_ack_seq,
186*4882a593Smuzhiyun (unsigned long long) dreq->dreq_iss,
187*4882a593Smuzhiyun (unsigned long long) dreq->dreq_gss);
188*4882a593Smuzhiyun goto drop;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun if (dccp_parse_options(sk, dreq, skb))
192*4882a593Smuzhiyun goto drop;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL,
195*4882a593Smuzhiyun req, &own_req);
196*4882a593Smuzhiyun if (child) {
197*4882a593Smuzhiyun child = inet_csk_complete_hashdance(sk, child, req, own_req);
198*4882a593Smuzhiyun goto out;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
202*4882a593Smuzhiyun drop:
203*4882a593Smuzhiyun if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET)
204*4882a593Smuzhiyun req->rsk_ops->send_reset(sk, skb);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun inet_csk_reqsk_queue_drop(sk, req);
207*4882a593Smuzhiyun out:
208*4882a593Smuzhiyun spin_unlock_bh(&dreq->dreq_lock);
209*4882a593Smuzhiyun return child;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_check_req);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun /*
215*4882a593Smuzhiyun * Queue segment on the new socket if the new socket is active,
216*4882a593Smuzhiyun * otherwise we just shortcircuit this and continue with
217*4882a593Smuzhiyun * the new socket.
218*4882a593Smuzhiyun */
dccp_child_process(struct sock * parent,struct sock * child,struct sk_buff * skb)219*4882a593Smuzhiyun int dccp_child_process(struct sock *parent, struct sock *child,
220*4882a593Smuzhiyun struct sk_buff *skb)
221*4882a593Smuzhiyun __releases(child)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun int ret = 0;
224*4882a593Smuzhiyun const int state = child->sk_state;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun if (!sock_owned_by_user(child)) {
227*4882a593Smuzhiyun ret = dccp_rcv_state_process(child, skb, dccp_hdr(skb),
228*4882a593Smuzhiyun skb->len);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /* Wakeup parent, send SIGIO */
231*4882a593Smuzhiyun if (state == DCCP_RESPOND && child->sk_state != state)
232*4882a593Smuzhiyun parent->sk_data_ready(parent);
233*4882a593Smuzhiyun } else {
234*4882a593Smuzhiyun /* Alas, it is possible again, because we do lookup
235*4882a593Smuzhiyun * in main socket hash table and lock on listening
236*4882a593Smuzhiyun * socket does not protect us more.
237*4882a593Smuzhiyun */
238*4882a593Smuzhiyun __sk_add_backlog(child, skb);
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun bh_unlock_sock(child);
242*4882a593Smuzhiyun sock_put(child);
243*4882a593Smuzhiyun return ret;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_child_process);
247*4882a593Smuzhiyun
dccp_reqsk_send_ack(const struct sock * sk,struct sk_buff * skb,struct request_sock * rsk)248*4882a593Smuzhiyun void dccp_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
249*4882a593Smuzhiyun struct request_sock *rsk)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun DCCP_BUG("DCCP-ACK packets are never sent in LISTEN/RESPOND state");
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack);
255*4882a593Smuzhiyun
dccp_reqsk_init(struct request_sock * req,struct dccp_sock const * dp,struct sk_buff const * skb)256*4882a593Smuzhiyun int dccp_reqsk_init(struct request_sock *req,
257*4882a593Smuzhiyun struct dccp_sock const *dp, struct sk_buff const *skb)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun struct dccp_request_sock *dreq = dccp_rsk(req);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun spin_lock_init(&dreq->dreq_lock);
262*4882a593Smuzhiyun inet_rsk(req)->ir_rmt_port = dccp_hdr(skb)->dccph_sport;
263*4882a593Smuzhiyun inet_rsk(req)->ir_num = ntohs(dccp_hdr(skb)->dccph_dport);
264*4882a593Smuzhiyun inet_rsk(req)->acked = 0;
265*4882a593Smuzhiyun dreq->dreq_timestamp_echo = 0;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /* inherit feature negotiation options from listening socket */
268*4882a593Smuzhiyun return dccp_feat_clone_list(&dp->dccps_featneg, &dreq->dreq_featneg);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(dccp_reqsk_init);
272