Blame view

net/dccp/output.c 20.2 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
  /*
   *  net/dccp/output.c
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
4
   *
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
5
6
   *  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>
48918a4db   Herbert Xu   [DCCP]: Simplify ...
9
  #include <linux/kernel.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
10
  #include <linux/skbuff.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
11
  #include <linux/slab.h>
174cd4b1e   Ingo Molnar   sched/headers: Pr...
12
  #include <linux/sched/signal.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
13

14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
14
  #include <net/inet_sock.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
15
  #include <net/sock.h>
ae31c3399   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
16
  #include "ackvec.h"
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
17
18
19
20
21
22
23
  #include "ccid.h"
  #include "dccp.h"
  
  static inline void dccp_event_ack_sent(struct sock *sk)
  {
  	inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
  }
8695e8019   Gerrit Renker   dccp: combine the...
24
25
  /* enqueue @skb on sk_send_head for retransmission, return clone to send now */
  static struct sk_buff *dccp_skb_entail(struct sock *sk, struct sk_buff *skb)
48918a4db   Herbert Xu   [DCCP]: Simplify ...
26
27
28
29
  {
  	skb_set_owner_w(skb, sk);
  	WARN_ON(sk->sk_send_head);
  	sk->sk_send_head = skb;
8695e8019   Gerrit Renker   dccp: combine the...
30
  	return skb_clone(sk->sk_send_head, gfp_any());
48918a4db   Herbert Xu   [DCCP]: Simplify ...
31
  }
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
32
33
34
35
36
37
  /*
   * All SKB's seen here are completely headerless. It is our
   * job to build the DCCP header, and pass the packet down to
   * IP so it can do the same plus pass the packet off to the
   * device.
   */
48918a4db   Herbert Xu   [DCCP]: Simplify ...
38
  static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
