Blame view

net/dccp/minisocks.c 7.27 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
2
3
4
5
6
  /*
   *  net/dccp/minisocks.c
   *
   *  An implementation of the DCCP protocol
   *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
7
   */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
8
  #include <linux/dccp.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
9
  #include <linux/gfp.h>
8a73cd09d   Gerrit Renker   [DCCP]: calling d...
10
  #include <linux/kernel.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
11
12
13
14
15
16
  #include <linux/skbuff.h>
  #include <linux/timer.h>
  
  #include <net/sock.h>
  #include <net/xfrm.h>
  #include <net/inet_timewait_sock.h>
ae31c3399   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
17
  #include "ackvec.h"
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
18
19
  #include "ccid.h"
  #include "dccp.h"
afe00251d   Andrea Bittau   [DCCP]: Initial f...
20
  #include "feat.h"
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
21

64cf1e5d8   Arnaldo Carvalho de Melo   [DCCP]: Finish th...
22
23
  struct inet_timewait_death_row dccp_death_row = {
  	.sysctl_max_tw_buckets = NR_FILE * 2,
64cf1e5d8   Arnaldo Carvalho de Melo   [DCCP]: Finish th...
24
  	.hashinfo	= &dccp_hashinfo,
64cf1e5d8   Arnaldo Carvalho de Melo   [DCCP]: Finish th...
25
  };
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
26
  EXPORT_SYMBOL_GPL(dccp_death_row);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
