Blame view

net/tipc/msg.c 20.6 KB
b97bf3fd8   Per Liden   [TIPC] Initial merge
1
2
  /*
   * net/tipc/msg.c: TIPC message header routines
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
3
   *
cf2157f88   Jon Paul Maloy   tipc: move messag...
4
   * Copyright (c) 2000-2006, 2014-2015, Ericsson AB
741de3e9f   Allan Stephens   tipc: Remove supp...
5
   * Copyright (c) 2005, 2010-2011, Wind River Systems
b97bf3fd8   Per Liden   [TIPC] Initial merge
6
7
   * All rights reserved.
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
8
   * Redistribution and use in source and binary forms, with or without
b97bf3fd8   Per Liden   [TIPC] Initial merge
9
10
   * modification, are permitted provided that the following conditions are met:
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
11
12
13
14
15
16
17
18
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. Neither the names of the copyright holders nor the names of its
   *    contributors may be used to endorse or promote products derived from
   *    this software without specific prior written permission.
b97bf3fd8   Per Liden   [TIPC] Initial merge
19
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL") version 2 as published by the Free
   * Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
b97bf3fd8   Per Liden   [TIPC] Initial merge
34
35
   * POSSIBILITY OF SUCH DAMAGE.
   */
c93d3baa2   Ying Xue   tipc: involve nam...
36
  #include <net/sock.h>
b97bf3fd8   Per Liden   [TIPC] Initial merge
37
  #include "core.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
38
  #include "msg.h"
5a379074a   Jon Paul Maloy   tipc: introduce m...
39
40
  #include "addr.h"
  #include "name_table.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
41

8db1bae30   Jon Paul Maloy   tipc: separate bu...
42
  #define MAX_FORWARD_SIZE 1024
27777daa8   Jon Paul Maloy   tipc: unclone unb...
43
44
  #define BUF_HEADROOM (LL_MAX_HEADER + 48)
  #define BUF_TAILROOM 16
8db1bae30   Jon Paul Maloy   tipc: separate bu...
45

4f1688b2c   Jon Paul Maloy   tipc: introduce s...
46
  static unsigned int align(unsigned int i)
23461e835   Allan Stephens   tipc: Reduce foot...
47
  {
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
48
  	return (i + 3) & ~3u;
23461e835   Allan Stephens   tipc: Reduce foot...
49
  }
859fc7c0c   Ying Xue   tipc: cleanup cor...
50
51
52
53
54
55
56
57
58
  /**
   * tipc_buf_acquire - creates a TIPC message buffer
   * @size: message size (including TIPC header)
   *
   * Returns a new buffer with data pointers set to the specified size.
   *
   * NOTE: Headroom is reserved to allow prepending of a data link header.
   *       There may also be unrequested tailroom present at the buffer's end.
   */
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
59
  struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp)
859fc7c0c   Ying Xue   tipc: cleanup cor...
60
61
62
  {
  	struct sk_buff *skb;
  	unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
63
  	skb = alloc_skb_fclone(buf_size, gfp);
859fc7c0c   Ying Xue   tipc: cleanup cor...
64
65
66
67
68
69
70
  	if (skb) {
  		skb_reserve(skb, BUF_HEADROOM);
  		skb_put(skb, size);
  		skb->next = NULL;
  	}
  	return skb;
  }
c5898636c   Jon Paul Maloy   tipc: reduce usag...
71
72
  void tipc_msg_init(u32 own_node, struct tipc_msg *m, u32 user, u32 type,
  		   u32 hsize, u32 dnode)
23461e835   Allan Stephens   tipc: Reduce foot...
73
74
75
76
77
78
  {
  	memset(m, 0, hsize);
  	msg_set_version(m);
  	msg_set_user(m, user);
  	msg_set_hdr_sz(m, hsize);
  	msg_set_size(m, hsize);
c5898636c   Jon Paul Maloy   tipc: reduce usag...
79
  	msg_set_prevnode(m, own_node);
23461e835   Allan Stephens   tipc: Reduce foot...
80
  	msg_set_type(m, type);
1dd0bd2b1   Jon Paul Maloy   tipc: introduce n...
81
  	if (hsize > SHORT_H_SIZE) {
c5898636c   Jon Paul Maloy   tipc: reduce usag...
82
83
  		msg_set_orignode(m, own_node);
  		msg_set_destnode(m, dnode);
1dd0bd2b1   Jon Paul Maloy   tipc: introduce n...
84
85
  	}
  }
c5898636c   Jon Paul Maloy   tipc: reduce usag...
86
  struct sk_buff *tipc_msg_create(uint user, uint type,
347475395   Ying Xue   tipc: make tipc n...
87
88
  				uint hdr_sz, uint data_sz, u32 dnode,
  				u32 onode, u32 dport, u32 oport, int errcode)
1dd0bd2b1   Jon Paul Maloy   tipc: introduce n...
89
90
91
  {
  	struct tipc_msg *msg;
  	struct sk_buff *buf;
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
92
  	buf = tipc_buf_acquire(hdr_sz + data_sz, GFP_ATOMIC);
1dd0bd2b1   Jon Paul Maloy   tipc: introduce n...
93
94
95
96
  	if (unlikely(!buf))
  		return NULL;
  
  	msg = buf_msg(buf);
c5898636c   Jon Paul Maloy   tipc: reduce usag...
97
  	tipc_msg_init(onode, msg, user, type, hdr_sz, dnode);
1dd0bd2b1   Jon Paul Maloy   tipc: introduce n...
98
  	msg_set_size(msg, hdr_sz + data_sz);
1dd0bd2b1   Jon Paul Maloy   tipc: introduce n...
99
100
101
102
103
104
105
106
  	msg_set_origport(msg, oport);
  	msg_set_destport(msg, dport);
  	msg_set_errcode(msg, errcode);
  	if (hdr_sz > SHORT_H_SIZE) {
  		msg_set_orignode(msg, onode);
  		msg_set_destnode(msg, dnode);
  	}
  	return buf;
23461e835   Allan Stephens   tipc: Reduce foot...
107
  }
