Blame view

net/dccp/output.c 20.2 KB
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
1
2
  /*
   *  net/dccp/output.c
8109b02b5   Arnaldo Carvalho de Melo   [DCCP]: Whitespac...
3
   *
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
4
5
6
7
8
9
10
11
   *  An implementation of the DCCP protocol
   *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
12
  #include <linux/dccp.h>
48918a4db   Herbert Xu   [DCCP]: Simplify ...
13
  #include <linux/kernel.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
14
  #include <linux/skbuff.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/slab.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
16

14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
17
  #include <net/inet_sock.h>
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
18
  #include <net/sock.h>
ae31c3399   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
19
  #include "ackvec.h"
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
20
21
22
23
24
25
26
  #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...
27
28
  /* 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 ...
29
30
31
32
  {
  	skb_set_owner_w(skb, sk);
  	WARN_ON(sk->sk_send_head);
  	sk->sk_send_head = skb;
8695e8019   Gerrit Renker   dccp: combine the...
33
  	return skb_clone(sk->sk_send_head, gfp_any());
48918a4db   Herbert Xu   [DCCP]: Simplify ...
34
  }
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
35
36
37
38
39
40
  /*
   * 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 ...
41
  static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
42
43
  {
  	if (likely(skb != NULL)) {
d9d8da805   David S. Miller   inet: Pass flowi ...
44
  		struct inet_sock *inet = inet_sk(sk);
57cca05af   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
45
  		const struct inet_connection_sock *icsk = inet_csk(sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
46
47
48
49
  		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...
50
  		const u32 dccp_header_size = sizeof(*dh) +
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
51
  					     sizeof(struct dccp_hdr_ext) +
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
52
  					  dccp_packet_hdr_len(dcb->dccpd_type);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
53
54
  		int err, set_ack = 1;
  		u64 ackno = dp->dccps_gsr;
73f18fdbc   Gerrit Renker   dccp: Bug-Fix - A...
55
56
57
58
59
  		/*
  		 * 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...
60

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

afe00251d   Andrea Bittau   [DCCP]: Initial f...
69
70
  		case DCCP_PKT_REQUEST:
  			set_ack = 0;
73f18fdbc   Gerrit Renker   dccp: Bug-Fix - A...
71
72
73
  			/* 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...
74
  			/* fall through */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
75
76
  		case DCCP_PKT_SYNC:
  		case DCCP_PKT_SYNCACK:
b0d045ca4   Gerrit Renker   [DCCP]: Parameter...
77
  			ackno = dcb->dccpd_ack_seq;
edc9e8191   Herbert Xu   [DCCP]: Set socke...
78
79
80
  			/* fall through */
  		default:
  			/*
ee1a15922   Gerrit Renker   [DCCP]: Remove du...
81
82
83
84
  			 * 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...
85
86
87
  			 */
  			WARN_ON(skb->sk);
  			skb_set_owner_w(skb, sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
88
89
  			break;
  		}
24117727b   Arnaldo Carvalho de Melo   [DCCP]: Fix ackno...
90

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

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

7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
97
  		/* Build DCCP header and checksum it. */
9b42078ed   Gerrit Renker   [DCCP]: Combine a...
98
  		dh = dccp_zeroed_hdr(skb, dccp_header_size);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
99
  		dh->dccph_type	= dcb->dccpd_type;
c720c7e83   Eric Dumazet   inet: rename some...
100
101
  		dh->dccph_sport	= inet->inet_sport;
  		dh->dccph_dport	= inet->inet_dport;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
102
103
  		dh->dccph_doff	= (dccp_header_size + dcb->dccpd_opt_len) / 4;
  		dh->dccph_ccval	= dcb->dccpd_ccval;
6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
104
  		dh->dccph_cscov = dp->dccps_pcslen;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
105
106
  		/* XXX For now we're using only 48 bits sequence numbers */
  		dh->dccph_x	= 1;
73f18fdbc   Gerrit Renker   dccp: Bug-Fix - A...
107
  		dccp_update_gss(sk, dcb->dccpd_seq);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
108
109
110
111
112
113
  		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...
114
  			dccp_hdr_request(skb)->dccph_req_service =
67e6b6292   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
115
  							dp->dccps_service;
