aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/output.c')
-rw-r--r--net/dccp/output.c78
1 files changed, 19 insertions, 59 deletions
diff --git a/net/dccp/output.c b/net/dccp/output.c
index d0c9ec6494bf..f4bde2056204 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -61,6 +61,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
61 set_ack = 0; 61 set_ack = 0;
62 /* fall through */ 62 /* fall through */
63 case DCCP_PKT_DATAACK: 63 case DCCP_PKT_DATAACK:
64 case DCCP_PKT_RESET:
64 break; 65 break;
65 66
66 case DCCP_PKT_REQUEST: 67 case DCCP_PKT_REQUEST:
@@ -73,8 +74,10 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
73 /* fall through */ 74 /* fall through */
74 default: 75 default:
75 /* 76 /*
76 * Only data packets should come through with skb->sk 77 * Set owner/destructor: some skbs are allocated via
77 * set. 78 * alloc_skb (e.g. when retransmission may happen).
79 * Only Data, DataAck, and Reset packets should come
80 * through here with skb->sk set.
78 */ 81 */
79 WARN_ON(skb->sk); 82 WARN_ON(skb->sk);
80 skb_set_owner_w(skb, sk); 83 skb_set_owner_w(skb, sk);
@@ -324,72 +327,29 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
324 327
325EXPORT_SYMBOL_GPL(dccp_make_response); 328EXPORT_SYMBOL_GPL(dccp_make_response);
326 329
327static struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst, 330/* send Reset on established socket, to close or abort the connection */
328 const enum dccp_reset_codes code)
329{
330 struct dccp_hdr *dh;
331 struct dccp_sock *dp = dccp_sk(sk);
332 const u32 dccp_header_size = sizeof(struct dccp_hdr) +
333 sizeof(struct dccp_hdr_ext) +
334 sizeof(struct dccp_hdr_reset);
335 struct sk_buff *skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1,
336 GFP_ATOMIC);
337 if (skb == NULL)
338 return NULL;
339
340 /* Reserve space for headers. */
341 skb_reserve(skb, sk->sk_prot->max_header);
342
343 skb->dst = dst_clone(dst);
344
345 dccp_inc_seqno(&dp->dccps_gss);
346
347 DCCP_SKB_CB(skb)->dccpd_reset_code = code;
348 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESET;
349 DCCP_SKB_CB(skb)->dccpd_seq = dp->dccps_gss;
350
351 if (dccp_insert_options(sk, skb)) {
352 kfree_skb(skb);
353 return NULL;
354 }
355
356 dh = dccp_zeroed_hdr(skb, dccp_header_size);
357
358 dh->dccph_sport = inet_sk(sk)->sport;
359 dh->dccph_dport = inet_sk(sk)->dport;
360 dh->dccph_doff = (dccp_header_size +
361 DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
362 dh->dccph_type = DCCP_PKT_RESET;
363 dh->dccph_x = 1;
364 dccp_hdr_set_seq(dh, dp->dccps_gss);
365 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dp->dccps_gsr);
366
367 dccp_hdr_reset(skb)->dccph_reset_code = code;
368 inet_csk(sk)->icsk_af_ops->send_check(sk, 0, skb);
369
370 DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
371 return skb;
372}
373
374int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code) 331int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code)
375{ 332{
333 struct sk_buff *skb;
376 /* 334 /*
377 * FIXME: what if rebuild_header fails? 335 * FIXME: what if rebuild_header fails?
378 * Should we be doing a rebuild_header here? 336 * Should we be doing a rebuild_header here?
379 */ 337 */
380 int err = inet_sk_rebuild_header(sk); 338 int err = inet_sk_rebuild_header(sk);
381 339
382 if (err == 0) { 340 if (err != 0)
383 struct sk_buff *skb = dccp_make_reset(sk, sk->sk_dst_cache, 341 return err;
384 code); 342
385 if (skb != NULL) { 343 skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1, GFP_ATOMIC);
386 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 344 if (skb == NULL)
387 err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, 0); 345 return -ENOBUFS;
388 return net_xmit_eval(err); 346
389 } 347 /* Reserve space for headers and prepare control bits. */
390 } 348 skb_reserve(skb, sk->sk_prot->max_header);
349 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESET;
350 DCCP_SKB_CB(skb)->dccpd_reset_code = code;
391 351
392 return err; 352 return dccp_transmit_skb(sk, skb);
393} 353}
394 354
395/* 355/*