37e22164a   Jon Paul Maloy   tipc: rename and ...
108
  /* tipc_buf_append(): Append a buffer to the fragment list of another buffer
29322d0db   Jon Paul Maloy   tipc: fix bug in ...
109
110
111
   * @*headbuf: in:  NULL for first frag, otherwise value returned from prev call
   *            out: set when successful non-complete reassembly, otherwise NULL
   * @*buf:     in:  the buffer to append. Always defined
b2ad5e5fc   stephen hemminger   tipc: spelling er...
112
   *            out: head buf after successful complete reassembly, otherwise NULL
29322d0db   Jon Paul Maloy   tipc: fix bug in ...
113
   * Returns 1 when reassembly complete, otherwise 0
37e22164a   Jon Paul Maloy   tipc: rename and ...
114
115
116
117
118
   */
  int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
  {
  	struct sk_buff *head = *headbuf;
  	struct sk_buff *frag = *buf;
45c8b7b17   Jon Paul Maloy   tipc: allow non-l...
119
  	struct sk_buff *tail = NULL;
13e9b9972   Jon Paul Maloy   tipc: make tipc_b...
120
121
  	struct tipc_msg *msg;
  	u32 fragid;
37e22164a   Jon Paul Maloy   tipc: rename and ...
122
  	int delta;
13e9b9972   Jon Paul Maloy   tipc: make tipc_b...
123
  	bool headstolen;
37e22164a   Jon Paul Maloy   tipc: rename and ...
124

13e9b9972   Jon Paul Maloy   tipc: make tipc_b...
125
126
127
128
129
130
  	if (!frag)
  		goto err;
  
  	msg = buf_msg(frag);
  	fragid = msg_type(msg);
  	frag->next = NULL;
37e22164a   Jon Paul Maloy   tipc: rename and ...
131
132
133
  	skb_pull(frag, msg_hdr_sz(msg));
  
  	if (fragid == FIRST_FRAGMENT) {
13e9b9972   Jon Paul Maloy   tipc: make tipc_b...
134
135
136
137
  		if (unlikely(head))
  			goto err;
  		if (unlikely(skb_unclone(frag, GFP_ATOMIC)))
  			goto err;
37e22164a   Jon Paul Maloy   tipc: rename and ...
138
  		head = *headbuf = frag;
29322d0db   Jon Paul Maloy   tipc: fix bug in ...
139
  		*buf = NULL;
45c8b7b17   Jon Paul Maloy   tipc: allow non-l...
140
141
142
143
144
145
146
147
  		TIPC_SKB_CB(head)->tail = NULL;
  		if (skb_is_nonlinear(head)) {
  			skb_walk_frags(head, tail) {
  				TIPC_SKB_CB(head)->tail = tail;
  			}
  		} else {
  			skb_frag_list_init(head);
  		}
37e22164a   Jon Paul Maloy   tipc: rename and ...
148
149
  		return 0;
  	}
13e9b9972   Jon Paul Maloy   tipc: make tipc_b...
150

37e22164a   Jon Paul Maloy   tipc: rename and ...
151
  	if (!head)
13e9b9972   Jon Paul Maloy   tipc: make tipc_b...
152
  		goto err;
37e22164a   Jon Paul Maloy   tipc: rename and ...
153
154
155
  	if (skb_try_coalesce(head, frag, &headstolen, &delta)) {
  		kfree_skb_partial(frag, headstolen);
  	} else {
13e9b9972   Jon Paul Maloy   tipc: make tipc_b...
156
  		tail = TIPC_SKB_CB(head)->tail;
37e22164a   Jon Paul Maloy   tipc: rename and ...
157
158
159
160
161
162
163
164
165
  		if (!skb_has_frag_list(head))
  			skb_shinfo(head)->frag_list = frag;
  		else
  			tail->next = frag;
  		head->truesize += frag->truesize;
  		head->data_len += frag->len;
  		head->len += frag->len;
  		TIPC_SKB_CB(head)->tail = frag;
  	}
13e9b9972   Jon Paul Maloy   tipc: make tipc_b...
166

37e22164a   Jon Paul Maloy   tipc: rename and ...
167
  	if (fragid == LAST_FRAGMENT) {
1149557d6   Jon Paul Maloy   tipc: eliminate u...
168
  		TIPC_SKB_CB(head)->validated = false;
d618d09a6   Jon Maloy   tipc: enforce val...
169
  		if (unlikely(!tipc_msg_validate(&head)))
1149557d6   Jon Paul Maloy   tipc: eliminate u...
170
  			goto err;
37e22164a   Jon Paul Maloy   tipc: rename and ...
171
172
173
174
175
176
177
  		*buf = head;
  		TIPC_SKB_CB(head)->tail = NULL;
  		*headbuf = NULL;
  		return 1;
  	}
  	*buf = NULL;
  	return 0;
13e9b9972   Jon Paul Maloy   tipc: make tipc_b...
178
  err:
37e22164a   Jon Paul Maloy   tipc: rename and ...
179
  	kfree_skb(*buf);
29322d0db   Jon Paul Maloy   tipc: fix bug in ...
180
181
  	kfree_skb(*headbuf);
  	*buf = *headbuf = NULL;
37e22164a   Jon Paul Maloy   tipc: rename and ...
182
183
  	return 0;
  }
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
184

cf2157f88   Jon Paul Maloy   tipc: move messag...
185
186
187
188
189
190
191
192
193
194
195
  /* tipc_msg_validate - validate basic format of received message
   *
   * This routine ensures a TIPC message has an acceptable header, and at least
   * as much data as the header indicates it should.  The routine also ensures
   * that the entire message header is stored in the main fragment of the message
   * buffer, to simplify future access to message header fields.
   *
   * Note: Having extra info present in the message header or data areas is OK.
   * TIPC will ignore the excess, under the assumption that it is optional info
   * introduced by a later release of the protocol.
   */