39
40
  {
  	if (likely(skb != NULL)) {
d9d8da805   David S. Miller   inet: Pass flowi ...
41
  		struct inet_sock *inet = inet_sk(sk);
57cca05af   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
42
  		const struct inet_connection_sock *icsk = inet_csk(sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
43
44
45
46
  		struct dccp_sock *dp = dccp_sk(sk);
  		struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
  		struct dccp_hdr *dh;
  		/* XXX For now we're using only 48 bits sequence numbers */
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
47
  		const u32 dccp_header_size = sizeof(*dh) +
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
48
  					     sizeof(struct dccp_hdr_ext) +
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
49
  					  dccp_packet_hdr_len(dcb->dccpd_type);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
50
51
  		int err, set_ack = 1;
  		u64 ackno = dp->dccps_gsr;
73f18fdbc   Gerrit Renker   dccp: Bug-Fix - A...
52
53
54
55
56
  		/*
  		 * Increment GSS here already in case the option code needs it.
  		 * Update GSS for real only if option processing below succeeds.
  		 */
  		dcb->dccpd_seq = ADD48(dp->dccps_gss, 1);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
57

7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
58
59
60
  		switch (dcb->dccpd_type) {
  		case DCCP_PKT_DATA:
  			set_ack = 0;
edc9e8191   Herbert Xu   [DCCP]: Set socke...
61
62
  			/* fall through */
  		case DCCP_PKT_DATAACK:
ee1a15922   Gerrit Renker   [DCCP]: Remove du...
63
  		case DCCP_PKT_RESET:
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
64
  			break;
edc9e8191   Herbert Xu   [DCCP]: Set socke...
65

afe00251d   Andrea Bittau   [DCCP]: Initial f...
66
67
  		case DCCP_PKT_REQUEST:
  			set_ack = 0;
73f18fdbc   Gerrit Renker   dccp: Bug-Fix - A...
68
69
70
  			/* Use ISS on the first (non-retransmitted) Request. */
  			if (icsk->icsk_retransmits == 0)
  				dcb->dccpd_seq = dp->dccps_iss;
afe00251d   Andrea Bittau   [DCCP]: Initial f...
71
  			/* fall through */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
72
73
  		case DCCP_PKT_SYNC:
  		case DCCP_PKT_SYNCACK:
b0d045ca4   Gerrit Renker   [DCCP]: Parameter...
74
  			ackno = dcb->dccpd_ack_seq;
edc9e8191   Herbert Xu   [DCCP]: Set socke...
75
76
77
  			/* fall through */
  		default:
  			/*
ee1a15922   Gerrit Renker   [DCCP]: Remove du...
78
79
80
81
  			 * Set owner/destructor: some skbs are allocated via
  			 * alloc_skb (e.g. when retransmission may happen).
  			 * Only Data, DataAck, and Reset packets should come
  			 * through here with skb->sk set.
edc9e8191   Herbert Xu   [DCCP]: Set socke...
82
83
84
  			 */
  			WARN_ON(skb->sk);
  			skb_set_owner_w(skb, sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
85
86
  			break;
  		}
24117727b   Arnaldo Carvalho de Melo   [DCCP]: Fix ackno...
87

2d0817d11   Arnaldo Carvalho de Melo   [DCCP] options: M...
88
89
90
91
  		if (dccp_insert_options(sk, skb)) {
  			kfree_skb(skb);
  			return -EPROTO;
  		}
c9eaf1734   YOSHIFUJI Hideaki   [NET] DCCP: Fix w...
92

fda0fd6c5   Herbert Xu   [DCCP]: Use skb_s...
93

7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
94
  		/* Build DCCP header and checksum it. */
9b42078ed   Gerrit Renker   [DCCP]: Combine a...
95
  		dh = dccp_zeroed_hdr(skb, dccp_header_size);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
96
  		dh->dccph_type	= dcb->dccpd_type;
c720c7e83   Eric Dumazet   inet: rename some...
97
98
  		dh->dccph_sport	= inet->inet_sport;
  		dh->dccph_dport	= inet->inet_dport;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
99
100
  		dh->dccph_doff	= (dccp_header_size + dcb->dccpd_opt_len) / 4;
  		dh->dccph_ccval	= dcb->dccpd_ccval;
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
101
  		dh->dccph_cscov = dp->dccps_pcslen;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
102
103
  		/* XXX For now we're using only 48 bits sequence numbers */
  		dh->dccph_x	= 1;
73f18fdbc   Gerrit Renker   dccp: Bug-Fix - A...
104
  		dccp_update_gss(sk, dcb->dccpd_seq);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
105
106
107
108
109
110
  		dccp_hdr_set_seq(dh, dp->dccps_gss);
  		if (set_ack)
  			dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno);
  
  		switch (dcb->dccpd_type) {
  		case DCCP_PKT_REQUEST:
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
111
  			dccp_hdr_request(skb)->dccph_req_service =
67e6b6292   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
112
  							dp->dccps_service;
73f18fdbc   Gerrit Renker   dccp: Bug-Fix - A...
113
114
115
116
117
  			/*
  			 * Limit Ack window to ISS <= P.ackno <= GSS, so that
  			 * only Responses to Requests we sent are considered.
  			 */
  			dp->dccps_awl = dp->dccps_iss;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
118
119
  			break;
  		case DCCP_PKT_RESET:
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
120
121
  			dccp_hdr_reset(skb)->dccph_reset_code =
  							dcb->dccpd_reset_code;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
122
123
  			break;
  		}
bb2962461   Herbert Xu   inet: Remove unus...
124
  		icsk->icsk_af_ops->send_check(sk, skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
125

7ad07e7cf   Arnaldo Carvalho de Melo   [DCCP]: Implement...
126
  		if (set_ack)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
127
128
129
  			dccp_event_ack_sent(sk);
  
  		DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
b0270e910   Eric Dumazet   ipv4: add a sock ...
130
  		err = icsk->icsk_af_ops->queue_xmit(sk, skb, &inet->cork.fl);
b9df3cb8c   Gerrit Renker   [TCP/DCCP]: Intro...
131
  		return net_xmit_eval(err);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
132
133
134
  	}
  	return -ENOBUFS;
  }
6179983ad   Gerrit Renker   [DCCP]: Introduci...
135
  /**
25985edce   Lucas De Marchi   Fix common misspe...
136
   * dccp_determine_ccmps  -  Find out about CCID-specific packet-size limits
6179983ad   Gerrit Renker   [DCCP]: Introduci...
137
138
139
140
141
142
143
144
145
146
147
148
   * We only consider the HC-sender CCID for setting the CCMPS (RFC 4340, 14.),
   * since the RX CCID is restricted to feedback packets (Acks), which are small
   * in comparison with the data traffic. A value of 0 means "no current CCMPS".
   */
  static u32 dccp_determine_ccmps(const struct dccp_sock *dp)
  {
  	const struct ccid *tx_ccid = dp->dccps_hc_tx_ccid;
  
  	if (tx_ccid == NULL || tx_ccid->ccid_ops == NULL)
  		return 0;
  	return tx_ccid->ccid_ops->ccid_ccmps;
  }
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
149
150
  unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
  {
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
151
  	struct inet_connection_sock *icsk = inet_csk(sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
152
  	struct dccp_sock *dp = dccp_sk(sk);
6179983ad   Gerrit Renker   [DCCP]: Introduci...
153
  	u32 ccmps = dccp_determine_ccmps(dp);
361a5c1dd   Gerrit Renker   dccp: Minimise he...
154
  	u32 cur_mps = ccmps ? min(pmtu, ccmps) : pmtu;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
155

6179983ad   Gerrit Renker   [DCCP]: Introduci...
156
157
158
  	/* Account for header lengths and IPv4/v6 option overhead */
  	cur_mps -= (icsk->icsk_af_ops->net_header_len + icsk->icsk_ext_hdr_len +
  		    sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
159
160
  
  	/*
361a5c1dd   Gerrit Renker   dccp: Minimise he...
161
162
163
164
165
166
167
168
169
170
171
  	 * Leave enough headroom for common DCCP header options.
  	 * This only considers options which may appear on DCCP-Data packets, as
  	 * per table 3 in RFC 4340, 5.8. When running out of space for other
  	 * options (eg. Ack Vector which can take up to 255 bytes), it is better
  	 * to schedule a separate Ack. Thus we leave headroom for the following:
  	 *  - 1 byte for Slow Receiver (11.6)
  	 *  - 6 bytes for Timestamp (13.1)
  	 *  - 10 bytes for Timestamp Echo (13.3)
  	 *  - 8 bytes for NDP count (7.7, when activated)
  	 *  - 6 bytes for Data Checksum (9.3)
  	 *  - %DCCPAV_MIN_OPTLEN bytes for Ack Vector size (11.4, when enabled)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
172
  	 */
361a5c1dd   Gerrit Renker   dccp: Minimise he...
173
174
  	cur_mps -= roundup(1 + 6 + 10 + dp->dccps_send_ndp_count * 8 + 6 +
  			   (dp->dccps_hc_rx_ackvec ? DCCPAV_MIN_OPTLEN : 0), 4);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
175
176
  
  	/* And store cached results */
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
177
  	icsk->icsk_pmtu_cookie = pmtu;
6179983ad   Gerrit Renker   [DCCP]: Introduci...
178
  	dp->dccps_mss_cache = cur_mps;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
179

6179983ad   Gerrit Renker   [DCCP]: Introduci...
180
  	return cur_mps;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
181
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
182
  EXPORT_SYMBOL_GPL(dccp_sync_mss);
c530cfb1c   Arnaldo Carvalho de Melo   [CCID3]: Call sk-...
183
184
  void dccp_write_space(struct sock *sk)
  {
438154823   Eric Dumazet   net: sock_def_rea...
185
  	struct socket_wq *wq;
c530cfb1c   Arnaldo Carvalho de Melo   [CCID3]: Call sk-...
186

438154823   Eric Dumazet   net: sock_def_rea...
187
188
  	rcu_read_lock();
  	wq = rcu_dereference(sk->sk_wq);
1ce0bf50a   Herbert Xu   net: Generalise w...
189
  	if (skwq_has_sleeper(wq))
438154823   Eric Dumazet   net: sock_def_rea...
190
  		wake_up_interruptible(&wq->wait);
c530cfb1c   Arnaldo Carvalho de Melo   [CCID3]: Call sk-...
191
192
  	/* Should agree with poll, otherwise some programs break */
  	if (sock_writeable(sk))
8d8ad9d7c   Pavel Emelyanov   [NET]: Name magic...
193
  		sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
c530cfb1c   Arnaldo Carvalho de Melo   [CCID3]: Call sk-...
194

438154823   Eric Dumazet   net: sock_def_rea...
195
  	rcu_read_unlock();
c530cfb1c   Arnaldo Carvalho de Melo   [CCID3]: Call sk-...
196
  }
d6809c12b   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
197
  /**
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
198
   * dccp_wait_for_ccid  -  Await CCID send permission
bc8498721   Gerrit Renker   [DCCP]: Wait for ...
199
   * @sk:    socket to wait for
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
200
   * @delay: timeout in jiffies
2c53040f0   Ben Hutchings   net: Fix (nearly-...
201
   *
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
202
   * This is used by CCIDs which need to delay the send time in process context.
d6809c12b   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
203
   */
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
204
  static int dccp_wait_for_ccid(struct sock *sk, unsigned long delay)
d6809c12b   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
205
  {
d6809c12b   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
206
  	DEFINE_WAIT(wait);
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
207
  	long remaining;
d6809c12b   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
208

b1fcf55ee   Gerrit Renker   dccp: Refine the ...
209
210
211
  	prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
  	sk->sk_write_pending++;
  	release_sock(sk);
bc8498721   Gerrit Renker   [DCCP]: Wait for ...
212

b1fcf55ee   Gerrit Renker   dccp: Refine the ...
213
  	remaining = schedule_timeout(delay);
d6809c12b   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
214

b1fcf55ee   Gerrit Renker   dccp: Refine the ...
215
216
  	lock_sock(sk);
  	sk->sk_write_pending--;
aa3951451   Eric Dumazet   net: sk_sleep() h...
217
  	finish_wait(sk_sleep(sk), &wait);
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
218
219
220
221
  
  	if (signal_pending(current) || sk->sk_err)
  		return -1;
  	return remaining;
d6809c12b   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
222
  }
dc841e30e   Gerrit Renker   dccp: Extend CCID...
223
224
225
226
227
228
229
230
  /**
   * dccp_xmit_packet  -  Send data packet under control of CCID
   * Transmits next-queued payload and informs CCID to account for the packet.
   */
  static void dccp_xmit_packet(struct sock *sk)
  {
  	int err, len;
  	struct dccp_sock *dp = dccp_sk(sk);
871a2c16c   Tomasz Grobelny   dccp: Policy-base...
231
  	struct sk_buff *skb = dccp_qpolicy_pop(sk);
dc841e30e   Gerrit Renker   dccp: Extend CCID...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  
  	if (unlikely(skb == NULL))
  		return;
  	len = skb->len;
  
  	if (sk->sk_state == DCCP_PARTOPEN) {
  		const u32 cur_mps = dp->dccps_mss_cache - DCCP_FEATNEG_OVERHEAD;
  		/*
  		 * See 8.1.5 - Handshake Completion.
  		 *
  		 * For robustness we resend Confirm options until the client has
  		 * entered OPEN. During the initial feature negotiation, the MPS
  		 * is smaller than usual, reduced by the Change/Confirm options.
  		 */
  		if (!list_empty(&dp->dccps_featneg) && len > cur_mps) {
  			DCCP_WARN("Payload too large (%d) for featneg.
  ", len);
  			dccp_send_ack(sk);
  			dccp_feat_list_purge(&dp->dccps_featneg);
  		}
  
  		inet_csk_schedule_ack(sk);
  		inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
  					      inet_csk(sk)->icsk_rto,
  					      DCCP_RTO_MAX);
  		DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_DATAACK;
  	} else if (dccp_ack_pending(sk)) {
  		DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_DATAACK;
  	} else {
  		DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_DATA;
  	}
  
  	err = dccp_transmit_skb(sk, skb);
  	if (err)
  		dccp_pr_debug("transmit_skb() returned err=%d
  ", err);
  	/*
  	 * Register this one as sent even if an error occurred. To the remote
  	 * end a local packet drop is indistinguishable from network loss, i.e.
  	 * any local drop will eventually be reported via receiver feedback.
  	 */
  	ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, len);
d83447f09   Gerrit Renker   dccp ccid-2: Sche...
274
275
276
277
278
279
280
281
282
  
  	/*
  	 * If the CCID needs to transfer additional header options out-of-band
  	 * (e.g. Ack Vectors or feature-negotiation options), it activates this
  	 * flag to schedule a Sync. The Sync will automatically incorporate all
  	 * currently pending header options, thus clearing the backlog.
  	 */
  	if (dp->dccps_sync_scheduled)
  		dccp_send_sync(sk, dp->dccps_gsr, DCCP_PKT_SYNC);
dc841e30e   Gerrit Renker   dccp: Extend CCID...
283
  }
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
  /**
   * dccp_flush_write_queue  -  Drain queue at end of connection
   * Since dccp_sendmsg queues packets without waiting for them to be sent, it may
   * happen that the TX queue is not empty at the end of a connection. We give the
   * HC-sender CCID a grace period of up to @time_budget jiffies. If this function
   * returns with a non-empty write queue, it will be purged later.
   */
  void dccp_flush_write_queue(struct sock *sk, long *time_budget)
  {
  	struct dccp_sock *dp = dccp_sk(sk);
  	struct sk_buff *skb;
  	long delay, rc;
  
  	while (*time_budget > 0 && (skb = skb_peek(&sk->sk_write_queue))) {
  		rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);
  
  		switch (ccid_packet_dequeue_eval(rc)) {
  		case CCID_PACKET_WILL_DEQUEUE_LATER:
  			/*
  			 * If the CCID determines when to send, the next sending
  			 * time is unknown or the CCID may not even send again
  			 * (e.g. remote host crashes or lost Ack packets).
  			 */
  			DCCP_WARN("CCID did not manage to send all packets
  ");
  			return;
  		case CCID_PACKET_DELAY:
  			delay = msecs_to_jiffies(rc);
  			if (delay > *time_budget)
  				return;
  			rc = dccp_wait_for_ccid(sk, delay);
  			if (rc < 0)
  				return;
  			*time_budget -= (delay - rc);
  			/* check again if we can send now */
  			break;
  		case CCID_PACKET_SEND_AT_ONCE:
  			dccp_xmit_packet(sk);
  			break;
  		case CCID_PACKET_ERR:
  			skb_dequeue(&sk->sk_write_queue);
  			kfree_skb(skb);
  			dccp_pr_debug("packet discarded due to err=%ld
  ", rc);
  		}
  	}
  }
  
  void dccp_write_xmit(struct sock *sk)
27258ee54   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
333
  {
97e5848dd   Ian McDonald   [DCCP]: Introduce...
334
335
  	struct dccp_sock *dp = dccp_sk(sk);
  	struct sk_buff *skb;
97e5848dd   Ian McDonald   [DCCP]: Introduce...
336

871a2c16c   Tomasz Grobelny   dccp: Policy-base...
337
  	while ((skb = dccp_qpolicy_top(sk))) {
dc841e30e   Gerrit Renker   dccp: Extend CCID...
338
  		int rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb);
d6809c12b   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
339

dc841e30e   Gerrit Renker   dccp: Extend CCID...
340
341
342
343
  		switch (ccid_packet_dequeue_eval(rc)) {
  		case CCID_PACKET_WILL_DEQUEUE_LATER:
  			return;
  		case CCID_PACKET_DELAY:
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
344
345
346
  			sk_reset_timer(sk, &dp->dccps_xmit_timer,
  				       jiffies + msecs_to_jiffies(rc));
  			return;
dc841e30e   Gerrit Renker   dccp: Extend CCID...
347
348
349
350
  		case CCID_PACKET_SEND_AT_ONCE:
  			dccp_xmit_packet(sk);
  			break;
  		case CCID_PACKET_ERR:
871a2c16c   Tomasz Grobelny   dccp: Policy-base...
351
  			dccp_qpolicy_drop(sk, skb);
dc841e30e   Gerrit Renker   dccp: Extend CCID...
352
353
  			dccp_pr_debug("packet discarded due to err=%d
  ", rc);
f6282f4da   Gerrit Renker   [DCCP]: Warn when...
354
  		}
97e5848dd   Ian McDonald   [DCCP]: Introduce...
355
  	}
27258ee54   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
356
  }
59435444a   Gerrit Renker   dccp: Allow to di...
357
358
359
360
361
362
363
364
365
366
  /**
   * dccp_retransmit_skb  -  Retransmit Request, Close, or CloseReq packets
   * There are only four retransmittable packet types in DCCP:
   * - Request  in client-REQUEST  state (sec. 8.1.1),
   * - CloseReq in server-CLOSEREQ state (sec. 8.3),
   * - Close    in   node-CLOSING  state (sec. 8.3),
   * - Acks in client-PARTOPEN state (sec. 8.1.5, handled by dccp_delack_timer()).
   * This function expects sk->sk_send_head to contain the original skb.
   */
  int dccp_retransmit_skb(struct sock *sk)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
367
  {
59435444a   Gerrit Renker   dccp: Allow to di...
368
  	WARN_ON(sk->sk_send_head == NULL);
57cca05af   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
369
  	if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
370
  		return -EHOSTUNREACH; /* Routing failure or similar. */
59435444a   Gerrit Renker   dccp: Allow to di...
371
372
373
374
  	/* this count is used to distinguish original and retransmitted skb */
  	inet_csk(sk)->icsk_retransmits++;
  
  	return dccp_transmit_skb(sk, skb_clone(sk->sk_send_head, GFP_ATOMIC));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
375
  }
802885fc0   Eric Dumazet   dccp: constify dc...
376
  struct sk_buff *dccp_make_response(const struct sock *sk, struct dst_entry *dst,
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
377
378
379
  				   struct request_sock *req)
  {
  	struct dccp_hdr *dh;
67e6b6292   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
380
  	struct dccp_request_sock *dreq;
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
381
  	const u32 dccp_header_size = sizeof(struct dccp_hdr) +
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
382
383
  				     sizeof(struct dccp_hdr_ext) +
  				     sizeof(struct dccp_hdr_response);
802885fc0   Eric Dumazet   dccp: constify dc...
384
385
386
387
388
389
390
391
392
  	struct sk_buff *skb;
  
  	/* sk is marked const to clearly express we dont hold socket lock.
  	 * sock_wmalloc() will atomically change sk->sk_wmem_alloc,
  	 * it is safe to promote sk to non const.
  	 */
  	skb = sock_wmalloc((struct sock *)sk, MAX_DCCP_HEADER, 1,
  			   GFP_ATOMIC);
  	if (!skb)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
393
  		return NULL;
802885fc0   Eric Dumazet   dccp: constify dc...
394
  	skb_reserve(skb, MAX_DCCP_HEADER);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
395

adf30907d   Eric Dumazet   net: skb->dst acc...
396
  	skb_dst_set(skb, dst_clone(dst));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
397

67e6b6292   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
398
  	dreq = dccp_rsk(req);
f541fb7e2   Samuel Jero   dccp: fix bug in ...
399
400
  	if (inet_rsk(req)->acked)	/* increase GSS upon retransmission */
  		dccp_inc_seqno(&dreq->dreq_gss);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
401
  	DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
f541fb7e2   Samuel Jero   dccp: fix bug in ...
402
  	DCCP_SKB_CB(skb)->dccpd_seq  = dreq->dreq_gss;
2d0817d11   Arnaldo Carvalho de Melo   [DCCP] options: M...
403

0c1168398   Gerrit Renker   dccp: Mechanism t...
404
405
406
407
408
409
  	/* Resolve feature dependencies resulting from choice of CCID */
  	if (dccp_feat_server_ccid_dependencies(dreq))
  		goto response_failed;
  
  	if (dccp_insert_options_rsk(dreq, skb))
  		goto response_failed;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
410

09dbc3895   Gerrit Renker   [DCCP]: Miscellan...
411
  	/* Build and checksum header */
9b42078ed   Gerrit Renker   [DCCP]: Combine a...
412
  	dh = dccp_zeroed_hdr(skb, dccp_header_size);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
413

b44084c2c   Eric Dumazet   inet: rename ir_l...
414
  	dh->dccph_sport	= htons(inet_rsk(req)->ir_num);
634fb979e   Eric Dumazet   inet: includes a ...
415
  	dh->dccph_dport	= inet_rsk(req)->ir_rmt_port;
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
416
417
  	dh->dccph_doff	= (dccp_header_size +
  			   DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
418
419
  	dh->dccph_type	= DCCP_PKT_RESPONSE;
  	dh->dccph_x	= 1;
f541fb7e2   Samuel Jero   dccp: fix bug in ...
420
421
  	dccp_hdr_set_seq(dh, dreq->dreq_gss);
  	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_gsr);
67e6b6292   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
422
  	dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
423

6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
424
  	dccp_csum_outgoing(skb);
e11d9d308   Gerrit Renker   [DCCP]: Increment...
425
426
  	/* We use `acked' to remember that a Response was already sent. */
  	inet_rsk(req)->acked = 1;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
427
428
  	DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
  	return skb;
0c1168398   Gerrit Renker   dccp: Mechanism t...
429
430
431
  response_failed:
  	kfree_skb(skb);
  	return NULL;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
432
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
433
  EXPORT_SYMBOL_GPL(dccp_make_response);
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
434
  /* answer offending packet in @rcv_skb with Reset from control socket @ctl */
7630f0268   Denis V. Lunev   [DCCP]: Replace s...
435
  struct sk_buff *dccp_ctl_make_reset(struct sock *sk, struct sk_buff *rcv_skb)
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
436
437
438
439
440
441
442
443
  {
  	struct dccp_hdr *rxdh = dccp_hdr(rcv_skb), *dh;
  	struct dccp_skb_cb *dcb = DCCP_SKB_CB(rcv_skb);
  	const u32 dccp_hdr_reset_len = sizeof(struct dccp_hdr) +
  				       sizeof(struct dccp_hdr_ext) +
  				       sizeof(struct dccp_hdr_reset);
  	struct dccp_hdr_reset *dhr;
  	struct sk_buff *skb;
7630f0268   Denis V. Lunev   [DCCP]: Replace s...
444
  	skb = alloc_skb(sk->sk_prot->max_header, GFP_ATOMIC);
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
445
446
  	if (skb == NULL)
  		return NULL;
7630f0268   Denis V. Lunev   [DCCP]: Replace s...
447
  	skb_reserve(skb, sk->sk_prot->max_header);
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  
  	/* Swap the send and the receive. */
  	dh = dccp_zeroed_hdr(skb, dccp_hdr_reset_len);
  	dh->dccph_type	= DCCP_PKT_RESET;
  	dh->dccph_sport	= rxdh->dccph_dport;
  	dh->dccph_dport	= rxdh->dccph_sport;
  	dh->dccph_doff	= dccp_hdr_reset_len / 4;
  	dh->dccph_x	= 1;
  
  	dhr = dccp_hdr_reset(skb);
  	dhr->dccph_reset_code = dcb->dccpd_reset_code;
  
  	switch (dcb->dccpd_reset_code) {
  	case DCCP_RESET_CODE_PACKET_ERROR:
  		dhr->dccph_reset_data[0] = rxdh->dccph_type;
  		break;
  	case DCCP_RESET_CODE_OPTION_ERROR:	/* fall through */
  	case DCCP_RESET_CODE_MANDATORY_ERROR:
  		memcpy(dhr->dccph_reset_data, dcb->dccpd_reset_data, 3);
  		break;
  	}
  	/*
  	 * From RFC 4340, 8.3.1:
  	 *   If P.ackno exists, set R.seqno := P.ackno + 1.
  	 *   Else set R.seqno := 0.
  	 */
  	if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
  		dccp_hdr_set_seq(dh, ADD48(dcb->dccpd_ack_seq, 1));
  	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dcb->dccpd_seq);
  
  	dccp_csum_outgoing(skb);
  	return skb;
  }
  
  EXPORT_SYMBOL_GPL(dccp_ctl_make_reset);
ee1a15922   Gerrit Renker   [DCCP]: Remove du...
483
  /* send Reset on established socket, to close or abort the connection */
017487d7d   Arnaldo Carvalho de Melo   [DCCP]: Generaliz...
484
485
  int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code)
  {
ee1a15922   Gerrit Renker   [DCCP]: Remove du...
486
  	struct sk_buff *skb;
017487d7d   Arnaldo Carvalho de Melo   [DCCP]: Generaliz...
487
488
489
490
  	/*
  	 * FIXME: what if rebuild_header fails?
  	 * Should we be doing a rebuild_header here?
  	 */
f53dc67c5   Gerrit Renker   [DCCP]: Use AF-in...
491
  	int err = inet_csk(sk)->icsk_af_ops->rebuild_header(sk);
017487d7d   Arnaldo Carvalho de Melo   [DCCP]: Generaliz...
492

ee1a15922   Gerrit Renker   [DCCP]: Remove du...
493
494
495
496
497
498
499
500
501
502
503
  	if (err != 0)
  		return err;
  
  	skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1, GFP_ATOMIC);
  	if (skb == NULL)
  		return -ENOBUFS;
  
  	/* Reserve space for headers and prepare control bits. */
  	skb_reserve(skb, sk->sk_prot->max_header);
  	DCCP_SKB_CB(skb)->dccpd_type	   = DCCP_PKT_RESET;
  	DCCP_SKB_CB(skb)->dccpd_reset_code = code;
017487d7d   Arnaldo Carvalho de Melo   [DCCP]: Generaliz...
504

ee1a15922   Gerrit Renker   [DCCP]: Remove du...
505
  	return dccp_transmit_skb(sk, skb);
017487d7d   Arnaldo Carvalho de Melo   [DCCP]: Generaliz...
506
  }
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
507
508
509
  /*
   * Do all connect socket setups that can be done AF independent.
   */
93344af44   Gerrit Renker   dccp: merge now-r...
510
  int dccp_connect(struct sock *sk)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
511
  {
93344af44   Gerrit Renker   dccp: merge now-r...
512
  	struct sk_buff *skb;
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
513
  	struct dccp_sock *dp = dccp_sk(sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
514
515
516
517
518
  	struct dst_entry *dst = __sk_dst_get(sk);
  	struct inet_connection_sock *icsk = inet_csk(sk);
  
  	sk->sk_err = 0;
  	sock_reset_flag(sk, SOCK_DONE);
c9eaf1734   YOSHIFUJI Hideaki   [NET] DCCP: Fix w...
519

7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
520
  	dccp_sync_mss(sk, dst_mtu(dst));
9eca0a47d   Gerrit Renker   dccp: Resolve dep...
521
522
523
  	/* do not connect if feature negotiation setup fails */
  	if (dccp_feat_finalise_settings(dccp_sk(sk)))
  		return -EPROTO;
93344af44   Gerrit Renker   dccp: merge now-r...
524
525
  	/* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */
  	dp->dccps_gar = dp->dccps_iss;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
526

118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
527
  	skb = alloc_skb(sk->sk_prot->max_header, sk->sk_allocation);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
528
529
530
531
  	if (unlikely(skb == NULL))
  		return -ENOBUFS;
  
  	/* Reserve space for headers. */
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
532
  	skb_reserve(skb, sk->sk_prot->max_header);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
533
534
  
  	DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
535

8695e8019   Gerrit Renker   dccp: combine the...
536
  	dccp_transmit_skb(sk, dccp_skb_entail(sk, skb));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
537
538
539
  	DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
  
  	/* Timer for repeating the REQUEST until an answer. */
93344af44   Gerrit Renker   dccp: merge now-r...
540
  	icsk->icsk_retransmits = 0;
27258ee54   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
541
542
  	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
  				  icsk->icsk_rto, DCCP_RTO_MAX);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
543
544
  	return 0;
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
545
  EXPORT_SYMBOL_GPL(dccp_connect);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
546
547
548
549
  void dccp_send_ack(struct sock *sk)
  {
  	/* If we have been reset, we may not send again. */
  	if (sk->sk_state != DCCP_CLOSED) {
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
550
551
  		struct sk_buff *skb = alloc_skb(sk->sk_prot->max_header,
  						GFP_ATOMIC);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
552
553
554
555
  
  		if (skb == NULL) {
  			inet_csk_schedule_ack(sk);
  			inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN;
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
556
557
558
  			inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
  						  TCP_DELACK_MAX,
  						  DCCP_RTO_MAX);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
559
560
561
562
  			return;
  		}
  
  		/* Reserve space for headers */
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
563
  		skb_reserve(skb, sk->sk_prot->max_header);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
564
  		DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
565
566
567
568
569
  		dccp_transmit_skb(sk, skb);
  	}
  }
  
  EXPORT_SYMBOL_GPL(dccp_send_ack);
1e2f0e5e8   Gerrit Renker   dccp: Fix sparse ...
570
  #if 0
727ecc5fa   Gerrit Renker   [DCCP]: Add FIXME...
571
  /* FIXME: Is this still necessary (11.3) - currently nowhere used by DCCP. */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
  void dccp_send_delayed_ack(struct sock *sk)
  {
  	struct inet_connection_sock *icsk = inet_csk(sk);
  	/*
  	 * FIXME: tune this timer. elapsed time fixes the skew, so no problem
  	 * with using 2s, and active senders also piggyback the ACK into a
  	 * DATAACK packet, so this is really for quiescent senders.
  	 */
  	unsigned long timeout = jiffies + 2 * HZ;
  
  	/* Use new timeout only if there wasn't a older one earlier. */
  	if (icsk->icsk_ack.pending & ICSK_ACK_TIMER) {
  		/* If delack timer was blocked or is about to expire,
  		 * send ACK now.
  		 *
  		 * FIXME: check the "about to expire" part
  		 */
  		if (icsk->icsk_ack.blocked) {
  			dccp_send_ack(sk);
  			return;
  		}
  
  		if (!time_before(timeout, icsk->icsk_ack.timeout))
  			timeout = icsk->icsk_ack.timeout;
  	}
  	icsk->icsk_ack.pending |= ICSK_ACK_SCHED | ICSK_ACK_TIMER;
  	icsk->icsk_ack.timeout = timeout;
  	sk_reset_timer(sk, &icsk->icsk_delack_timer, timeout);
  }
1e2f0e5e8   Gerrit Renker   dccp: Fix sparse ...
601
  #endif
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
602

b0d045ca4   Gerrit Renker   [DCCP]: Parameter...
603
  void dccp_send_sync(struct sock *sk, const u64 ackno,
e92ae93a8   Arnaldo Carvalho de Melo   [DCCP]: Send SYNC...
604
  		    const enum dccp_pkt_type pkt_type)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
605
606
607
608
609
610
  {
  	/*
  	 * We are not putting this on the write queue, so
  	 * dccp_transmit_skb() will set the ownership to this
  	 * sock.
  	 */
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
611
  	struct sk_buff *skb = alloc_skb(sk->sk_prot->max_header, GFP_ATOMIC);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
612

b0d045ca4   Gerrit Renker   [DCCP]: Parameter...
613
  	if (skb == NULL) {
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
614
  		/* FIXME: how to make sure the sync is sent? */
b0d045ca4   Gerrit Renker   [DCCP]: Parameter...
615
  		DCCP_CRIT("could not send %s", dccp_packet_name(pkt_type));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
616
  		return;
b0d045ca4   Gerrit Renker   [DCCP]: Parameter...
617
  	}
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
618
619
  
  	/* Reserve space for headers and prepare control bits. */
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
620
  	skb_reserve(skb, sk->sk_prot->max_header);
e92ae93a8   Arnaldo Carvalho de Melo   [DCCP]: Send SYNC...
621
  	DCCP_SKB_CB(skb)->dccpd_type = pkt_type;
b0d045ca4   Gerrit Renker   [DCCP]: Parameter...
622
  	DCCP_SKB_CB(skb)->dccpd_ack_seq = ackno;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
623

d83447f09   Gerrit Renker   dccp ccid-2: Sche...
624
625
626
627
628
  	/*
  	 * Clear the flag in case the Sync was scheduled for out-of-band data,
  	 * such as carrying a long Ack Vector.
  	 */
  	dccp_sk(sk)->dccps_sync_scheduled = 0;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
629
630
  	dccp_transmit_skb(sk, skb);
  }
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
631
  EXPORT_SYMBOL_GPL(dccp_send_sync);
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
632
633
634
635
  /*
   * Send a DCCP_PKT_CLOSE/CLOSEREQ. The caller locks the socket for us. This
   * cannot be allowed to fail queueing a DCCP_PKT_CLOSE/CLOSEREQ frame under
   * any circumstances.
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
636
   */
7ad07e7cf   Arnaldo Carvalho de Melo   [DCCP]: Implement...
637
  void dccp_send_close(struct sock *sk, const int active)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
638
639
640
  {
  	struct dccp_sock *dp = dccp_sk(sk);
  	struct sk_buff *skb;
7d877f3bd   Al Viro   [PATCH] gfp_t: net/*
641
  	const gfp_t prio = active ? GFP_KERNEL : GFP_ATOMIC;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
642

7ad07e7cf   Arnaldo Carvalho de Melo   [DCCP]: Implement...
643
644
645
  	skb = alloc_skb(sk->sk_prot->max_header, prio);
  	if (skb == NULL)
  		return;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
646
647
648
  
  	/* Reserve space for headers and prepare control bits. */
  	skb_reserve(skb, sk->sk_prot->max_header);
b8599d207   Gerrit Renker   [DCCP]: Support f...
649
650
651
652
  	if (dp->dccps_role == DCCP_ROLE_SERVER && !dp->dccps_server_timewait)
  		DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSEREQ;
  	else
  		DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
653

7ad07e7cf   Arnaldo Carvalho de Melo   [DCCP]: Implement...
654
  	if (active) {
8695e8019   Gerrit Renker   dccp: combine the...
655
  		skb = dccp_skb_entail(sk, skb);
92d31920b   Gerrit Renker   [DCCP]: Shift the...
656
657
658
659
660
661
662
663
664
665
666
667
  		/*
  		 * Retransmission timer for active-close: RFC 4340, 8.3 requires
  		 * to retransmit the Close/CloseReq until the CLOSING/CLOSEREQ
  		 * state can be left. The initial timeout is 2 RTTs.
  		 * Since RTT measurement is done by the CCIDs, there is no easy
  		 * way to get an RTT sample. The fallback RTT from RFC 4340, 3.4
  		 * is too low (200ms); we use a high value to avoid unnecessary
  		 * retransmissions when the link RTT is > 0.2 seconds.
  		 * FIXME: Let main module sample RTTs and use that instead.
  		 */
  		inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
  					  DCCP_TIMEOUT_INIT, DCCP_RTO_MAX);
8695e8019   Gerrit Renker   dccp: combine the...
668
669
  	}
  	dccp_transmit_skb(sk, skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
670
  }