output.c revision 09dbc3895e3242346bd434dae743c456fd28fc6a
17c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo/*
27c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo *  net/dccp/output.c
37c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo *
47c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo *  An implementation of the DCCP protocol
57c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
67c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo *
77c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo *	This program is free software; you can redistribute it and/or
87c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo *	modify it under the terms of the GNU General Public License
97c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo *	as published by the Free Software Foundation; either version
107c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo *	2 of the License, or (at your option) any later version.
117c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo */
127c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
137c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo#include <linux/dccp.h>
1448918a4dbd6c599d6af30bd64cb355fadca708ebHerbert Xu#include <linux/kernel.h>
157c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo#include <linux/skbuff.h>
167c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1714c850212ed8f8cbb5972ad6b8812e08a0bc901cArnaldo Carvalho de Melo#include <net/inet_sock.h>
187c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo#include <net/sock.h>
197c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
20ae31c3399d17b1f7bc1742724f70476b5417744fArnaldo Carvalho de Melo#include "ackvec.h"
217c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo#include "ccid.h"
227c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo#include "dccp.h"
237c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
247c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melostatic inline void dccp_event_ack_sent(struct sock *sk)
257c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
267c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
277c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
287c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
29c25a18ba347f091d1ce620ba33e6772b60a528e1Arnaldo Carvalho de Melostatic void dccp_skb_entail(struct sock *sk, struct sk_buff *skb)
3048918a4dbd6c599d6af30bd64cb355fadca708ebHerbert Xu{
3148918a4dbd6c599d6af30bd64cb355fadca708ebHerbert Xu	skb_set_owner_w(skb, sk);
3248918a4dbd6c599d6af30bd64cb355fadca708ebHerbert Xu	WARN_ON(sk->sk_send_head);
3348918a4dbd6c599d6af30bd64cb355fadca708ebHerbert Xu	sk->sk_send_head = skb;
3448918a4dbd6c599d6af30bd64cb355fadca708ebHerbert Xu}
3548918a4dbd6c599d6af30bd64cb355fadca708ebHerbert Xu
367c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo/*
377c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * All SKB's seen here are completely headerless. It is our
387c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * job to build the DCCP header, and pass the packet down to
397c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * IP so it can do the same plus pass the packet off to the
407c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * device.
417c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo */
4248918a4dbd6c599d6af30bd64cb355fadca708ebHerbert Xustatic int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
437c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
447c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	if (likely(skb != NULL)) {
457c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		const struct inet_sock *inet = inet_sk(sk);
4657cca05af1e20fdc65b55be52c042c234f86c866Arnaldo Carvalho de Melo		const struct inet_connection_sock *icsk = inet_csk(sk);
477c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		struct dccp_sock *dp = dccp_sk(sk);
487c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
497c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		struct dccp_hdr *dh;
507c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		/* XXX For now we're using only 48 bits sequence numbers */
51118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo		const u32 dccp_header_size = sizeof(*dh) +
527c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo					     sizeof(struct dccp_hdr_ext) +
537690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo					  dccp_packet_hdr_len(dcb->dccpd_type);
547c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		int err, set_ack = 1;
557c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		u64 ackno = dp->dccps_gsr;
567c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
577c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		dccp_inc_seqno(&dp->dccps_gss);
587c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
597c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		switch (dcb->dccpd_type) {
607c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		case DCCP_PKT_DATA:
617c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			set_ack = 0;
62edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu			/* fall through */
63edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu		case DCCP_PKT_DATAACK:
647c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			break;
65edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu
66afe00251dd9b53d51de91ff0099961f42bbf3754Andrea Bittau		case DCCP_PKT_REQUEST:
67afe00251dd9b53d51de91ff0099961f42bbf3754Andrea Bittau			set_ack = 0;
68afe00251dd9b53d51de91ff0099961f42bbf3754Andrea Bittau			/* fall through */
69afe00251dd9b53d51de91ff0099961f42bbf3754Andrea Bittau
707c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		case DCCP_PKT_SYNC:
717c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		case DCCP_PKT_SYNCACK:
727c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			ackno = dcb->dccpd_seq;
73edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu			/* fall through */
74edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu		default:
75edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu			/*
76edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu			 * Only data packets should come through with skb->sk
77edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu			 * set.
78edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu			 */
79edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu			WARN_ON(skb->sk);
80edc9e81917157d1e73bf081d4fbcad7c34d32783Herbert Xu			skb_set_owner_w(skb, sk);
817c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			break;
827c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		}
8324117727b753426d85ba09671c24854834f81b2cArnaldo Carvalho de Melo
8424117727b753426d85ba09671c24854834f81b2cArnaldo Carvalho de Melo		dcb->dccpd_seq = dp->dccps_gss;
852d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo
862d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo		if (dccp_insert_options(sk, skb)) {
872d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo			kfree_skb(skb);
882d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo			return -EPROTO;
892d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo		}
907c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
91fda0fd6c5b722cc48e904e0daafedca275d332afHerbert Xu
927c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		/* Build DCCP header and checksum it. */
939b42078ed6edfe04e9dc9a59b946ad912aeef717Gerrit Renker		dh = dccp_zeroed_hdr(skb, dccp_header_size);
947c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		dh->dccph_type	= dcb->dccpd_type;
957c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		dh->dccph_sport	= inet->sport;
967c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		dh->dccph_dport	= inet->dport;
977c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		dh->dccph_doff	= (dccp_header_size + dcb->dccpd_opt_len) / 4;
987c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		dh->dccph_ccval	= dcb->dccpd_ccval;
996f4e5fff1e4d46714ea554fd83e44eab534e8b11Gerrit Renker		dh->dccph_cscov = dp->dccps_pcslen;
1007c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		/* XXX For now we're using only 48 bits sequence numbers */
1017c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		dh->dccph_x	= 1;
1027c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1037c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		dp->dccps_awh = dp->dccps_gss;
1047c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		dccp_hdr_set_seq(dh, dp->dccps_gss);
1057c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		if (set_ack)
1067c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno);
1077c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1087c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		switch (dcb->dccpd_type) {
1097c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		case DCCP_PKT_REQUEST:
1107690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo			dccp_hdr_request(skb)->dccph_req_service =
11167e6b629212fa9ffb7420e8a88a41806af637e28Arnaldo Carvalho de Melo							dp->dccps_service;
1127c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			break;
1137c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		case DCCP_PKT_RESET:
1147690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo			dccp_hdr_reset(skb)->dccph_reset_code =
1157690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo							dcb->dccpd_reset_code;
1167c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			break;
1177c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		}
1187c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1196f4e5fff1e4d46714ea554fd83e44eab534e8b11Gerrit Renker		icsk->icsk_af_ops->send_check(sk, 0, skb);
1207c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1217ad07e7cf343181002c10c39d3f57a88e4903d4fArnaldo Carvalho de Melo		if (set_ack)
1227c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			dccp_event_ack_sent(sk);
1237c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1247c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
1257c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
12649c5bfaffe8ae6e6440dc4bf78b03800960d93f5Herbert Xu		memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
127931731123a103cfb3f70ac4b7abfc71d94ba1f03David S. Miller		err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0);
128b9df3cb8cf9a96e63dfdcd3056a9cbc71f2459e7Gerrit Renker		return net_xmit_eval(err);
1297c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	}
1307c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	return -ENOBUFS;
1317c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
1327c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1337c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melounsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
1347c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
135d83d8461f902c672bc1bd8fbc6a94e19f092da97Arnaldo Carvalho de Melo	struct inet_connection_sock *icsk = inet_csk(sk);
1367c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct dccp_sock *dp = dccp_sk(sk);
137d83d8461f902c672bc1bd8fbc6a94e19f092da97Arnaldo Carvalho de Melo	int mss_now = (pmtu - icsk->icsk_af_ops->net_header_len -
13857cca05af1e20fdc65b55be52c042c234f86c866Arnaldo Carvalho de Melo		       sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext));
1397c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1407c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/* Now subtract optional transport overhead */
141d83d8461f902c672bc1bd8fbc6a94e19f092da97Arnaldo Carvalho de Melo	mss_now -= icsk->icsk_ext_hdr_len;
1427c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1437c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/*
1447c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * FIXME: this should come from the CCID infrastructure, where, say,
1457c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * TFRC will say it wants TIMESTAMPS, ELAPSED time, etc, for now lets
1467c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * put a rough estimate for NDP + TIMESTAMP + TIMESTAMP_ECHO + ELAPSED
1477c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * TIME + TFRC_OPT_LOSS_EVENT_RATE + TFRC_OPT_RECEIVE_RATE + padding to
1487c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * make it a multiple of 4
1497c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 */
1507c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1517c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	mss_now -= ((5 + 6 + 10 + 6 + 6 + 6 + 3) / 4) * 4;
1527c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1537c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/* And store cached results */
154d83d8461f902c672bc1bd8fbc6a94e19f092da97Arnaldo Carvalho de Melo	icsk->icsk_pmtu_cookie = pmtu;
1557c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dp->dccps_mss_cache = mss_now;
1567c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
1577c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	return mss_now;
1587c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
1597c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
160f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de MeloEXPORT_SYMBOL_GPL(dccp_sync_mss);
161f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo
162c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melovoid dccp_write_space(struct sock *sk)
163c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo{
164c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo	read_lock(&sk->sk_callback_lock);
165c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo
166c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
167c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo		wake_up_interruptible(sk->sk_sleep);
168c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo	/* Should agree with poll, otherwise some programs break */
169c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo	if (sock_writeable(sk))
170c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo		sk_wake_async(sk, 2, POLL_OUT);
171c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo
172c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo	read_unlock(&sk->sk_callback_lock);
173c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo}
174c530cfb1ce1e8f230744c3f3bd86771f50725053Arnaldo Carvalho de Melo
175d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo/**
176d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo * dccp_wait_for_ccid - Wait for ccid to tell us we can send a packet
177d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo * @sk: socket to wait for
178d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo * @timeo: for how long
179d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo */
180d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melostatic int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb,
181d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo			      long *timeo)
182d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo{
183d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	struct dccp_sock *dp = dccp_sk(sk);
184d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	DEFINE_WAIT(wait);
185d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	long delay;
186d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	int rc;
187d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo
188d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	while (1) {
189d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
190d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo
19197e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		if (sk->sk_err)
192d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo			goto do_error;
193d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		if (!*timeo)
194d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo			goto do_nonblock;
195d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		if (signal_pending(current))
196d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo			goto do_interrupted;
197d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo
198d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		rc = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb,
199d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo					    skb->len);
200d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		if (rc <= 0)
201d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo			break;
202d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		delay = msecs_to_jiffies(rc);
203d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		if (delay > *timeo || delay < 0)
204d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo			goto do_nonblock;
205d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo
206d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		sk->sk_write_pending++;
207d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		release_sock(sk);
208d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		*timeo -= schedule_timeout(delay);
209d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		lock_sock(sk);
210d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo		sk->sk_write_pending--;
211d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	}
212d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Meloout:
213d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	finish_wait(sk->sk_sleep, &wait);
214d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	return rc;
215d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo
216d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melodo_error:
217d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	rc = -EPIPE;
218d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	goto out;
219d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melodo_nonblock:
220d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	rc = -EAGAIN;
221d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	goto out;
222d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melodo_interrupted:
223d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	rc = sock_intr_errno(*timeo);
224d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo	goto out;
225d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo}
226d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo
22797e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonaldstatic void dccp_write_xmit_timer(unsigned long data) {
22897e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	struct sock *sk = (struct sock *)data;
22997e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	struct dccp_sock *dp = dccp_sk(sk);
23097e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald
23197e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	bh_lock_sock(sk);
23297e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	if (sock_owned_by_user(sk))
23397e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		sk_reset_timer(sk, &dp->dccps_xmit_timer, jiffies+1);
23497e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	else
23597e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		dccp_write_xmit(sk, 0);
23697e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	bh_unlock_sock(sk);
23797e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	sock_put(sk);
23897e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald}
23997e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald
24097e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonaldvoid dccp_write_xmit(struct sock *sk, int block)
24127258ee54f8cd4a43d09319aa5448145afc2cb8dArnaldo Carvalho de Melo{
24297e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	struct dccp_sock *dp = dccp_sk(sk);
24397e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	struct sk_buff *skb;
244f45b3ec481581f24719d8ab0bc812c02fcedc2bcIan McDonald	long timeo = DCCP_XMIT_TIMEO; 	/* If a packet is taking longer than
245f45b3ec481581f24719d8ab0bc812c02fcedc2bcIan McDonald					   this we have other issues */
24697e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald
24797e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	while ((skb = skb_peek(&sk->sk_write_queue))) {
24897e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb,
249d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo					 skb->len);
250d6809c12b3334a929c39bf08ea63bd819e0500f7Arnaldo Carvalho de Melo
25197e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		if (err > 0) {
25297e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			if (!block) {
25397e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				sk_reset_timer(sk, &dp->dccps_xmit_timer,
25497e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald						msecs_to_jiffies(err)+jiffies);
25597e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				break;
256f45b3ec481581f24719d8ab0bc812c02fcedc2bcIan McDonald			} else {
25797e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				err = dccp_wait_for_ccid(sk, skb, &timeo);
258f45b3ec481581f24719d8ab0bc812c02fcedc2bcIan McDonald				timeo = DCCP_XMIT_TIMEO;
259f45b3ec481581f24719d8ab0bc812c02fcedc2bcIan McDonald			}
26097e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			if (err) {
26197e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				printk(KERN_CRIT "%s:err at dccp_wait_for_ccid"
26297e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald						 " %d\n", __FUNCTION__, err);
26397e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				dump_stack();
26497e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			}
26597e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		}
26627258ee54f8cd4a43d09319aa5448145afc2cb8dArnaldo Carvalho de Melo
26797e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		skb_dequeue(&sk->sk_write_queue);
26897e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		if (err == 0) {
26997e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
27097e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			const int len = skb->len;
27127258ee54f8cd4a43d09319aa5448145afc2cb8dArnaldo Carvalho de Melo
27297e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			if (sk->sk_state == DCCP_PARTOPEN) {
27397e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				/* See 8.1.5.  Handshake Completion */
27497e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				inet_csk_schedule_ack(sk);
27597e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
27627258ee54f8cd4a43d09319aa5448145afc2cb8dArnaldo Carvalho de Melo						  inet_csk(sk)->icsk_rto,
27727258ee54f8cd4a43d09319aa5448145afc2cb8dArnaldo Carvalho de Melo						  DCCP_RTO_MAX);
27897e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				dcb->dccpd_type = DCCP_PKT_DATAACK;
27997e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			} else if (dccp_ack_pending(sk))
28097e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				dcb->dccpd_type = DCCP_PKT_DATAACK;
28197e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			else
28297e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				dcb->dccpd_type = DCCP_PKT_DATA;
28397e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald
28497e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			err = dccp_transmit_skb(sk, skb);
28597e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len);
28697e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			if (err) {
28797e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				printk(KERN_CRIT "%s:err from "
28897e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald					         "ccid_hc_tx_packet_sent %d\n",
28997e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald					         __FUNCTION__, err);
29097e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald				dump_stack();
29197e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			}
29297e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		} else
29397e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald			kfree(skb);
29497e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	}
29527258ee54f8cd4a43d09319aa5448145afc2cb8dArnaldo Carvalho de Melo}
29627258ee54f8cd4a43d09319aa5448145afc2cb8dArnaldo Carvalho de Melo
2977c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Meloint dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
2987c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
29957cca05af1e20fdc65b55be52c042c234f86c866Arnaldo Carvalho de Melo	if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)
3007c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		return -EHOSTUNREACH; /* Routing failure or similar. */
3017c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3027c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	return dccp_transmit_skb(sk, (skb_cloned(skb) ?
3037c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo				      pskb_copy(skb, GFP_ATOMIC):
3047c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo				      skb_clone(skb, GFP_ATOMIC)));
3057c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
3067c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3077c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melostruct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
3087c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo				   struct request_sock *req)
3097c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
3107c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct dccp_hdr *dh;
31167e6b629212fa9ffb7420e8a88a41806af637e28Arnaldo Carvalho de Melo	struct dccp_request_sock *dreq;
312118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo	const u32 dccp_header_size = sizeof(struct dccp_hdr) +
3137c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo				     sizeof(struct dccp_hdr_ext) +
3147c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo				     sizeof(struct dccp_hdr_response);
315118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo	struct sk_buff *skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1,
3167c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo					   GFP_ATOMIC);
3177c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	if (skb == NULL)
3187c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		return NULL;
3197c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3207c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/* Reserve space for headers. */
321118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo	skb_reserve(skb, sk->sk_prot->max_header);
3227c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3237c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	skb->dst = dst_clone(dst);
3247c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
32567e6b629212fa9ffb7420e8a88a41806af637e28Arnaldo Carvalho de Melo	dreq = dccp_rsk(req);
326e11d9d30802278af22e78d8c10f348b683670cd9Gerrit Renker	if (inet_rsk(req)->acked)	/* increase ISS upon retransmission */
327e11d9d30802278af22e78d8c10f348b683670cd9Gerrit Renker		dccp_inc_seqno(&dreq->dreq_iss);
3287c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
32967e6b629212fa9ffb7420e8a88a41806af637e28Arnaldo Carvalho de Melo	DCCP_SKB_CB(skb)->dccpd_seq  = dreq->dreq_iss;
3302d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo
3312d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo	if (dccp_insert_options(sk, skb)) {
3322d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo		kfree_skb(skb);
3332d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo		return NULL;
3342d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo	}
3357c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
33609dbc3895e3242346bd434dae743c456fd28fc6aGerrit Renker	/* Build and checksum header */
3379b42078ed6edfe04e9dc9a59b946ad912aeef717Gerrit Renker	dh = dccp_zeroed_hdr(skb, dccp_header_size);
3387c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3397c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dh->dccph_sport	= inet_sk(sk)->sport;
3407c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dh->dccph_dport	= inet_rsk(req)->rmt_port;
3417690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo	dh->dccph_doff	= (dccp_header_size +
3427690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo			   DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
3437c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dh->dccph_type	= DCCP_PKT_RESPONSE;
3447c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dh->dccph_x	= 1;
34567e6b629212fa9ffb7420e8a88a41806af637e28Arnaldo Carvalho de Melo	dccp_hdr_set_seq(dh, dreq->dreq_iss);
34667e6b629212fa9ffb7420e8a88a41806af637e28Arnaldo Carvalho de Melo	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr);
34767e6b629212fa9ffb7420e8a88a41806af637e28Arnaldo Carvalho de Melo	dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service;
3487c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3496f4e5fff1e4d46714ea554fd83e44eab534e8b11Gerrit Renker	dccp_csum_outgoing(skb);
3506f4e5fff1e4d46714ea554fd83e44eab534e8b11Gerrit Renker
351e11d9d30802278af22e78d8c10f348b683670cd9Gerrit Renker	/* We use `acked' to remember that a Response was already sent. */
352e11d9d30802278af22e78d8c10f348b683670cd9Gerrit Renker	inet_rsk(req)->acked = 1;
3537c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
3547c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	return skb;
3557c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
3567c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
357f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de MeloEXPORT_SYMBOL_GPL(dccp_make_response);
358f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo
359017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melostatic struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
360017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo				       const enum dccp_reset_codes code)
3617c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3627c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
3637c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct dccp_hdr *dh;
3647c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct dccp_sock *dp = dccp_sk(sk);
365118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo	const u32 dccp_header_size = sizeof(struct dccp_hdr) +
3667c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo				     sizeof(struct dccp_hdr_ext) +
3677c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo				     sizeof(struct dccp_hdr_reset);
368118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo	struct sk_buff *skb = sock_wmalloc(sk, sk->sk_prot->max_header, 1,
3697c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo					   GFP_ATOMIC);
3707c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	if (skb == NULL)
3717c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		return NULL;
3727c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3737c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/* Reserve space for headers. */
374118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo	skb_reserve(skb, sk->sk_prot->max_header);
3757c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3767c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	skb->dst = dst_clone(dst);
3777c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3787c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dccp_inc_seqno(&dp->dccps_gss);
3797c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3807c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	DCCP_SKB_CB(skb)->dccpd_reset_code = code;
3817c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	DCCP_SKB_CB(skb)->dccpd_type	   = DCCP_PKT_RESET;
3827c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	DCCP_SKB_CB(skb)->dccpd_seq	   = dp->dccps_gss;
3832d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo
3842d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo	if (dccp_insert_options(sk, skb)) {
3852d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo		kfree_skb(skb);
3862d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo		return NULL;
3872d0817d11eaec57435feb61493331a763f732a2bArnaldo Carvalho de Melo	}
3887c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3899b42078ed6edfe04e9dc9a59b946ad912aeef717Gerrit Renker	dh = dccp_zeroed_hdr(skb, dccp_header_size);
3907c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
3917c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dh->dccph_sport	= inet_sk(sk)->sport;
3927c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dh->dccph_dport	= inet_sk(sk)->dport;
3937690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo	dh->dccph_doff	= (dccp_header_size +
3947690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo			   DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
3957c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dh->dccph_type	= DCCP_PKT_RESET;
3967c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dh->dccph_x	= 1;
3977c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dccp_hdr_set_seq(dh, dp->dccps_gss);
3987c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dp->dccps_gsr);
3997c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
4007c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dccp_hdr_reset(skb)->dccph_reset_code = code;
4016f4e5fff1e4d46714ea554fd83e44eab534e8b11Gerrit Renker	inet_csk(sk)->icsk_af_ops->send_check(sk, 0, skb);
4027c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
4037c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
4047c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	return skb;
4057c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
4067c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
407017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Meloint dccp_send_reset(struct sock *sk, enum dccp_reset_codes code)
408017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo{
409017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo	/*
410017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo	 * FIXME: what if rebuild_header fails?
411017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo	 * Should we be doing a rebuild_header here?
412017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo	 */
413017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo	int err = inet_sk_rebuild_header(sk);
414017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo
415017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo	if (err == 0) {
416017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo		struct sk_buff *skb = dccp_make_reset(sk, sk->sk_dst_cache,
417017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo						      code);
418017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo		if (skb != NULL) {
419017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo			memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
420931731123a103cfb3f70ac4b7abfc71d94ba1f03David S. Miller			err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, sk, 0);
421b9df3cb8cf9a96e63dfdcd3056a9cbc71f2459e7Gerrit Renker			return net_xmit_eval(err);
422017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo		}
423017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo	}
424017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo
425017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo	return err;
426017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo}
427017487d7d1e905a5bb529f6a2bc8cf8ea14e2307Arnaldo Carvalho de Melo
4287c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo/*
4297c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo * Do all connect socket setups that can be done AF independent.
4307c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo */
4317c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melostatic inline void dccp_connect_init(struct sock *sk)
4327c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
433f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo	struct dccp_sock *dp = dccp_sk(sk);
4347c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct dst_entry *dst = __sk_dst_get(sk);
4357c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct inet_connection_sock *icsk = inet_csk(sk);
4367c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
4377c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	sk->sk_err = 0;
4387c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	sock_reset_flag(sk, SOCK_DONE);
4397c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
4407c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dccp_sync_mss(sk, dst_mtu(dst));
4417c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
442f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo 	/*
443f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo	 * SWL and AWL are initially adjusted so that they are not less than
444f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo	 * the initial Sequence Numbers received and sent, respectively:
445f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo	 *	SWL := max(GSR + 1 - floor(W/4), ISR),
446f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo	 *	AWL := max(GSS - W' + 1, ISS).
447f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo	 * These adjustments MUST be applied only at the beginning of the
448f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo	 * connection.
449f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo 	 */
450d7f7365f5776723da6df73540d855069c2daaa5cGerrit Renker	dccp_update_gss(sk, dp->dccps_iss);
451f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo	dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
4527c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
453d7f7365f5776723da6df73540d855069c2daaa5cGerrit Renker	/* S.GAR - greatest valid acknowledgement number received on a non-Sync;
454d7f7365f5776723da6df73540d855069c2daaa5cGerrit Renker	 *         initialized to S.ISS (sec. 8.5)                            */
455d7f7365f5776723da6df73540d855069c2daaa5cGerrit Renker	dp->dccps_gar = dp->dccps_iss;
456d7f7365f5776723da6df73540d855069c2daaa5cGerrit Renker
4577c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	icsk->icsk_retransmits = 0;
45897e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	init_timer(&dp->dccps_xmit_timer);
45997e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	dp->dccps_xmit_timer.data = (unsigned long)sk;
46097e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald	dp->dccps_xmit_timer.function = dccp_write_xmit_timer;
4617c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
4627c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
4637c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Meloint dccp_connect(struct sock *sk)
4647c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
4657c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct sk_buff *skb;
4667c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct inet_connection_sock *icsk = inet_csk(sk);
4677c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
4687c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dccp_connect_init(sk);
4697c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
470118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo	skb = alloc_skb(sk->sk_prot->max_header, sk->sk_allocation);
4717c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	if (unlikely(skb == NULL))
4727c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		return -ENOBUFS;
4737c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
4747c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/* Reserve space for headers. */
475118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo	skb_reserve(skb, sk->sk_prot->max_header);
4767c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
4777c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
4787c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
47948918a4dbd6c599d6af30bd64cb355fadca708ebHerbert Xu	dccp_skb_entail(sk, skb);
4807c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));
4817c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
4827c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
4837c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/* Timer for repeating the REQUEST until an answer. */
48427258ee54f8cd4a43d09319aa5448145afc2cb8dArnaldo Carvalho de Melo	inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
48527258ee54f8cd4a43d09319aa5448145afc2cb8dArnaldo Carvalho de Melo				  icsk->icsk_rto, DCCP_RTO_MAX);
4867c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	return 0;
4877c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
4887c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
489f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de MeloEXPORT_SYMBOL_GPL(dccp_connect);
490f21e68caa0ddffddf98a1e729e734a470957b6ecArnaldo Carvalho de Melo
4917c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melovoid dccp_send_ack(struct sock *sk)
4927c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
4937c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/* If we have been reset, we may not send again. */
4947c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	if (sk->sk_state != DCCP_CLOSED) {
495118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo		struct sk_buff *skb = alloc_skb(sk->sk_prot->max_header,
496118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo						GFP_ATOMIC);
4977c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
4987c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		if (skb == NULL) {
4997c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			inet_csk_schedule_ack(sk);
5007c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN;
5017690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo			inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
5027690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo						  TCP_DELACK_MAX,
5037690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo						  DCCP_RTO_MAX);
5047c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			return;
5057c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		}
5067c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5077c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		/* Reserve space for headers */
508118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo		skb_reserve(skb, sk->sk_prot->max_header);
5097c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_ACK;
5107c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		dccp_transmit_skb(sk, skb);
5117c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	}
5127c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
5137c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5147c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de MeloEXPORT_SYMBOL_GPL(dccp_send_ack);
5157c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5167c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melovoid dccp_send_delayed_ack(struct sock *sk)
5177c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
5187c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct inet_connection_sock *icsk = inet_csk(sk);
5197c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/*
5207c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * FIXME: tune this timer. elapsed time fixes the skew, so no problem
5217c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * with using 2s, and active senders also piggyback the ACK into a
5227c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * DATAACK packet, so this is really for quiescent senders.
5237c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 */
5247c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	unsigned long timeout = jiffies + 2 * HZ;
5257c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5267c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/* Use new timeout only if there wasn't a older one earlier. */
5277c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	if (icsk->icsk_ack.pending & ICSK_ACK_TIMER) {
5287c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		/* If delack timer was blocked or is about to expire,
5297c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		 * send ACK now.
5307c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		 *
5317c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		 * FIXME: check the "about to expire" part
5327c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		 */
5337c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		if (icsk->icsk_ack.blocked) {
5347c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			dccp_send_ack(sk);
5357c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			return;
5367c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		}
5377c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5387c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		if (!time_before(timeout, icsk->icsk_ack.timeout))
5397c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo			timeout = icsk->icsk_ack.timeout;
5407c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	}
5417c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	icsk->icsk_ack.pending |= ICSK_ACK_SCHED | ICSK_ACK_TIMER;
5427c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	icsk->icsk_ack.timeout = timeout;
5437c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	sk_reset_timer(sk, &icsk->icsk_delack_timer, timeout);
5447c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
5457c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
546e92ae93a8aa66aea12935420cb22d4df1c18d023Arnaldo Carvalho de Melovoid dccp_send_sync(struct sock *sk, const u64 seq,
547e92ae93a8aa66aea12935420cb22d4df1c18d023Arnaldo Carvalho de Melo		    const enum dccp_pkt_type pkt_type)
5487c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
5497c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/*
5507c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * We are not putting this on the write queue, so
5517c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * dccp_transmit_skb() will set the ownership to this
5527c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 * sock.
5537c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	 */
554118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo	struct sk_buff *skb = alloc_skb(sk->sk_prot->max_header, GFP_ATOMIC);
5557c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5567c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	if (skb == NULL)
5577c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		/* FIXME: how to make sure the sync is sent? */
5587c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo		return;
5597c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5607c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/* Reserve space for headers and prepare control bits. */
561118b2c9532c853ebdf15c21128d30a343b89ea45Arnaldo Carvalho de Melo	skb_reserve(skb, sk->sk_prot->max_header);
562e92ae93a8aa66aea12935420cb22d4df1c18d023Arnaldo Carvalho de Melo	DCCP_SKB_CB(skb)->dccpd_type = pkt_type;
5637c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	DCCP_SKB_CB(skb)->dccpd_seq = seq;
5647c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5657c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	dccp_transmit_skb(sk, skb);
5667c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
5677c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
568b61fafc4ef3faf54236d57e3b230ca19167663bfArnaldo Carvalho de MeloEXPORT_SYMBOL_GPL(dccp_send_sync);
569b61fafc4ef3faf54236d57e3b230ca19167663bfArnaldo Carvalho de Melo
5707690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo/*
5717690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo * Send a DCCP_PKT_CLOSE/CLOSEREQ. The caller locks the socket for us. This
5727690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo * cannot be allowed to fail queueing a DCCP_PKT_CLOSE/CLOSEREQ frame under
5737690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo * any circumstances.
5747c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo */
5757ad07e7cf343181002c10c39d3f57a88e4903d4fArnaldo Carvalho de Melovoid dccp_send_close(struct sock *sk, const int active)
5767c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo{
5777c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct dccp_sock *dp = dccp_sk(sk);
5787c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	struct sk_buff *skb;
5797d877f3bda870ab5f001bd92528654471d5966b3Al Viro	const gfp_t prio = active ? GFP_KERNEL : GFP_ATOMIC;
5807c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5817ad07e7cf343181002c10c39d3f57a88e4903d4fArnaldo Carvalho de Melo	skb = alloc_skb(sk->sk_prot->max_header, prio);
5827ad07e7cf343181002c10c39d3f57a88e4903d4fArnaldo Carvalho de Melo	if (skb == NULL)
5837ad07e7cf343181002c10c39d3f57a88e4903d4fArnaldo Carvalho de Melo		return;
5847c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5857c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	/* Reserve space for headers and prepare control bits. */
5867c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo	skb_reserve(skb, sk->sk_prot->max_header);
5877690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo	DCCP_SKB_CB(skb)->dccpd_type = dp->dccps_role == DCCP_ROLE_CLIENT ?
5887690af3fff7633e40b1b9950eb8489129251d074Arnaldo Carvalho de Melo					DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ;
5897c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo
5907ad07e7cf343181002c10c39d3f57a88e4903d4fArnaldo Carvalho de Melo	if (active) {
59197e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		dccp_write_xmit(sk, 1);
59248918a4dbd6c599d6af30bd64cb355fadca708ebHerbert Xu		dccp_skb_entail(sk, skb);
5937ad07e7cf343181002c10c39d3f57a88e4903d4fArnaldo Carvalho de Melo		dccp_transmit_skb(sk, skb_clone(skb, prio));
59497e5848dd39e7e76bd6077735ebb5473763ab9c5Ian McDonald		/* FIXME do we need a retransmit timer here? */
5957ad07e7cf343181002c10c39d3f57a88e4903d4fArnaldo Carvalho de Melo	} else
5967ad07e7cf343181002c10c39d3f57a88e4903d4fArnaldo Carvalho de Melo		dccp_transmit_skb(sk, skb);
5977c657876b63cb1d8a2ec06f8fc6c37bb8412e66cArnaldo Carvalho de Melo}
598