d618d09a6   Jon Maloy   tipc: enforce val...
196
  bool tipc_msg_validate(struct sk_buff **_skb)
cf2157f88   Jon Paul Maloy   tipc: move messag...
197
  {
d618d09a6   Jon Maloy   tipc: enforce val...
198
199
  	struct sk_buff *skb = *_skb;
  	struct tipc_msg *hdr;
cf2157f88   Jon Paul Maloy   tipc: move messag...
200
  	int msz, hsz;
d618d09a6   Jon Maloy   tipc: enforce val...
201
  	/* Ensure that flow control ratio condition is satisfied */
55b3280d1   Hoang Le   tipc: fix skb tru...
202
203
  	if (unlikely(skb->truesize / buf_roundup_len(skb) >= 4)) {
  		skb = skb_copy_expand(skb, BUF_HEADROOM, 0, GFP_ATOMIC);
d618d09a6   Jon Maloy   tipc: enforce val...
204
205
206
207
208
  		if (!skb)
  			return false;
  		kfree_skb(*_skb);
  		*_skb = skb;
  	}
cf2157f88   Jon Paul Maloy   tipc: move messag...
209
210
211
212
213
214
215
216
217
218
  	if (unlikely(TIPC_SKB_CB(skb)->validated))
  		return true;
  	if (unlikely(!pskb_may_pull(skb, MIN_H_SIZE)))
  		return false;
  
  	hsz = msg_hdr_sz(buf_msg(skb));
  	if (unlikely(hsz < MIN_H_SIZE) || (hsz > MAX_H_SIZE))
  		return false;
  	if (unlikely(!pskb_may_pull(skb, hsz)))
  		return false;
d618d09a6   Jon Maloy   tipc: enforce val...
219
220
  	hdr = buf_msg(skb);
  	if (unlikely(msg_version(hdr) != TIPC_VERSION))
cf2157f88   Jon Paul Maloy   tipc: move messag...
221
  		return false;
d618d09a6   Jon Maloy   tipc: enforce val...
222
  	msz = msg_size(hdr);
cf2157f88   Jon Paul Maloy   tipc: move messag...
223
224
225
226
227
228
229
230
231
232
  	if (unlikely(msz < hsz))
  		return false;
  	if (unlikely((msz - hsz) > TIPC_MAX_USER_MSG_SIZE))
  		return false;
  	if (unlikely(skb->len < msz))
  		return false;
  
  	TIPC_SKB_CB(skb)->validated = true;
  	return true;
  }
067608e9d   Jon Paul Maloy   tipc: introduce d...
233
234
  
  /**
2320bcdae   Tuong Lien   tipc: fix changeo...
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
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
   * tipc_msg_fragment - build a fragment skb list for TIPC message
   *
   * @skb: TIPC message skb
   * @hdr: internal msg header to be put on the top of the fragments
   * @pktmax: max size of a fragment incl. the header
   * @frags: returned fragment skb list
   *
   * Returns 0 if the fragmentation is successful, otherwise: -EINVAL
   * or -ENOMEM
   */
  int tipc_msg_fragment(struct sk_buff *skb, const struct tipc_msg *hdr,
  		      int pktmax, struct sk_buff_head *frags)
  {
  	int pktno, nof_fragms, dsz, dmax, eat;
  	struct tipc_msg *_hdr;
  	struct sk_buff *_skb;
  	u8 *data;
  
  	/* Non-linear buffer? */
  	if (skb_linearize(skb))
  		return -ENOMEM;
  
  	data = (u8 *)skb->data;
  	dsz = msg_size(buf_msg(skb));
  	dmax = pktmax - INT_H_SIZE;
  	if (dsz <= dmax || !dmax)
  		return -EINVAL;
  
  	nof_fragms = dsz / dmax + 1;
  	for (pktno = 1; pktno <= nof_fragms; pktno++) {
  		if (pktno < nof_fragms)
  			eat = dmax;
  		else
  			eat = dsz % dmax;
  		/* Allocate a new fragment */
  		_skb = tipc_buf_acquire(INT_H_SIZE + eat, GFP_ATOMIC);
  		if (!_skb)
  			goto error;
  		skb_orphan(_skb);
  		__skb_queue_tail(frags, _skb);
  		/* Copy header & data to the fragment */
  		skb_copy_to_linear_data(_skb, hdr, INT_H_SIZE);
  		skb_copy_to_linear_data_offset(_skb, INT_H_SIZE, data, eat);
  		data += eat;
  		/* Update the fragment's header */
  		_hdr = buf_msg(_skb);
  		msg_set_fragm_no(_hdr, pktno);
  		msg_set_nof_fragms(_hdr, nof_fragms);
  		msg_set_size(_hdr, INT_H_SIZE + eat);
  	}
  	return 0;
  
  error:
  	__skb_queue_purge(frags);
  	__skb_queue_head_init(frags);
  	return -ENOMEM;
  }
  
  /**
9fbfb8b12   Jon Paul Maloy   tipc: rename temp...
294
   * tipc_msg_build - create buffer chain containing specified header and data
067608e9d   Jon Paul Maloy   tipc: introduce d...
295
   * @mhdr: Message header, to be prepended to data
45dcc687f   Al Viro   tipc_msg_build():...
296
   * @m: User message
067608e9d   Jon Paul Maloy   tipc: introduce d...
297
298
   * @dsz: Total length of user data
   * @pktmax: Max packet size that can be used
a6ca10944   Ying Xue   tipc: use generic...
299
300
   * @list: Buffer or chain of buffers to be returned to caller
   *
4c94cc2d3   Jon Maloy   tipc: fall back t...
301
302
303
   * Note that the recursive call we are making here is safe, since it can
   * logically go only one further level down.
   *
067608e9d   Jon Paul Maloy   tipc: introduce d...
304
305
   * Returns message data size or errno: -ENOMEM, -EFAULT
   */
