1/* SCTP kernel reference Implementation
2 * (C) Copyright IBM Corp. 2003, 2004
3 *
4 * This file is part of the SCTP kernel reference Implementation
5 *
6 * This file contains the code relating the chunk abstraction.
7 *
8 * The SCTP reference implementation is free software;
9 * you can redistribute it and/or modify it under the terms of
10 * the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * The SCTP reference implementation is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 *                 ************************
17 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 * See the GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with GNU CC; see the file COPYING.  If not, write to
22 * the Free Software Foundation, 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
24 *
25 * Please send any bug reports or fixes you make to the
26 * email address(es):
27 *    lksctp developers <lksctp-developers@lists.sourceforge.net>
28 *
29 * Or submit a bug report through the following website:
30 *    http://www.sf.net/projects/lksctp
31 *
32 * Written or modified by:
33 *    Jon Grimm             <jgrimm@us.ibm.com>
34 *    Sridhar Samudrala     <sri@us.ibm.com>
35 *
36 * Any bugs reported given to us we will try to fix... any fixes shared will
37 * be incorporated into the next SCTP release.
38 */
39
40#include <linux/types.h>
41#include <linux/kernel.h>
42#include <linux/net.h>
43#include <linux/inet.h>
44#include <linux/skbuff.h>
45#include <net/sock.h>
46#include <net/sctp/sctp.h>
47#include <net/sctp/sm.h>
48
49/* This file is mostly in anticipation of future work, but initially
50 * populate with fragment tracking for an outbound message.
51 */
52
53/* Initialize datamsg from memory. */
54static void sctp_datamsg_init(struct sctp_datamsg *msg)
55{
56	atomic_set(&msg->refcnt, 1);
57	msg->send_failed = 0;
58	msg->send_error = 0;
59	msg->can_abandon = 0;
60	msg->expires_at = 0;
61	INIT_LIST_HEAD(&msg->chunks);
62}
63
64/* Allocate and initialize datamsg. */
65SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp)
66{
67	struct sctp_datamsg *msg;
68	msg = kmalloc(sizeof(struct sctp_datamsg), gfp);
69	if (msg)
70		sctp_datamsg_init(msg);
71	SCTP_DBG_OBJCNT_INC(datamsg);
72	return msg;
73}
74
75/* Final destructruction of datamsg memory. */
76static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
77{
78	struct list_head *pos, *temp;
79	struct sctp_chunk *chunk;
80	struct sctp_sock *sp;
81	struct sctp_ulpevent *ev;
82	struct sctp_association *asoc = NULL;
83	int error = 0, notify;
84
85	/* If we failed, we may need to notify. */
86	notify = msg->send_failed ? -1 : 0;
87
88	/* Release all references. */
89	list_for_each_safe(pos, temp, &msg->chunks) {
90		list_del_init(pos);
91		chunk = list_entry(pos, struct sctp_chunk, frag_list);
92		/* Check whether we _really_ need to notify. */
93		if (notify < 0) {
94			asoc = chunk->asoc;
95			if (msg->send_error)
96				error = msg->send_error;
97			else
98				error = asoc->outqueue.error;
99
100			sp = sctp_sk(asoc->base.sk);
101			notify = sctp_ulpevent_type_enabled(SCTP_SEND_FAILED,
102							    &sp->subscribe);
103		}
104
105		/* Generate a SEND FAILED event only if enabled. */
106		if (notify > 0) {
107			int sent;
108			if (chunk->has_tsn)
109				sent = SCTP_DATA_SENT;
110			else
111				sent = SCTP_DATA_UNSENT;
112
113			ev = sctp_ulpevent_make_send_failed(asoc, chunk, sent,
114							    error, GFP_ATOMIC);
115			if (ev)
116				sctp_ulpq_tail_event(&asoc->ulpq, ev);
117		}
118
119		sctp_chunk_put(chunk);
120	}
121
122	SCTP_DBG_OBJCNT_DEC(datamsg);
123	kfree(msg);
124}
125
126/* Hold a reference. */
127static void sctp_datamsg_hold(struct sctp_datamsg *msg)
128{
129	atomic_inc(&msg->refcnt);
130}
131
132/* Release a reference. */
133void sctp_datamsg_put(struct sctp_datamsg *msg)
134{
135	if (atomic_dec_and_test(&msg->refcnt))
136		sctp_datamsg_destroy(msg);
137}
138
139/* Free a message.  Really just give up a reference, the
140 * really free happens in sctp_datamsg_destroy().
141 */
142void sctp_datamsg_free(struct sctp_datamsg *msg)
143{
144	sctp_datamsg_put(msg);
145}
146
147/* Hold on to all the fragments until all chunks have been sent. */
148void sctp_datamsg_track(struct sctp_chunk *chunk)
149{
150	sctp_chunk_hold(chunk);
151}
152
153/* Assign a chunk to this datamsg. */
154static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk)
155{
156	sctp_datamsg_hold(msg);
157	chunk->msg = msg;
158}
159
160
161/* A data chunk can have a maximum payload of (2^16 - 20).  Break
162 * down any such message into smaller chunks.  Opportunistically, fragment
163 * the chunks down to the current MTU constraints.  We may get refragmented
164 * later if the PMTU changes, but it is _much better_ to fragment immediately
165 * with a reasonable guess than always doing our fragmentation on the
166 * soft-interrupt.
167 */
168struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
169					    struct sctp_sndrcvinfo *sinfo,
170					    struct msghdr *msgh, int msg_len)
171{
172	int max, whole, i, offset, over, err;
173	int len, first_len;
174	struct sctp_chunk *chunk;
175	struct sctp_datamsg *msg;
176	struct list_head *pos, *temp;
177	__u8 frag;
178
179	msg = sctp_datamsg_new(GFP_KERNEL);
180	if (!msg)
181		return NULL;
182
183	/* Note: Calculate this outside of the loop, so that all fragments
184	 * have the same expiration.
185	 */
186	if (sinfo->sinfo_timetolive) {
187		/* sinfo_timetolive is in milliseconds */
188		msg->expires_at = jiffies +
189				    msecs_to_jiffies(sinfo->sinfo_timetolive);
190		msg->can_abandon = 1;
191		SCTP_DEBUG_PRINTK("%s: msg:%p expires_at: %ld jiffies:%ld\n",
192				  __FUNCTION__, msg, msg->expires_at, jiffies);
193	}
194
195	max = asoc->frag_point;
196
197	whole = 0;
198	first_len = max;
199
200	/* Encourage Cookie-ECHO bundling. */
201	if (asoc->state < SCTP_STATE_COOKIE_ECHOED) {
202		whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN);
203
204		/* Account for the DATA to be bundled with the COOKIE-ECHO. */
205		if (whole) {
206			first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN;
207			msg_len -= first_len;
208			whole = 1;
209		}
210	}
211
212	/* How many full sized?  How many bytes leftover? */
213	whole += msg_len / max;
214	over = msg_len % max;
215	offset = 0;
216
217	if ((whole > 1) || (whole && over))
218		SCTP_INC_STATS_USER(SCTP_MIB_FRAGUSRMSGS);
219
220	/* Create chunks for all the full sized DATA chunks. */
221	for (i=0, len=first_len; i < whole; i++) {
222		frag = SCTP_DATA_MIDDLE_FRAG;
223
224		if (0 == i)
225			frag |= SCTP_DATA_FIRST_FRAG;
226
227		if ((i == (whole - 1)) && !over)
228			frag |= SCTP_DATA_LAST_FRAG;
229
230		chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
231
232		if (!chunk)
233			goto errout;
234		err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov);
235		if (err < 0)
236			goto errout;
237
238		offset += len;
239
240		/* Put the chunk->skb back into the form expected by send.  */
241		__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
242			   - (__u8 *)chunk->skb->data);
243
244		sctp_datamsg_assign(msg, chunk);
245		list_add_tail(&chunk->frag_list, &msg->chunks);
246
247		/* The first chunk, the first chunk was likely short
248		 * to allow bundling, so reset to full size.
249		 */
250		if (0 == i)
251			len = max;
252	}
253
254	/* .. now the leftover bytes. */
255	if (over) {
256		if (!whole)
257			frag = SCTP_DATA_NOT_FRAG;
258		else
259			frag = SCTP_DATA_LAST_FRAG;
260
261		chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
262
263		if (!chunk)
264			goto errout;
265
266		err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov);
267
268		/* Put the chunk->skb back into the form expected by send.  */
269		__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
270			   - (__u8 *)chunk->skb->data);
271		if (err < 0)
272			goto errout;
273
274		sctp_datamsg_assign(msg, chunk);
275		list_add_tail(&chunk->frag_list, &msg->chunks);
276	}
277
278	return msg;
279
280errout:
281	list_for_each_safe(pos, temp, &msg->chunks) {
282		list_del_init(pos);
283		chunk = list_entry(pos, struct sctp_chunk, frag_list);
284		sctp_chunk_free(chunk);
285	}
286	sctp_datamsg_free(msg);
287	return NULL;
288}
289
290/* Check whether this message has expired. */
291int sctp_chunk_abandoned(struct sctp_chunk *chunk)
292{
293	struct sctp_datamsg *msg = chunk->msg;
294
295	if (!msg->can_abandon)
296		return 0;
297
298	if (time_after(jiffies, msg->expires_at))
299		return 1;
300
301	return 0;
302}
303
304/* This chunk (and consequently entire message) has failed in its sending. */
305void sctp_chunk_fail(struct sctp_chunk *chunk, int error)
306{
307	chunk->msg->send_failed = 1;
308	chunk->msg->send_error = error;
309}
310