73f18fdbc   Gerrit Renker   dccp: Bug-Fix - A...
116
117
118
119
120
  			/*
  			 * 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...
121
122
  			break;
  		case DCCP_PKT_RESET:
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
123
124
  			dccp_hdr_reset(skb)->dccph_reset_code =
  							dcb->dccpd_reset_code;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
125
126
  			break;
  		}
bb2962461   Herbert Xu   inet: Remove unus...
127
  		icsk->icsk_af_ops->send_check(sk, skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
128

7ad07e7cf   Arnaldo Carvalho de Melo   [DCCP]: Implement...
129
  		if (set_ack)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
130
131
132
  			dccp_event_ack_sent(sk);
  
  		DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
d9d8da805   David S. Miller   inet: Pass flowi ...
133
  		err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl);
b9df3cb8c   Gerrit Renker   [TCP/DCCP]: Intro...
134
  		return net_xmit_eval(err);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
135
136
137
  	}
  	return -ENOBUFS;
  }
6179983ad   Gerrit Renker   [DCCP]: Introduci...
138
  /**
25985edce   Lucas De Marchi   Fix common misspe...
139
   * dccp_determine_ccmps  -  Find out about CCID-specific packet-size limits
6179983ad   Gerrit Renker   [DCCP]: Introduci...
140
141
142
143
144
145
146
147
148
149
150
151
   * 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...
152
153
  unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
  {
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
154
  	struct inet_connection_sock *icsk = inet_csk(sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
155
  	struct dccp_sock *dp = dccp_sk(sk);
6179983ad   Gerrit Renker   [DCCP]: Introduci...
156
  	u32 ccmps = dccp_determine_ccmps(dp);
361a5c1dd   Gerrit Renker   dccp: Minimise he...
157
  	u32 cur_mps = ccmps ? min(pmtu, ccmps) : pmtu;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
158

6179983ad   Gerrit Renker   [DCCP]: Introduci...
159
160
161
  	/* 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...
162
163
  
  	/*
361a5c1dd   Gerrit Renker   dccp: Minimise he...
164
165
166
167
168
169
170
171
172
173
174
  	 * 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...
175
  	 */
361a5c1dd   Gerrit Renker   dccp: Minimise he...
176
177
  	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...
178
179
  
  	/* And store cached results */
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
180
  	icsk->icsk_pmtu_cookie = pmtu;
6179983ad   Gerrit Renker   [DCCP]: Introduci...
181
  	dp->dccps_mss_cache = cur_mps;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
182

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

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

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

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

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

b1fcf55ee   Gerrit Renker   dccp: Refine the ...
217
218
  	lock_sock(sk);
  	sk->sk_write_pending--;
aa3951451   Eric Dumazet   net: sk_sleep() h...
219
  	finish_wait(sk_sleep(sk), &wait);
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
220
221
222
223
  
  	if (signal_pending(current) || sk->sk_err)
  		return -1;
  	return remaining;
d6809c12b   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
224
  }
dc841e30e   Gerrit Renker   dccp: Extend CCID...
225
226
227
228
229
230
231
232
  /**
   * 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...
233
  	struct sk_buff *skb = dccp_qpolicy_pop(sk);
dc841e30e   Gerrit Renker   dccp: Extend CCID...
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
274
275
  
  	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...
276
277
278
279
280
281
282
283
284
  
  	/*
  	 * 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...
285
  }
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
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
333
334
  /**
   * 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...
335
  {
97e5848dd   Ian McDonald   [DCCP]: Introduce...
336
337
  	struct dccp_sock *dp = dccp_sk(sk);
  	struct sk_buff *skb;
97e5848dd   Ian McDonald   [DCCP]: Introduce...
338

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

dc841e30e   Gerrit Renker   dccp: Extend CCID...
342
343
344
345
  		switch (ccid_packet_dequeue_eval(rc)) {
  		case CCID_PACKET_WILL_DEQUEUE_LATER:
  			return;
  		case CCID_PACKET_DELAY:
b1fcf55ee   Gerrit Renker   dccp: Refine the ...
346
347
348
  			sk_reset_timer(sk, &dp->dccps_xmit_timer,
  				       jiffies + msecs_to_jiffies(rc));
  			return;
dc841e30e   Gerrit Renker   dccp: Extend CCID...
349
350
351
352
  		case CCID_PACKET_SEND_AT_ONCE:
  			dccp_xmit_packet(sk);
  			break;
  		case CCID_PACKET_ERR:
871a2c16c   Tomasz Grobelny   dccp: Policy-base...
353
  			dccp_qpolicy_drop(sk, skb);
dc841e30e   Gerrit Renker   dccp: Extend CCID...
354
355
  			dccp_pr_debug("packet discarded due to err=%d
  ", rc);
f6282f4da   Gerrit Renker   [DCCP]: Warn when...
356
  		}
97e5848dd   Ian McDonald   [DCCP]: Introduce...
357
  	}
27258ee54   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
358
  }
59435444a   Gerrit Renker   dccp: Allow to di...
359
360
361
362
363
364
365
366
367
368
  /**
   * 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...
369
  {
59435444a   Gerrit Renker   dccp: Allow to di...
370
  	WARN_ON(sk->sk_send_head == NULL);
57cca05af   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
371
  	if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
372
  		return -EHOSTUNREACH; /* Routing failure or similar. */