4c94cc2d3   Jon Maloy   tipc: fall back t...
306
307
  int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
  		   int dsz, int pktmax, struct sk_buff_head *list)
067608e9d   Jon Paul Maloy   tipc: introduce d...
308
309
  {
  	int mhsz = msg_hdr_sz(mhdr);
4c94cc2d3   Jon Maloy   tipc: fall back t...
310
  	struct tipc_msg pkthdr;
067608e9d   Jon Paul Maloy   tipc: introduce d...
311
  	int msz = mhsz + dsz;
067608e9d   Jon Paul Maloy   tipc: introduce d...
312
  	int pktrem = pktmax;
a6ca10944   Ying Xue   tipc: use generic...
313
  	struct sk_buff *skb;
4c94cc2d3   Jon Maloy   tipc: fall back t...
314
315
  	int drem = dsz;
  	int pktno = 1;
067608e9d   Jon Paul Maloy   tipc: introduce d...
316
  	char *pktpos;
4c94cc2d3   Jon Maloy   tipc: fall back t...
317
  	int pktsz;
067608e9d   Jon Paul Maloy   tipc: introduce d...
318
  	int rc;
a6ca10944   Ying Xue   tipc: use generic...
319

067608e9d   Jon Paul Maloy   tipc: introduce d...
320
321
322
323
  	msg_set_size(mhdr, msz);
  
  	/* No fragmentation needed? */
  	if (likely(msz <= pktmax)) {
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
324
  		skb = tipc_buf_acquire(msz, GFP_KERNEL);
4c94cc2d3   Jon Maloy   tipc: fall back t...
325
326
327
328
329
330
331
332
333
334
  
  		/* Fall back to smaller MTU if node local message */
  		if (unlikely(!skb)) {
  			if (pktmax != MAX_MSG_SIZE)
  				return -ENOMEM;
  			rc = tipc_msg_build(mhdr, m, offset, dsz, FB_MTU, list);
  			if (rc != dsz)
  				return rc;
  			if (tipc_msg_assemble(list))
  				return dsz;
067608e9d   Jon Paul Maloy   tipc: introduce d...
335
  			return -ENOMEM;
4c94cc2d3   Jon Maloy   tipc: fall back t...
336
  		}
c93d3baa2   Ying Xue   tipc: involve nam...
337
  		skb_orphan(skb);
a6ca10944   Ying Xue   tipc: use generic...
338
339
340
  		__skb_queue_tail(list, skb);
  		skb_copy_to_linear_data(skb, mhdr, mhsz);
  		pktpos = skb->data + mhsz;
cbbd26b8b   Al Viro   [iov_iter] new pr...
341
  		if (copy_from_iter_full(pktpos, dsz, &m->msg_iter))
067608e9d   Jon Paul Maloy   tipc: introduce d...
342
343
344
345
346
347
  			return dsz;
  		rc = -EFAULT;
  		goto error;
  	}
  
  	/* Prepare reusable fragment header */
c5898636c   Jon Paul Maloy   tipc: reduce usag...
348
349
  	tipc_msg_init(msg_prevnode(mhdr), &pkthdr, MSG_FRAGMENTER,
  		      FIRST_FRAGMENT, INT_H_SIZE, msg_destnode(mhdr));
067608e9d   Jon Paul Maloy   tipc: introduce d...
350
351
  	msg_set_size(&pkthdr, pktmax);
  	msg_set_fragm_no(&pkthdr, pktno);
e3eea1eb4   Jon Paul Maloy   tipc: clean up ha...
352
  	msg_set_importance(&pkthdr, msg_importance(mhdr));
067608e9d   Jon Paul Maloy   tipc: introduce d...
353
354
  
  	/* Prepare first fragment */
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
355
  	skb = tipc_buf_acquire(pktmax, GFP_KERNEL);
a6ca10944   Ying Xue   tipc: use generic...
356
  	if (!skb)
067608e9d   Jon Paul Maloy   tipc: introduce d...
357
  		return -ENOMEM;
c93d3baa2   Ying Xue   tipc: involve nam...
358
  	skb_orphan(skb);
a6ca10944   Ying Xue   tipc: use generic...
359
360
361
  	__skb_queue_tail(list, skb);
  	pktpos = skb->data;
  	skb_copy_to_linear_data(skb, &pkthdr, INT_H_SIZE);
067608e9d   Jon Paul Maloy   tipc: introduce d...
362
363
  	pktpos += INT_H_SIZE;
  	pktrem -= INT_H_SIZE;
a6ca10944   Ying Xue   tipc: use generic...
364
  	skb_copy_to_linear_data_offset(skb, INT_H_SIZE, mhdr, mhsz);
067608e9d   Jon Paul Maloy   tipc: introduce d...
365
366
367
368
369
370
  	pktpos += mhsz;
  	pktrem -= mhsz;
  
  	do {
  		if (drem < pktrem)
  			pktrem = drem;
cbbd26b8b   Al Viro   [iov_iter] new pr...
371
  		if (!copy_from_iter_full(pktpos, pktrem, &m->msg_iter)) {
067608e9d   Jon Paul Maloy   tipc: introduce d...
372
373
374
375
  			rc = -EFAULT;
  			goto error;
  		}
  		drem -= pktrem;
067608e9d   Jon Paul Maloy   tipc: introduce d...
376
377
378
379
380
381
382
383
384
  
  		if (!drem)
  			break;
  
  		/* Prepare new fragment: */
  		if (drem < (pktmax - INT_H_SIZE))
  			pktsz = drem + INT_H_SIZE;
  		else
  			pktsz = pktmax;
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
385
  		skb = tipc_buf_acquire(pktsz, GFP_KERNEL);
a6ca10944   Ying Xue   tipc: use generic...
386
  		if (!skb) {
067608e9d   Jon Paul Maloy   tipc: introduce d...
387
388
389
  			rc = -ENOMEM;
  			goto error;
  		}
c93d3baa2   Ying Xue   tipc: involve nam...
390
  		skb_orphan(skb);
a6ca10944   Ying Xue   tipc: use generic...
391
  		__skb_queue_tail(list, skb);
067608e9d   Jon Paul Maloy   tipc: introduce d...
392
393
394
  		msg_set_type(&pkthdr, FRAGMENT);
  		msg_set_size(&pkthdr, pktsz);
  		msg_set_fragm_no(&pkthdr, ++pktno);
a6ca10944   Ying Xue   tipc: use generic...
395
396
  		skb_copy_to_linear_data(skb, &pkthdr, INT_H_SIZE);
  		pktpos = skb->data + INT_H_SIZE;
067608e9d   Jon Paul Maloy   tipc: introduce d...
397
398
399
  		pktrem = pktsz - INT_H_SIZE;
  
  	} while (1);
a6ca10944   Ying Xue   tipc: use generic...
400
  	msg_set_type(buf_msg(skb), LAST_FRAGMENT);
067608e9d   Jon Paul Maloy   tipc: introduce d...
401
402
  	return dsz;
  error:
a6ca10944   Ying Xue   tipc: use generic...
403
404
  	__skb_queue_purge(list);
  	__skb_queue_head_init(list);
067608e9d   Jon Paul Maloy   tipc: introduce d...
405
406
  	return rc;
  }
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
407
408
  /**
   * tipc_msg_bundle(): Append contents of a buffer to tail of an existing one
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
409
410
   * @skb: the buffer to append to ("bundle")
   * @msg:  message to be appended
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
411
412
413
414
   * @mtu:  max allowable size for the bundle buffer
   * Consumes buffer if successful
   * Returns true if bundling could be performed, otherwise false
   */
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
415
  bool tipc_msg_bundle(struct sk_buff *skb, struct tipc_msg *msg, u32 mtu)
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
416
  {
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
417
  	struct tipc_msg *bmsg;
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
418
  	unsigned int bsz;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
419
  	unsigned int msz = msg_size(msg);
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
420
  	u32 start, pad;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
421
  	u32 max = mtu - INT_H_SIZE;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
422
423
424
  
  	if (likely(msg_user(msg) == MSG_FRAGMENTER))
  		return false;
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
425
  	if (!skb)
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
426
  		return false;
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
427
  	bmsg = buf_msg(skb);
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
428
429
430
  	bsz = msg_size(bmsg);
  	start = align(bsz);
  	pad = start - bsz;
dff29b1a8   Jon Paul Maloy   tipc: eliminate d...
431
  	if (unlikely(msg_user(msg) == TUNNEL_PROTOCOL))
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
432
433
434
  		return false;
  	if (unlikely(msg_user(msg) == BCAST_PROTOCOL))
  		return false;
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
435
  	if (unlikely(msg_user(bmsg) != MSG_BUNDLER))
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
436
  		return false;
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
437
  	if (unlikely(skb_tailroom(skb) < (pad + msz)))
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
438
439
440
  		return false;
  	if (unlikely(max < (start + msz)))
  		return false;
f21e897ec   Jon Paul Maloy   tipc: improve lin...
441
442
443
  	if ((msg_importance(msg) < TIPC_SYSTEM_IMPORTANCE) &&
  	    (msg_importance(bmsg) == TIPC_SYSTEM_IMPORTANCE))
  		return false;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
444

dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
445
446
  	skb_put(skb, pad + msz);
  	skb_copy_to_linear_data_offset(skb, start, msg, msz);
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
447
448
  	msg_set_size(bmsg, start + msz);
  	msg_set_msgcnt(bmsg, msg_msgcnt(bmsg) + 1);
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
449
450
451
452
  	return true;
  }
  
  /**
c637c1035   Jon Paul Maloy   tipc: resolve rac...
453
   *  tipc_msg_extract(): extract bundled inner packet from buffer
c1336ee47   Jon Paul Maloy   tipc: extract bun...
454
   *  @skb: buffer to be extracted from.
c637c1035   Jon Paul Maloy   tipc: resolve rac...
455
   *  @iskb: extracted inner buffer, to be returned
c1336ee47   Jon Paul Maloy   tipc: extract bun...
456
457
   *  @pos: position in outer message of msg to be extracted.
   *        Returns position of next msg
c637c1035   Jon Paul Maloy   tipc: resolve rac...
458
459
460
461
462
   *  Consumes outer buffer when last packet extracted
   *  Returns true when when there is an extracted buffer, otherwise false
   */
  bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos)
  {
ef9be7556   Tung Nguyen   tipc: eliminate b...
463
464
  	struct tipc_msg *hdr, *ihdr;
  	int imsz;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
465

c1336ee47   Jon Paul Maloy   tipc: extract bun...
466
  	*iskb = NULL;
1149557d6   Jon Paul Maloy   tipc: eliminate u...
467
  	if (unlikely(skb_linearize(skb)))
c1336ee47   Jon Paul Maloy   tipc: extract bun...
468
  		goto none;
ef9be7556   Tung Nguyen   tipc: eliminate b...
469
470
  	hdr = buf_msg(skb);
  	if (unlikely(*pos > (msg_data_sz(hdr) - MIN_H_SIZE)))
c637c1035   Jon Paul Maloy   tipc: resolve rac...
471
  		goto none;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
472

ef9be7556   Tung Nguyen   tipc: eliminate b...
473
474
475
476
  	ihdr = (struct tipc_msg *)(msg_data(hdr) + *pos);
  	imsz = msg_size(ihdr);
  
  	if ((*pos + imsz) > msg_data_sz(hdr))
c637c1035   Jon Paul Maloy   tipc: resolve rac...
477
  		goto none;
ef9be7556   Tung Nguyen   tipc: eliminate b...
478
479
480
481
482
483
  
  	*iskb = tipc_buf_acquire(imsz, GFP_ATOMIC);
  	if (!*iskb)
  		goto none;
  
  	skb_copy_to_linear_data(*iskb, ihdr, imsz);
d618d09a6   Jon Maloy   tipc: enforce val...
484
  	if (unlikely(!tipc_msg_validate(iskb)))
c637c1035   Jon Paul Maloy   tipc: resolve rac...
485
  		goto none;
ef9be7556   Tung Nguyen   tipc: eliminate b...
486

c637c1035   Jon Paul Maloy   tipc: resolve rac...
487
488
489
490
  	*pos += align(imsz);
  	return true;
  none:
  	kfree_skb(skb);
c1336ee47   Jon Paul Maloy   tipc: extract bun...
491
  	kfree_skb(*iskb);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
492
493
494
495
496
  	*iskb = NULL;
  	return false;
  }
  
  /**
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
497
   * tipc_msg_make_bundle(): Create bundle buf and append message to its tail
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
498
499
500
   * @list: the buffer chain, where head is the buffer to replace/append
   * @skb: buffer to be created, appended to and returned in case of success
   * @msg: message to be appended
58dc55f25   Ying Xue   tipc: use generic...
501
   * @mtu: max allowable size for the bundle buffer, inclusive header
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
502
   * @dnode: destination node for message. (Not always present in header)
b2ad5e5fc   stephen hemminger   tipc: spelling er...
503
   * Returns true if success, otherwise false
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
504
   */
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
505
506
  bool tipc_msg_make_bundle(struct sk_buff **skb,  struct tipc_msg *msg,
  			  u32 mtu, u32 dnode)
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
507
  {
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
508
  	struct sk_buff *_skb;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
509
  	struct tipc_msg *bmsg;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
510
511
512
513
514
  	u32 msz = msg_size(msg);
  	u32 max = mtu - INT_H_SIZE;
  
  	if (msg_user(msg) == MSG_FRAGMENTER)
  		return false;
dff29b1a8   Jon Paul Maloy   tipc: eliminate d...
515
  	if (msg_user(msg) == TUNNEL_PROTOCOL)
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
516
517
518
519
520
  		return false;
  	if (msg_user(msg) == BCAST_PROTOCOL)
  		return false;
  	if (msz > (max / 2))
  		return false;
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
521
  	_skb = tipc_buf_acquire(max, GFP_ATOMIC);
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
522
  	if (!_skb)
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
523
  		return false;
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
524
525
  	skb_trim(_skb, INT_H_SIZE);
  	bmsg = buf_msg(_skb);
c5898636c   Jon Paul Maloy   tipc: reduce usag...
526
527
  	tipc_msg_init(msg_prevnode(msg), bmsg, MSG_BUNDLER, 0,
  		      INT_H_SIZE, dnode);
e95584a88   Tuong Lien   tipc: fix unlimit...
528
  	msg_set_importance(bmsg, msg_importance(msg));
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
529
530
531
  	msg_set_seqno(bmsg, msg_seqno(msg));
  	msg_set_ack(bmsg, msg_ack(msg));
  	msg_set_bcast_ack(bmsg, msg_bcast_ack(msg));
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
532
533
  	tipc_msg_bundle(_skb, msg, mtu);
  	*skb = _skb;
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
534
  	return true;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
535
  }