27
28
  void dccp_time_wait(struct sock *sk, int state, int timeo)
  {
789f558cf   Eric Dumazet   tcp/dccp: get rid...
29
  	struct inet_timewait_sock *tw;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
30

789f558cf   Eric Dumazet   tcp/dccp: get rid...
31
  	tw = inet_twsk_alloc(sk, &dccp_death_row, state);
64cf1e5d8   Arnaldo Carvalho de Melo   [DCCP]: Finish th...
32
33
34
35
  
  	if (tw != NULL) {
  		const struct inet_connection_sock *icsk = inet_csk(sk);
  		const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
dfd56b8b3   Eric Dumazet   net: use IS_ENABL...
36
  #if IS_ENABLED(CONFIG_IPV6)
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
37
  		if (tw->tw_family == PF_INET6) {
efe4208f4   Eric Dumazet   ipv6: make lookup...
38
39
  			tw->tw_v6_daddr = sk->sk_v6_daddr;
  			tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
9fe516ba3   Eric Dumazet   inet: move ipv6on...
40
  			tw->tw_ipv6only = sk->sk_ipv6only;
3df80d932   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
41
42
  		}
  #endif
64cf1e5d8   Arnaldo Carvalho de Melo   [DCCP]: Finish th...
43
44
45
46
  
  		/* Get the TIME_WAIT timeout firing. */
  		if (timeo < rto)
  			timeo = rto;
64cf1e5d8   Arnaldo Carvalho de Melo   [DCCP]: Finish th...
47
48
  		if (state == DCCP_TIME_WAIT)
  			timeo = DCCP_TIMEWAIT_LEN;
cfac7f836   Eric Dumazet   tcp/dccp: block b...
49
50
51
52
53
  		/* tw_timer is pinned, so we need to make sure BH are disabled
  		 * in following section, otherwise timer handler could run before
  		 * we complete the initialization.
  		 */
  		local_bh_disable();
789f558cf   Eric Dumazet   tcp/dccp: get rid...
54
  		inet_twsk_schedule(tw, timeo);
ec94c2696   Eric Dumazet   tcp/dccp: avoid o...
55
56
57
58
  		/* Linkage updates.
  		 * Note that access to tw after this point is illegal.
  		 */
  		inet_twsk_hashdance(tw, sk, &dccp_hashinfo);
cfac7f836   Eric Dumazet   tcp/dccp: block b...
59
  		local_bh_enable();
64cf1e5d8   Arnaldo Carvalho de Melo   [DCCP]: Finish th...
60
61
62
63
64
  	} else {
  		/* Sorry, if we're out of memory, just CLOSE this
  		 * socket up.  We've got bigger problems than
  		 * non-graceful socket closings.
  		 */
59348b19e   Gerrit Renker   [DCCP]: Simplifie...
65
66
  		DCCP_WARN("time wait bucket table overflow
  ");
64cf1e5d8   Arnaldo Carvalho de Melo   [DCCP]: Finish th...
67
68
69
  	}
  
  	dccp_done(sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
70
  }
54105f98f   Eric Dumazet   dccp: constify dc...
71
  struct sock *dccp_create_openreq_child(const struct sock *sk,
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
72
73
74
75
76
77
  				       const struct request_sock *req,
  				       const struct sk_buff *skb)
  {
  	/*
  	 * Step 3: Process LISTEN state
  	 *
d83ca5acc   Gerrit Renker   [DCCP]: Update co...
78
79
  	 *   (* Generate a new socket and switch to that socket *)
  	 *   Set S := new socket for this port pair
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
80
  	 */
e56c57d0d   Eric Dumazet   net: rename sk_cl...
81
  	struct sock *newsk = inet_csk_clone_lock(sk, req, GFP_ATOMIC);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
82
83
  
  	if (newsk != NULL) {
192b27ff3   Gerrit Renker   dccp: Integration...
84
  		struct dccp_request_sock *dreq = dccp_rsk(req);
99c72ce09   Gerrit Renker   [DCCP]: Set RTO f...
85
  		struct inet_connection_sock *newicsk = inet_csk(newsk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
86
  		struct dccp_sock *newdp = dccp_sk(newsk);
b4d4f7c70   Gerrit Renker   [DCCP]: Handle ti...
87
88
89
90
91
92
93
  		newdp->dccps_role	    = DCCP_ROLE_SERVER;
  		newdp->dccps_hc_rx_ackvec   = NULL;
  		newdp->dccps_service_list   = NULL;
  		newdp->dccps_service	    = dreq->dreq_service;
  		newdp->dccps_timestamp_echo = dreq->dreq_timestamp_echo;
  		newdp->dccps_timestamp_time = dreq->dreq_timestamp_time;
  		newicsk->icsk_rto	    = DCCP_TIMEOUT_INIT;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
94

ac75773c2   Gerrit Renker   dccp: Per-socket ...
95
  		INIT_LIST_HEAD(&newdp->dccps_featneg);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
96
97
98
  		/*
  		 * Step 3: Process LISTEN state
  		 *
d83ca5acc   Gerrit Renker   [DCCP]: Update co...
99
100
  		 *    Choose S.ISS (initial seqno) or set from Init Cookies
  		 *    Initialize S.GAR := S.ISS
0b53d4604   Gerrit Renker   dccp: fix the adj...
101
102
103
104
105
  		 *    Set S.ISR, S.GSR from packet (or Init Cookies)
  		 *
  		 *    Setting AWL/AWH and SWL/SWH happens as part of the feature
  		 *    activation below, as these windows all depend on the local
  		 *    and remote Sequence Window feature values (7.5.2).
03ace394a   Arnaldo Carvalho de Melo   [DCCP]: Fix the A...
106
  		 */
f541fb7e2   Samuel Jero   dccp: fix bug in ...
107
108
  		newdp->dccps_iss = dreq->dreq_iss;
  		newdp->dccps_gss = dreq->dreq_gss;
0b53d4604   Gerrit Renker   dccp: fix the adj...
109
  		newdp->dccps_gar = newdp->dccps_iss;
f541fb7e2   Samuel Jero   dccp: fix bug in ...
110
111
  		newdp->dccps_isr = dreq->dreq_isr;
  		newdp->dccps_gsr = dreq->dreq_gsr;
03ace394a   Arnaldo Carvalho de Melo   [DCCP]: Fix the A...
112

192b27ff3   Gerrit Renker   dccp: Integration...
113
  		/*
0b53d4604   Gerrit Renker   dccp: fix the adj...
114
  		 * Activate features: initialise CCIDs, sequence windows etc.
192b27ff3   Gerrit Renker   dccp: Integration...
115
116
  		 */
  		if (dccp_feat_activate_values(newsk, &dreq->dreq_featneg)) {
94352d450   Arnaldo Carvalho de Melo   net: Introduce sk...
117
  			sk_free_unlock_clone(newsk);
192b27ff3   Gerrit Renker   dccp: Integration...
118
119
  			return NULL;
  		}
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
120
  		dccp_init_xmit_timers(newsk);
aa62d76b6   Eric Dumazet   dccp: rename DCCP...
121
  		__DCCP_INC_STATS(DCCP_MIB_PASSIVEOPENS);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
122
123
124
  	}
  	return newsk;
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
125
  EXPORT_SYMBOL_GPL(dccp_create_openreq_child);
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
126
  /*
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
127
128
129
130
   * Process an incoming packet for RESPOND sockets represented
   * as an request_sock.
   */
  struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
52452c542   Eric Dumazet   inet: drop prev p...
131
  			    struct request_sock *req)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
132
133
  {
  	struct sock *child = NULL;
8109616e2   Gerrit Renker   [DCCP]: Add (miss...
134
  	struct dccp_request_sock *dreq = dccp_rsk(req);
5e0724d02   Eric Dumazet   tcp/dccp: fix has...
135
  	bool own_req;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
136

62f8f4d90   Eric Dumazet   dccp: fix use-aft...
137
138
139
140
141
142
  	/* TCP/DCCP listeners became lockless.
  	 * DCCP stores complex state in its request_sock, so we need
  	 * a protection for them, now this code runs without being protected
  	 * by the parent (listener) lock.
  	 */
  	spin_lock_bh(&dreq->dreq_lock);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
143
144
  	/* Check for retransmitted REQUEST */
  	if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) {
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
145

f541fb7e2   Samuel Jero   dccp: fix bug in ...
146
  		if (after48(DCCP_SKB_CB(skb)->dccpd_seq, dreq->dreq_gsr)) {
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
147
148
  			dccp_pr_debug("Retransmitted REQUEST
  ");
f541fb7e2   Samuel Jero   dccp: fix bug in ...
149
  			dreq->dreq_gsr = DCCP_SKB_CB(skb)->dccpd_seq;
e11d9d308   Gerrit Renker   [DCCP]: Increment...
150
151
152
153
154
  			/*
  			 * Send another RESPONSE packet
  			 * To protect against Request floods, increment retrans
  			 * counter (backoff, monitored by dccp_response_timer).
  			 */
e6c022a4f   Eric Dumazet   tcp: better retra...
155
  			inet_rtx_syn_ack(sk, req);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
156
157
  		}
  		/* Network Duplicate, discard packet */
62f8f4d90   Eric Dumazet   dccp: fix use-aft...
158
  		goto out;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
159
160
161
162
163
164
165
166
167
  	}
  
  	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
  
  	if (dccp_hdr(skb)->dccph_type != DCCP_PKT_ACK &&
  	    dccp_hdr(skb)->dccph_type != DCCP_PKT_DATAACK)
  		goto drop;
  
  	/* Invalid ACK */
f541fb7e2   Samuel Jero   dccp: fix bug in ...
168
169
  	if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
  				dreq->dreq_iss, dreq->dreq_gss)) {
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
170
  		dccp_pr_debug("Invalid ACK number: ack_seq=%llu, "
f541fb7e2   Samuel Jero   dccp: fix bug in ...
171
172
  			      "dreq_iss=%llu, dreq_gss=%llu
  ",
f6ccf5541   David S. Miller   [DCCP]: Fix u64 p...
173
174
  			      (unsigned long long)
  			      DCCP_SKB_CB(skb)->dccpd_ack_seq,
f541fb7e2   Samuel Jero   dccp: fix bug in ...
175
176
  			      (unsigned long long) dreq->dreq_iss,
  			      (unsigned long long) dreq->dreq_gss);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
177
178
  		goto drop;
  	}
8109616e2   Gerrit Renker   [DCCP]: Add (miss...
179
180
  	if (dccp_parse_options(sk, dreq, skb))
  		 goto drop;
5e0724d02   Eric Dumazet   tcp/dccp: fix has...
181
182
  	child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL,
  							 req, &own_req);
62f8f4d90   Eric Dumazet   dccp: fix use-aft...
183
184
185
186
  	if (child) {
  		child = inet_csk_complete_hashdance(sk, child, req, own_req);
  		goto out;
  	}
5e0724d02   Eric Dumazet   tcp/dccp: fix has...
187

7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
188
189
190
  	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
  drop:
  	if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
191
  		req->rsk_ops->send_reset(sk, skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
192

52452c542   Eric Dumazet   inet: drop prev p...
193
  	inet_csk_reqsk_queue_drop(sk, req);
62f8f4d90   Eric Dumazet   dccp: fix use-aft...
194
195
196
  out:
  	spin_unlock_bh(&dreq->dreq_lock);
  	return child;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
197
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
198
  EXPORT_SYMBOL_GPL(dccp_check_req);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
199
200
201
202
203
204
205
  /*
   *  Queue segment on the new socket if the new socket is active,
   *  otherwise we just shortcircuit this and continue with
   *  the new socket.
   */
  int dccp_child_process(struct sock *parent, struct sock *child,
  		       struct sk_buff *skb)
3283ff2ea   Jules Irenge   dccp: Add missing...
206
  	__releases(child)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
207
208
209
210
211
  {
  	int ret = 0;
  	const int state = child->sk_state;
  
  	if (!sock_owned_by_user(child)) {
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
212
213
  		ret = dccp_rcv_state_process(child, skb, dccp_hdr(skb),
  					     skb->len);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
214
215
216
  
  		/* Wakeup parent, send SIGIO */
  		if (state == DCCP_RESPOND && child->sk_state != state)
676d23690   David S. Miller   net: Fix use afte...
217
  			parent->sk_data_ready(parent);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
218
219
220
221
222
  	} else {
  		/* Alas, it is possible again, because we do lookup
  		 * in main socket hash table and lock on listening
  		 * socket does not protect us more.
  		 */
a3a858ff1   Zhu Yi   net: backlog func...
223
  		__sk_add_backlog(child, skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
224
225
226
227
228
229
  	}
  
  	bh_unlock_sock(child);
  	sock_put(child);
  	return ret;
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
230
231
  
  EXPORT_SYMBOL_GPL(dccp_child_process);
8a73cd09d   Gerrit Renker   [DCCP]: calling d...
232

a00e74442   Eric Dumazet   tcp/dccp: constif...
233
  void dccp_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
6edafaaf6   Gui Jianfeng   tcp: Fix kernel p...
234
  			 struct request_sock *rsk)
8a73cd09d   Gerrit Renker   [DCCP]: calling d...
235
  {
59348b19e   Gerrit Renker   [DCCP]: Simplifie...
236
  	DCCP_BUG("DCCP-ACK packets are never sent in LISTEN/RESPOND state");
8a73cd09d   Gerrit Renker   [DCCP]: calling d...
237
238
239
  }
  
  EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack);
cf557926f   Gerrit Renker   [DCCP]: tidy up d...
240

ac75773c2   Gerrit Renker   dccp: Per-socket ...
241
242
  int dccp_reqsk_init(struct request_sock *req,
  		    struct dccp_sock const *dp, struct sk_buff const *skb)
cf557926f   Gerrit Renker   [DCCP]: tidy up d...
243
  {
b4d4f7c70   Gerrit Renker   [DCCP]: Handle ti...
244
  	struct dccp_request_sock *dreq = dccp_rsk(req);
62f8f4d90   Eric Dumazet   dccp: fix use-aft...
245
  	spin_lock_init(&dreq->dreq_lock);
b44084c2c   Eric Dumazet   inet: rename ir_l...
246
247
248
249
  	inet_rsk(req)->ir_rmt_port = dccp_hdr(skb)->dccph_sport;
  	inet_rsk(req)->ir_num	   = ntohs(dccp_hdr(skb)->dccph_dport);
  	inet_rsk(req)->acked	   = 0;
  	dreq->dreq_timestamp_echo  = 0;
ac75773c2   Gerrit Renker   dccp: Per-socket ...
250
251
252
  
  	/* inherit feature negotiation options from listening socket */
  	return dccp_feat_clone_list(&dp->dccps_featneg, &dreq->dreq_featneg);
cf557926f   Gerrit Renker   [DCCP]: tidy up d...
253
254
255
  }
  
  EXPORT_SYMBOL_GPL(dccp_reqsk_init);