59435444a   Gerrit Renker   dccp: Allow to di...
373
374
375
376
  	/* 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...
377
378
379
380
381
382
  }
  
  struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
  				   struct request_sock *req)
  {
  	struct dccp_hdr *dh;
67e6b6292   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
383
  	struct dccp_request_sock *dreq;
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
384
  	const u32 dccp_header_size = sizeof(struct dccp_hdr) +
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
385
386
  				     sizeof(struct dccp_hdr_ext) +
  				     sizeof(struct dccp_hdr_response);
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
387
  	struct sk_buff *skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1,
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
388
389
390
391
392
  					   GFP_ATOMIC);
  	if (skb == NULL)
  		return NULL;
  
  	/* Reserve space for headers. */
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
393
  	skb_reserve(skb, sk->sk_prot->max_header);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
394

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

67e6b6292   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
397
  	dreq = dccp_rsk(req);
e11d9d308   Gerrit Renker   [DCCP]: Increment...
398
399
  	if (inet_rsk(req)->acked)	/* increase ISS upon retransmission */
  		dccp_inc_seqno(&dreq->dreq_iss);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
400
  	DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
67e6b6292   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
401
  	DCCP_SKB_CB(skb)->dccpd_seq  = dreq->dreq_iss;
2d0817d11   Arnaldo Carvalho de Melo   [DCCP] options: M...
402

0c1168398   Gerrit Renker   dccp: Mechanism t...
403
404
405
406
407
408
  	/* 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...
409

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

944f75022   Gerrit Renker   dccp: Port redire...
413
  	dh->dccph_sport	= inet_rsk(req)->loc_port;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
414
  	dh->dccph_dport	= inet_rsk(req)->rmt_port;
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
415
416
  	dh->dccph_doff	= (dccp_header_size +
  			   DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
417
418
  	dh->dccph_type	= DCCP_PKT_RESPONSE;
  	dh->dccph_x	= 1;
67e6b6292   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
419
420
421
  	dccp_hdr_set_seq(dh, dreq->dreq_iss);
  	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr);
  	dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
422

6f4e5fff1   Gerrit Renker   [DCCP]: Support f...
423
  	dccp_csum_outgoing(skb);
e11d9d308   Gerrit Renker   [DCCP]: Increment...
424
425
  	/* We use `acked' to remember that a Response was already sent. */
  	inet_rsk(req)->acked = 1;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
426
427
  	DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
  	return skb;
0c1168398   Gerrit Renker   dccp: Mechanism t...
428
429
430
  response_failed:
  	kfree_skb(skb);
  	return NULL;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
431
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
432
  EXPORT_SYMBOL_GPL(dccp_make_response);
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
433
  /* answer offending packet in @rcv_skb with Reset from control socket @ctl */
7630f0268   Denis V. Lunev   [DCCP]: Replace s...
434
  struct sk_buff *dccp_ctl_make_reset(struct sock *sk, struct sk_buff *rcv_skb)
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
435
436
437
438
439
440
441
442
  {
  	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...
443
  	skb = alloc_skb(sk->sk_prot->max_header, GFP_ATOMIC);
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
444
445
  	if (skb == NULL)
  		return NULL;
7630f0268   Denis V. Lunev   [DCCP]: Replace s...
446
  	skb_reserve(skb, sk->sk_prot->max_header);
e356d37a0   Gerrit Renker   [DCCP]: Factor ou...
447
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
  
  	/* 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...
482
  /* send Reset on established socket, to close or abort the connection */
017487d7d   Arnaldo Carvalho de Melo   [DCCP]: Generaliz...
483
484
  int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code)
  {
ee1a15922   Gerrit Renker   [DCCP]: Remove du...
485
  	struct sk_buff *skb;
017487d7d   Arnaldo Carvalho de Melo   [DCCP]: Generaliz...
486
487
488
489
  	/*
  	 * FIXME: what if rebuild_header fails?
  	 * Should we be doing a rebuild_header here?
  	 */
f53dc67c5   Gerrit Renker   [DCCP]: Use AF-in...
490
  	int err = inet_csk(sk)->icsk_af_ops->rebuild_header(sk);
017487d7d   Arnaldo Carvalho de Melo   [DCCP]: Generaliz...
491

ee1a15922   Gerrit Renker   [DCCP]: Remove du...
492
493
494
495
496
497
498
499
500
501
502
  	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...
503

ee1a15922   Gerrit Renker   [DCCP]: Remove du...
504
  	return dccp_transmit_skb(sk, skb);
017487d7d   Arnaldo Carvalho de Melo   [DCCP]: Generaliz...
505
  }
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
506
507
508
  /*
   * Do all connect socket setups that can be done AF independent.
   */
93344af44   Gerrit Renker   dccp: merge now-r...
509
  int dccp_connect(struct sock *sk)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