8db1bae30   Jon Paul Maloy   tipc: separate bu...
536
537
538
  
  /**
   * tipc_msg_reverse(): swap source and destination addresses and add error code
29042e19f   Jon Paul Maloy   tipc: let functio...
539
   * @own_node: originating node id for reversed message
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
540
   * @skb:  buffer containing message to be reversed; will be consumed
29042e19f   Jon Paul Maloy   tipc: let functio...
541
   * @err:  error code to be set in message, if any
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
542
   * Replaces consumed buffer with new one when successful
8db1bae30   Jon Paul Maloy   tipc: separate bu...
543
544
   * Returns true if success, otherwise false
   */
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
545
  bool tipc_msg_reverse(u32 own_node,  struct sk_buff **skb, int err)
8db1bae30   Jon Paul Maloy   tipc: separate bu...
546
  {
29042e19f   Jon Paul Maloy   tipc: let functio...
547
  	struct sk_buff *_skb = *skb;
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
548
549
  	struct tipc_msg *_hdr, *hdr;
  	int hlen, dlen;
8db1bae30   Jon Paul Maloy   tipc: separate bu...
550

29042e19f   Jon Paul Maloy   tipc: let functio...
551
  	if (skb_linearize(_skb))
8db1bae30   Jon Paul Maloy   tipc: separate bu...
552
  		goto exit;
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
553
554
555
556
557
  	_hdr = buf_msg(_skb);
  	dlen = min_t(uint, msg_data_sz(_hdr), MAX_FORWARD_SIZE);
  	hlen = msg_hdr_sz(_hdr);
  
  	if (msg_dest_droppable(_hdr))
ac0074ee7   Jon Paul Maloy   tipc: clean up co...
558
  		goto exit;
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
559
  	if (msg_errcode(_hdr))
8db1bae30   Jon Paul Maloy   tipc: separate bu...
560
  		goto exit;
29042e19f   Jon Paul Maloy   tipc: let functio...
561

5cbdbd1a1   Jon Maloy   tipc: refactor fu...
562
563
564
  	/* Never return SHORT header */
  	if (hlen == SHORT_H_SIZE)
  		hlen = BASIC_H_SIZE;
29042e19f   Jon Paul Maloy   tipc: let functio...
565

678792747   Tung Nguyen   tipc: buffer over...
566
567
568
  	/* Don't return data along with SYN+, - sender has a clone */
  	if (msg_is_syn(_hdr) && err == TIPC_ERR_OVERLOAD)
  		dlen = 0;
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
569
570
571
572
573
574
575
576
577
578
  	/* Allocate new buffer to return */
  	*skb = tipc_buf_acquire(hlen + dlen, GFP_ATOMIC);
  	if (!*skb)
  		goto exit;
  	memcpy((*skb)->data, _skb->data, msg_hdr_sz(_hdr));
  	memcpy((*skb)->data + hlen, msg_data(_hdr), dlen);
  
  	/* Build reverse header in new buffer */
  	hdr = buf_msg(*skb);
  	msg_set_hdr_sz(hdr, hlen);
29042e19f   Jon Paul Maloy   tipc: let functio...
579
  	msg_set_errcode(hdr, err);
59a361bc6   Jon Paul Maloy   tipc: avoid inher...
580
  	msg_set_non_seq(hdr, 0);
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
581
582
583
  	msg_set_origport(hdr, msg_destport(_hdr));
  	msg_set_destport(hdr, msg_origport(_hdr));
  	msg_set_destnode(hdr, msg_prevnode(_hdr));
29042e19f   Jon Paul Maloy   tipc: let functio...
584
585
  	msg_set_prevnode(hdr, own_node);
  	msg_set_orignode(hdr, own_node);
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
586
  	msg_set_size(hdr, hlen + dlen);
29042e19f   Jon Paul Maloy   tipc: let functio...
587
  	skb_orphan(_skb);
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
588
  	kfree_skb(_skb);
8db1bae30   Jon Paul Maloy   tipc: separate bu...
589
590
  	return true;
  exit:
29042e19f   Jon Paul Maloy   tipc: let functio...
591
592
  	kfree_skb(_skb);
  	*skb = NULL;
8db1bae30   Jon Paul Maloy   tipc: separate bu...
593
594
  	return false;
  }
5a379074a   Jon Paul Maloy   tipc: introduce m...
595

678792747   Tung Nguyen   tipc: buffer over...
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
  bool tipc_msg_skb_clone(struct sk_buff_head *msg, struct sk_buff_head *cpy)
  {
  	struct sk_buff *skb, *_skb;
  
  	skb_queue_walk(msg, skb) {
  		_skb = skb_clone(skb, GFP_ATOMIC);
  		if (!_skb) {
  			__skb_queue_purge(cpy);
  			pr_err_ratelimited("Failed to clone buffer chain
  ");
  			return false;
  		}
  		__skb_queue_tail(cpy, _skb);
  	}
  	return true;
  }
5a379074a   Jon Paul Maloy   tipc: introduce m...
612
  /**
e3a77561e   Jon Paul Maloy   tipc: split up fu...
613
614
   * tipc_msg_lookup_dest(): try to find new destination for named message
   * @skb: the buffer containing the message.
cda3696d3   Jon Paul Maloy   tipc: clean up so...
615
   * @err: error code to be used by caller if lookup fails
5a379074a   Jon Paul Maloy   tipc: introduce m...
616
   * Does not consume buffer
e3a77561e   Jon Paul Maloy   tipc: split up fu...
617
   * Returns true if a destination is found, false otherwise
5a379074a   Jon Paul Maloy   tipc: introduce m...
618
   */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
619
  bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
5a379074a   Jon Paul Maloy   tipc: introduce m...
620
  {
e3a77561e   Jon Paul Maloy   tipc: split up fu...
621
  	struct tipc_msg *msg = buf_msg(skb);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
622
623
  	u32 dport, dnode;
  	u32 onode = tipc_own_addr(net);
5a379074a   Jon Paul Maloy   tipc: introduce m...
624

e3a77561e   Jon Paul Maloy   tipc: split up fu...
625
626
627
628
  	if (!msg_isdata(msg))
  		return false;
  	if (!msg_named(msg))
  		return false;
d482994fc   Jon Paul Maloy   tipc: fix two bug...
629
630
  	if (msg_errcode(msg))
  		return false;
aad06212d   Parthasarathy Bhuvaragan   tipc: use only po...
631
  	*err = TIPC_ERR_NO_NAME;
e3a77561e   Jon Paul Maloy   tipc: split up fu...
632
633
  	if (skb_linearize(skb))
  		return false;
4e3ae0010   Erik Hugne   tipc: reinitializ...
634
  	msg = buf_msg(skb);
d482994fc   Jon Paul Maloy   tipc: fix two bug...
635
  	if (msg_reroute_cnt(msg))
e3a77561e   Jon Paul Maloy   tipc: split up fu...
636
  		return false;
928df1880   Jon Maloy   tipc: obsolete TI...
637
  	dnode = tipc_scope2node(net, msg_lookup_scope(msg));
4ac1c8d0e   Ying Xue   tipc: name tipc n...
638
  	dport = tipc_nametbl_translate(net, msg_nametype(msg),
cda3696d3   Jon Paul Maloy   tipc: clean up so...
639
  				       msg_nameinst(msg), &dnode);
5a379074a   Jon Paul Maloy   tipc: introduce m...
640
  	if (!dport)
e3a77561e   Jon Paul Maloy   tipc: split up fu...
641
  		return false;
5a379074a   Jon Paul Maloy   tipc: introduce m...
642
  	msg_incr_reroute_cnt(msg);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
643
644
645
  	if (dnode != onode)
  		msg_set_prevnode(msg, onode);
  	msg_set_destnode(msg, dnode);
5a379074a   Jon Paul Maloy   tipc: introduce m...
646
  	msg_set_destport(msg, dport);
e3a77561e   Jon Paul Maloy   tipc: split up fu...
647
  	*err = TIPC_OK;
a9e2971b8   Jon Maloy   tipc: Unclone mes...
648
649
650
  
  	if (!skb_cloned(skb))
  		return true;
e3a77561e   Jon Paul Maloy   tipc: split up fu...
651
  	return true;
5a379074a   Jon Paul Maloy   tipc: introduce m...
652
  }
078bec826   Jon Paul Maloy   tipc: add new fun...
653

4c94cc2d3   Jon Maloy   tipc: fall back t...
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
  /* tipc_msg_assemble() - assemble chain of fragments into one message
   */
  bool tipc_msg_assemble(struct sk_buff_head *list)
  {
  	struct sk_buff *skb, *tmp = NULL;
  
  	if (skb_queue_len(list) == 1)
  		return true;
  
  	while ((skb = __skb_dequeue(list))) {
  		skb->next = NULL;
  		if (tipc_buf_append(&tmp, &skb)) {
  			__skb_queue_tail(list, skb);
  			return true;
  		}
  		if (!tmp)
  			break;
  	}
  	__skb_queue_purge(list);
  	__skb_queue_head_init(list);
  	pr_warn("Failed do assemble buffer
  ");
  	return false;
  }
078bec826   Jon Paul Maloy   tipc: add new fun...
678
679
680
  /* tipc_msg_reassemble() - clone a buffer chain of fragments and
   *                         reassemble the clones into one message
   */
2f5661245   Jon Paul Maloy   tipc: let broadca...
681
  bool tipc_msg_reassemble(struct sk_buff_head *list, struct sk_buff_head *rcvq)
078bec826   Jon Paul Maloy   tipc: add new fun...
682
  {
2f5661245   Jon Paul Maloy   tipc: let broadca...
683
  	struct sk_buff *skb, *_skb;
a6ca10944   Ying Xue   tipc: use generic...
684
  	struct sk_buff *frag = NULL;
078bec826   Jon Paul Maloy   tipc: add new fun...
685
  	struct sk_buff *head = NULL;
2f5661245   Jon Paul Maloy   tipc: let broadca...
686
  	int hdr_len;
078bec826   Jon Paul Maloy   tipc: add new fun...
687
688
  
  	/* Copy header if single buffer */
a6ca10944   Ying Xue   tipc: use generic...
689
690
  	if (skb_queue_len(list) == 1) {
  		skb = skb_peek(list);
2f5661245   Jon Paul Maloy   tipc: let broadca...
691
692
693
694
695
696
  		hdr_len = skb_headroom(skb) + msg_hdr_sz(buf_msg(skb));
  		_skb = __pskb_copy(skb, hdr_len, GFP_ATOMIC);
  		if (!_skb)
  			return false;
  		__skb_queue_tail(rcvq, _skb);
  		return true;
078bec826   Jon Paul Maloy   tipc: add new fun...
697
698
699
  	}
  
  	/* Clone all fragments and reassemble */
a6ca10944   Ying Xue   tipc: use generic...
700
701
  	skb_queue_walk(list, skb) {
  		frag = skb_clone(skb, GFP_ATOMIC);
078bec826   Jon Paul Maloy   tipc: add new fun...
702
703
704
705
706
707
708
  		if (!frag)
  			goto error;
  		frag->next = NULL;
  		if (tipc_buf_append(&head, &frag))
  			break;
  		if (!head)
  			goto error;
078bec826   Jon Paul Maloy   tipc: add new fun...
709
  	}
2f5661245   Jon Paul Maloy   tipc: let broadca...
710
711
  	__skb_queue_tail(rcvq, frag);
  	return true;
078bec826   Jon Paul Maloy   tipc: add new fun...
712
713
714
715
  error:
  	pr_warn("Failed do clone local mcast rcv buffer
  ");
  	kfree_skb(head);
2f5661245   Jon Paul Maloy   tipc: let broadca...
716
  	return false;
078bec826   Jon Paul Maloy   tipc: add new fun...
717
  }
8306f99a5   Jon Paul Maloy   tipc: disallow pa...
718

a853e4c6d   Jon Paul Maloy   tipc: introduce r...
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
  bool tipc_msg_pskb_copy(u32 dst, struct sk_buff_head *msg,
  			struct sk_buff_head *cpy)
  {
  	struct sk_buff *skb, *_skb;
  
  	skb_queue_walk(msg, skb) {
  		_skb = pskb_copy(skb, GFP_ATOMIC);
  		if (!_skb) {
  			__skb_queue_purge(cpy);
  			return false;
  		}
  		msg_set_destnode(buf_msg(_skb), dst);
  		__skb_queue_tail(cpy, _skb);
  	}
  	return true;
  }
8306f99a5   Jon Paul Maloy   tipc: disallow pa...
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
  /* tipc_skb_queue_sorted(); sort pkt into list according to sequence number
   * @list: list to be appended to
   * @seqno: sequence number of buffer to add
   * @skb: buffer to add
   */
  void __tipc_skb_queue_sorted(struct sk_buff_head *list, u16 seqno,
  			     struct sk_buff *skb)
  {
  	struct sk_buff *_skb, *tmp;
  
  	if (skb_queue_empty(list) || less(seqno, buf_seqno(skb_peek(list)))) {
  		__skb_queue_head(list, skb);
  		return;
  	}
  
  	if (more(seqno, buf_seqno(skb_peek_tail(list)))) {
  		__skb_queue_tail(list, skb);
  		return;
  	}
  
  	skb_queue_walk_safe(list, _skb, tmp) {
  		if (more(seqno, buf_seqno(_skb)))
  			continue;
  		if (seqno == buf_seqno(_skb))
  			break;
  		__skb_queue_before(list, _skb, skb);
  		return;
  	}
  	kfree_skb(skb);
  }
64ac5f597   Jon Maloy   tipc: refactor fu...
765
766
767
768
769
770
771
  
  void tipc_skb_reject(struct net *net, int err, struct sk_buff *skb,
  		     struct sk_buff_head *xmitq)
  {
  	if (tipc_msg_reverse(tipc_own_addr(net), &skb, err))
  		__skb_queue_tail(xmitq, skb);
  }