510
  {
93344af44   Gerrit Renker   dccp: merge now-r...
511
  	struct sk_buff *skb;
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
512
  	struct dccp_sock *dp = dccp_sk(sk);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
513
514
515
516
517
  	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...
518

7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
519
  	dccp_sync_mss(sk, dst_mtu(dst));
9eca0a47d   Gerrit Renker   dccp: Resolve dep...
520
521
522
  	/* 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...
523
524
  	/* 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...
525

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

8695e8019   Gerrit Renker   dccp: combine the...
535
  	dccp_transmit_skb(sk, dccp_skb_entail(sk, skb));
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
536
537
538
  	DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
  
  	/* Timer for repeating the REQUEST until an answer. */
93344af44   Gerrit Renker   dccp: merge now-r...
539
  	icsk->icsk_retransmits = 0;
27258ee54   Arnaldo Carvalho de Melo   [DCCP]: Introduce...
540
541
  	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
  				  icsk->icsk_rto, DCCP_RTO_MAX);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
542
543
  	return 0;
  }
f21e68caa   Arnaldo Carvalho de Melo   [DCCP]: Prepare t...
544
  EXPORT_SYMBOL_GPL(dccp_connect);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
545
546
547
548
  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...
549
550
  		struct sk_buff *skb = alloc_skb(sk->sk_prot->max_header,
  						GFP_ATOMIC);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
551
552
553
554
  
  		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...
555
556
557
  			inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
  						  TCP_DELACK_MAX,
  						  DCCP_RTO_MAX);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
558
559
560
561
  			return;
  		}
  
  		/* Reserve space for headers */
118b2c953   Arnaldo Carvalho de Melo   [DCCP]: Use sk->s...
562
  		skb_reserve(skb, sk->sk_prot->max_header);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
563
  		DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
564
565
566
567
568
  		dccp_transmit_skb(sk, skb);
  	}
  }
  
  EXPORT_SYMBOL_GPL(dccp_send_ack);
1e2f0e5e8   Gerrit Renker   dccp: Fix sparse ...
569
  #if 0
727ecc5fa   Gerrit Renker   [DCCP]: Add FIXME...
570
  /* FIXME: Is this still necessary (11.3) - currently nowhere used by DCCP. */
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
571
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
  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 ...
600
  #endif
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
601

b0d045ca4   Gerrit Renker   [DCCP]: Parameter...
602
  void dccp_send_sync(struct sock *sk, const u64 ackno,
e92ae93a8   Arnaldo Carvalho de Melo   [DCCP]: Send SYNC...
603
  		    const enum dccp_pkt_type pkt_type)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
604
605
606
607
608
609
  {
  	/*
  	 * 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...
610
  	struct sk_buff *skb = alloc_skb(sk->sk_prot->max_header, GFP_ATOMIC);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
611

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

d83447f09   Gerrit Renker   dccp ccid-2: Sche...
623
624
625
626
627
  	/*
  	 * 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...
628
629
  	dccp_transmit_skb(sk, skb);
  }
b61fafc4e   Arnaldo Carvalho de Melo   [DCCP]: Move the ...
630
  EXPORT_SYMBOL_GPL(dccp_send_sync);
7690af3ff   Arnaldo Carvalho de Melo   [DCCP]: Just refl...
631
632
633
634
  /*
   * 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...
635
   */
7ad07e7cf   Arnaldo Carvalho de Melo   [DCCP]: Implement...
636
  void dccp_send_close(struct sock *sk, const int active)
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
637
638
639
  {
  	struct dccp_sock *dp = dccp_sk(sk);
  	struct sk_buff *skb;
7d877f3bd   Al Viro   [PATCH] gfp_t: net/*
640
  	const gfp_t prio = active ? GFP_KERNEL : GFP_ATOMIC;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
641

7ad07e7cf   Arnaldo Carvalho de Melo   [DCCP]: Implement...
642
643
644
  	skb = alloc_skb(sk->sk_prot->max_header, prio);
  	if (skb == NULL)
  		return;
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
645
646
647
  
  	/* Reserve space for headers and prepare control bits. */
  	skb_reserve(skb, sk->sk_prot->max_header);
b8599d207   Gerrit Renker   [DCCP]: Support f...
648
649
650
651
  	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...
652

7ad07e7cf   Arnaldo Carvalho de Melo   [DCCP]: Implement...
653
  	if (active) {
8695e8019   Gerrit Renker   dccp: combine the...
654
  		skb = dccp_skb_entail(sk, skb);
92d31920b   Gerrit Renker   [DCCP]: Shift the...
655
656
657
658
659
660
661
662
663
664
665
666
  		/*
  		 * 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...
667
668
  	}
  	dccp_transmit_skb(sk, skb);
7c657876b   Arnaldo Carvalho de Melo   [DCCP]: Initial i...
669
  }