Blame view

net/tipc/msg.c 18.7 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
  
  /**
9fbfb8b12   Jon Paul Maloy   tipc: rename temp...
235
   * tipc_msg_build - create buffer chain containing specified header and data
067608e9d   Jon Paul Maloy   tipc: introduce d...
236
   * @mhdr: Message header, to be prepended to data
45dcc687f   Al Viro   tipc_msg_build():...
237
   * @m: User message
067608e9d   Jon Paul Maloy   tipc: introduce d...
238
239
   * @dsz: Total length of user data
   * @pktmax: Max packet size that can be used
a6ca10944   Ying Xue   tipc: use generic...
240
241
   * @list: Buffer or chain of buffers to be returned to caller
   *
4c94cc2d3   Jon Maloy   tipc: fall back t...
242
243
244
   * 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...
245
246
   * Returns message data size or errno: -ENOMEM, -EFAULT
   */
4c94cc2d3   Jon Maloy   tipc: fall back t...
247
248
  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...
249
250
  {
  	int mhsz = msg_hdr_sz(mhdr);
4c94cc2d3   Jon Maloy   tipc: fall back t...
251
  	struct tipc_msg pkthdr;
067608e9d   Jon Paul Maloy   tipc: introduce d...
252
  	int msz = mhsz + dsz;
067608e9d   Jon Paul Maloy   tipc: introduce d...
253
  	int pktrem = pktmax;
a6ca10944   Ying Xue   tipc: use generic...
254
  	struct sk_buff *skb;
4c94cc2d3   Jon Maloy   tipc: fall back t...
255
256
  	int drem = dsz;
  	int pktno = 1;
067608e9d   Jon Paul Maloy   tipc: introduce d...
257
  	char *pktpos;
4c94cc2d3   Jon Maloy   tipc: fall back t...
258
  	int pktsz;
067608e9d   Jon Paul Maloy   tipc: introduce d...
259
  	int rc;
a6ca10944   Ying Xue   tipc: use generic...
260

067608e9d   Jon Paul Maloy   tipc: introduce d...
261
262
263
264
  	msg_set_size(mhdr, msz);
  
  	/* No fragmentation needed? */
  	if (likely(msz <= pktmax)) {
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
265
  		skb = tipc_buf_acquire(msz, GFP_KERNEL);
4c94cc2d3   Jon Maloy   tipc: fall back t...
266
267
268
269
270
271
272
273
274
275
  
  		/* 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...
276
  			return -ENOMEM;
4c94cc2d3   Jon Maloy   tipc: fall back t...
277
  		}
c93d3baa2   Ying Xue   tipc: involve nam...
278
  		skb_orphan(skb);
a6ca10944   Ying Xue   tipc: use generic...
279
280
281
  		__skb_queue_tail(list, skb);
  		skb_copy_to_linear_data(skb, mhdr, mhsz);
  		pktpos = skb->data + mhsz;
cbbd26b8b   Al Viro   [iov_iter] new pr...
282
  		if (copy_from_iter_full(pktpos, dsz, &m->msg_iter))
067608e9d   Jon Paul Maloy   tipc: introduce d...
283
284
285
286
287
288
  			return dsz;
  		rc = -EFAULT;
  		goto error;
  	}
  
  	/* Prepare reusable fragment header */
c5898636c   Jon Paul Maloy   tipc: reduce usag...
289
290
  	tipc_msg_init(msg_prevnode(mhdr), &pkthdr, MSG_FRAGMENTER,
  		      FIRST_FRAGMENT, INT_H_SIZE, msg_destnode(mhdr));
067608e9d   Jon Paul Maloy   tipc: introduce d...
291
292
  	msg_set_size(&pkthdr, pktmax);
  	msg_set_fragm_no(&pkthdr, pktno);
e3eea1eb4   Jon Paul Maloy   tipc: clean up ha...
293
  	msg_set_importance(&pkthdr, msg_importance(mhdr));
067608e9d   Jon Paul Maloy   tipc: introduce d...
294
295
  
  	/* Prepare first fragment */
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
296
  	skb = tipc_buf_acquire(pktmax, GFP_KERNEL);
a6ca10944   Ying Xue   tipc: use generic...
297
  	if (!skb)
067608e9d   Jon Paul Maloy   tipc: introduce d...
298
  		return -ENOMEM;
c93d3baa2   Ying Xue   tipc: involve nam...
299
  	skb_orphan(skb);
a6ca10944   Ying Xue   tipc: use generic...
300
301
302
  	__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...
303
304
  	pktpos += INT_H_SIZE;
  	pktrem -= INT_H_SIZE;
a6ca10944   Ying Xue   tipc: use generic...
305
  	skb_copy_to_linear_data_offset(skb, INT_H_SIZE, mhdr, mhsz);
067608e9d   Jon Paul Maloy   tipc: introduce d...
306
307
308
309
310
311
  	pktpos += mhsz;
  	pktrem -= mhsz;
  
  	do {
  		if (drem < pktrem)
  			pktrem = drem;
cbbd26b8b   Al Viro   [iov_iter] new pr...
312
  		if (!copy_from_iter_full(pktpos, pktrem, &m->msg_iter)) {
067608e9d   Jon Paul Maloy   tipc: introduce d...
313
314
315
316
  			rc = -EFAULT;
  			goto error;
  		}
  		drem -= pktrem;
067608e9d   Jon Paul Maloy   tipc: introduce d...
317
318
319
320
321
322
323
324
325
  
  		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...
326
  		skb = tipc_buf_acquire(pktsz, GFP_KERNEL);
a6ca10944   Ying Xue   tipc: use generic...
327
  		if (!skb) {
067608e9d   Jon Paul Maloy   tipc: introduce d...
328
329
330
  			rc = -ENOMEM;
  			goto error;
  		}
c93d3baa2   Ying Xue   tipc: involve nam...
331
  		skb_orphan(skb);
a6ca10944   Ying Xue   tipc: use generic...
332
  		__skb_queue_tail(list, skb);
067608e9d   Jon Paul Maloy   tipc: introduce d...
333
334
335
  		msg_set_type(&pkthdr, FRAGMENT);
  		msg_set_size(&pkthdr, pktsz);
  		msg_set_fragm_no(&pkthdr, ++pktno);
a6ca10944   Ying Xue   tipc: use generic...
336
337
  		skb_copy_to_linear_data(skb, &pkthdr, INT_H_SIZE);
  		pktpos = skb->data + INT_H_SIZE;
067608e9d   Jon Paul Maloy   tipc: introduce d...
338
339
340
  		pktrem = pktsz - INT_H_SIZE;
  
  	} while (1);
a6ca10944   Ying Xue   tipc: use generic...
341
  	msg_set_type(buf_msg(skb), LAST_FRAGMENT);
067608e9d   Jon Paul Maloy   tipc: introduce d...
342
343
  	return dsz;
  error:
a6ca10944   Ying Xue   tipc: use generic...
344
345
  	__skb_queue_purge(list);
  	__skb_queue_head_init(list);
067608e9d   Jon Paul Maloy   tipc: introduce d...
346
347
  	return rc;
  }
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
348
349
  /**
   * tipc_msg_bundle(): Append contents of a buffer to tail of an existing one
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
350
351
   * @skb: the buffer to append to ("bundle")
   * @msg:  message to be appended
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
352
353
354
355
   * @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 ...
356
  bool tipc_msg_bundle(struct sk_buff *skb, struct tipc_msg *msg, u32 mtu)
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
357
  {
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
358
  	struct tipc_msg *bmsg;
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
359
  	unsigned int bsz;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
360
  	unsigned int msz = msg_size(msg);
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
361
  	u32 start, pad;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
362
  	u32 max = mtu - INT_H_SIZE;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
363
364
365
  
  	if (likely(msg_user(msg) == MSG_FRAGMENTER))
  		return false;
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
366
  	if (!skb)
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
367
  		return false;
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
368
  	bmsg = buf_msg(skb);
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
369
370
371
  	bsz = msg_size(bmsg);
  	start = align(bsz);
  	pad = start - bsz;
dff29b1a8   Jon Paul Maloy   tipc: eliminate d...
372
  	if (unlikely(msg_user(msg) == TUNNEL_PROTOCOL))
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
373
374
375
  		return false;
  	if (unlikely(msg_user(msg) == BCAST_PROTOCOL))
  		return false;
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
376
  	if (unlikely(msg_user(bmsg) != MSG_BUNDLER))
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
377
  		return false;
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
378
  	if (unlikely(skb_tailroom(skb) < (pad + msz)))
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
379
380
381
  		return false;
  	if (unlikely(max < (start + msz)))
  		return false;
f21e897ec   Jon Paul Maloy   tipc: improve lin...
382
383
384
  	if ((msg_importance(msg) < TIPC_SYSTEM_IMPORTANCE) &&
  	    (msg_importance(bmsg) == TIPC_SYSTEM_IMPORTANCE))
  		return false;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
385

dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
386
387
  	skb_put(skb, pad + msz);
  	skb_copy_to_linear_data_offset(skb, start, msg, msz);
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
388
389
  	msg_set_size(bmsg, start + msz);
  	msg_set_msgcnt(bmsg, msg_msgcnt(bmsg) + 1);
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
390
391
392
393
  	return true;
  }
  
  /**
c637c1035   Jon Paul Maloy   tipc: resolve rac...
394
   *  tipc_msg_extract(): extract bundled inner packet from buffer
c1336ee47   Jon Paul Maloy   tipc: extract bun...
395
   *  @skb: buffer to be extracted from.
c637c1035   Jon Paul Maloy   tipc: resolve rac...
396
   *  @iskb: extracted inner buffer, to be returned
c1336ee47   Jon Paul Maloy   tipc: extract bun...
397
398
   *  @pos: position in outer message of msg to be extracted.
   *        Returns position of next msg
c637c1035   Jon Paul Maloy   tipc: resolve rac...
399
400
401
402
403
   *  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...
404
405
  	struct tipc_msg *hdr, *ihdr;
  	int imsz;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
406

c1336ee47   Jon Paul Maloy   tipc: extract bun...
407
  	*iskb = NULL;
1149557d6   Jon Paul Maloy   tipc: eliminate u...
408
  	if (unlikely(skb_linearize(skb)))
c1336ee47   Jon Paul Maloy   tipc: extract bun...
409
  		goto none;
ef9be7556   Tung Nguyen   tipc: eliminate b...
410
411
  	hdr = buf_msg(skb);
  	if (unlikely(*pos > (msg_data_sz(hdr) - MIN_H_SIZE)))
c637c1035   Jon Paul Maloy   tipc: resolve rac...
412
  		goto none;
c637c1035   Jon Paul Maloy   tipc: resolve rac...
413

ef9be7556   Tung Nguyen   tipc: eliminate b...
414
415
416
417
  	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...
418
  		goto none;
ef9be7556   Tung Nguyen   tipc: eliminate b...
419
420
421
422
423
424
  
  	*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...
425
  	if (unlikely(!tipc_msg_validate(iskb)))
c637c1035   Jon Paul Maloy   tipc: resolve rac...
426
  		goto none;
ef9be7556   Tung Nguyen   tipc: eliminate b...
427

c637c1035   Jon Paul Maloy   tipc: resolve rac...
428
429
430
431
  	*pos += align(imsz);
  	return true;
  none:
  	kfree_skb(skb);
c1336ee47   Jon Paul Maloy   tipc: extract bun...
432
  	kfree_skb(*iskb);
c637c1035   Jon Paul Maloy   tipc: resolve rac...
433
434
435
436
437
  	*iskb = NULL;
  	return false;
  }
  
  /**
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
438
   * tipc_msg_make_bundle(): Create bundle buf and append message to its tail
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
439
440
441
   * @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...
442
   * @mtu: max allowable size for the bundle buffer, inclusive header
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
443
   * @dnode: destination node for message. (Not always present in header)
b2ad5e5fc   stephen hemminger   tipc: spelling er...
444
   * Returns true if success, otherwise false
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
445
   */
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
446
447
  bool tipc_msg_make_bundle(struct sk_buff **skb,  struct tipc_msg *msg,
  			  u32 mtu, u32 dnode)
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
448
  {
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
449
  	struct sk_buff *_skb;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
450
  	struct tipc_msg *bmsg;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
451
452
453
454
455
  	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...
456
  	if (msg_user(msg) == TUNNEL_PROTOCOL)
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
457
458
459
460
461
  		return false;
  	if (msg_user(msg) == BCAST_PROTOCOL)
  		return false;
  	if (msz > (max / 2))
  		return false;
57d5f64d8   Parthasarathy Bhuvaragan   tipc: allocate us...
462
  	_skb = tipc_buf_acquire(max, GFP_ATOMIC);
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
463
  	if (!_skb)
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
464
  		return false;
dd3f9e70f   Jon Paul Maloy   tipc: add packet ...
465
466
  	skb_trim(_skb, INT_H_SIZE);
  	bmsg = buf_msg(_skb);
c5898636c   Jon Paul Maloy   tipc: reduce usag...
467
468
  	tipc_msg_init(msg_prevnode(msg), bmsg, MSG_BUNDLER, 0,
  		      INT_H_SIZE, dnode);
f21e897ec   Jon Paul Maloy   tipc: improve lin...
469
470
471
472
  	if (msg_isdata(msg))
  		msg_set_importance(bmsg, TIPC_CRITICAL_IMPORTANCE);
  	else
  		msg_set_importance(bmsg, TIPC_SYSTEM_IMPORTANCE);
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
473
474
475
  	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 ...
476
477
  	tipc_msg_bundle(_skb, msg, mtu);
  	*skb = _skb;
05dcc5aa4   Jon Paul Maloy   tipc: split link ...
478
  	return true;
4f1688b2c   Jon Paul Maloy   tipc: introduce s...
479
  }
8db1bae30   Jon Paul Maloy   tipc: separate bu...
480
481
482
  
  /**
   * tipc_msg_reverse(): swap source and destination addresses and add error code
29042e19f   Jon Paul Maloy   tipc: let functio...
483
   * @own_node: originating node id for reversed message
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
484
   * @skb:  buffer containing message to be reversed; will be consumed
29042e19f   Jon Paul Maloy   tipc: let functio...
485
   * @err:  error code to be set in message, if any
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
486
   * Replaces consumed buffer with new one when successful
8db1bae30   Jon Paul Maloy   tipc: separate bu...
487
488
   * Returns true if success, otherwise false
   */
bcd3ffd4f   Jon Paul Maloy   tipc: introduce n...
489
  bool tipc_msg_reverse(u32 own_node,  struct sk_buff **skb, int err)
8db1bae30   Jon Paul Maloy   tipc: separate bu...
490
  {
29042e19f   Jon Paul Maloy   tipc: let functio...
491
  	struct sk_buff *_skb = *skb;
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
492
493
  	struct tipc_msg *_hdr, *hdr;
  	int hlen, dlen;
8db1bae30   Jon Paul Maloy   tipc: separate bu...
494

29042e19f   Jon Paul Maloy   tipc: let functio...
495
  	if (skb_linearize(_skb))
8db1bae30   Jon Paul Maloy   tipc: separate bu...
496
  		goto exit;
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
497
498
499
500
501
  	_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...
502
  		goto exit;
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
503
  	if (msg_errcode(_hdr))
8db1bae30   Jon Paul Maloy   tipc: separate bu...
504
  		goto exit;
29042e19f   Jon Paul Maloy   tipc: let functio...
505

5cbdbd1a1   Jon Maloy   tipc: refactor fu...
506
507
508
  	/* Never return SHORT header */
  	if (hlen == SHORT_H_SIZE)
  		hlen = BASIC_H_SIZE;
29042e19f   Jon Paul Maloy   tipc: let functio...
509

5cbdbd1a1   Jon Maloy   tipc: refactor fu...
510
511
512
513
514
515
516
517
518
519
  	/* 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...
520
  	msg_set_errcode(hdr, err);
59a361bc6   Jon Paul Maloy   tipc: avoid inher...
521
  	msg_set_non_seq(hdr, 0);
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
522
523
524
  	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...
525
526
  	msg_set_prevnode(hdr, own_node);
  	msg_set_orignode(hdr, own_node);
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
527
  	msg_set_size(hdr, hlen + dlen);
29042e19f   Jon Paul Maloy   tipc: let functio...
528
  	skb_orphan(_skb);
5cbdbd1a1   Jon Maloy   tipc: refactor fu...
529
  	kfree_skb(_skb);
8db1bae30   Jon Paul Maloy   tipc: separate bu...
530
531
  	return true;
  exit:
29042e19f   Jon Paul Maloy   tipc: let functio...
532
533
  	kfree_skb(_skb);
  	*skb = NULL;
8db1bae30   Jon Paul Maloy   tipc: separate bu...
534
535
  	return false;
  }
5a379074a   Jon Paul Maloy   tipc: introduce m...
536
537
  
  /**
e3a77561e   Jon Paul Maloy   tipc: split up fu...
538
539
   * 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...
540
   * @err: error code to be used by caller if lookup fails
5a379074a   Jon Paul Maloy   tipc: introduce m...
541
   * Does not consume buffer
e3a77561e   Jon Paul Maloy   tipc: split up fu...
542
   * Returns true if a destination is found, false otherwise
5a379074a   Jon Paul Maloy   tipc: introduce m...
543
   */
cda3696d3   Jon Paul Maloy   tipc: clean up so...
544
  bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
5a379074a   Jon Paul Maloy   tipc: introduce m...
545
  {
e3a77561e   Jon Paul Maloy   tipc: split up fu...
546
  	struct tipc_msg *msg = buf_msg(skb);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
547
548
  	u32 dport, dnode;
  	u32 onode = tipc_own_addr(net);
5a379074a   Jon Paul Maloy   tipc: introduce m...
549

e3a77561e   Jon Paul Maloy   tipc: split up fu...
550
551
552
553
  	if (!msg_isdata(msg))
  		return false;
  	if (!msg_named(msg))
  		return false;
d482994fc   Jon Paul Maloy   tipc: fix two bug...
554
555
  	if (msg_errcode(msg))
  		return false;
aad06212d   Parthasarathy Bhuvaragan   tipc: use only po...
556
  	*err = TIPC_ERR_NO_NAME;
e3a77561e   Jon Paul Maloy   tipc: split up fu...
557
558
  	if (skb_linearize(skb))
  		return false;
4e3ae0010   Erik Hugne   tipc: reinitializ...
559
  	msg = buf_msg(skb);
d482994fc   Jon Paul Maloy   tipc: fix two bug...
560
  	if (msg_reroute_cnt(msg))
e3a77561e   Jon Paul Maloy   tipc: split up fu...
561
  		return false;
928df1880   Jon Maloy   tipc: obsolete TI...
562
  	dnode = tipc_scope2node(net, msg_lookup_scope(msg));
4ac1c8d0e   Ying Xue   tipc: name tipc n...
563
  	dport = tipc_nametbl_translate(net, msg_nametype(msg),
cda3696d3   Jon Paul Maloy   tipc: clean up so...
564
  				       msg_nameinst(msg), &dnode);
5a379074a   Jon Paul Maloy   tipc: introduce m...
565
  	if (!dport)
e3a77561e   Jon Paul Maloy   tipc: split up fu...
566
  		return false;
5a379074a   Jon Paul Maloy   tipc: introduce m...
567
  	msg_incr_reroute_cnt(msg);
cda3696d3   Jon Paul Maloy   tipc: clean up so...
568
569
570
  	if (dnode != onode)
  		msg_set_prevnode(msg, onode);
  	msg_set_destnode(msg, dnode);
5a379074a   Jon Paul Maloy   tipc: introduce m...
571
  	msg_set_destport(msg, dport);
e3a77561e   Jon Paul Maloy   tipc: split up fu...
572
  	*err = TIPC_OK;
a9e2971b8   Jon Maloy   tipc: Unclone mes...
573
574
575
  
  	if (!skb_cloned(skb))
  		return true;
e3a77561e   Jon Paul Maloy   tipc: split up fu...
576
  	return true;
5a379074a   Jon Paul Maloy   tipc: introduce m...
577
  }
078bec826   Jon Paul Maloy   tipc: add new fun...
578

4c94cc2d3   Jon Maloy   tipc: fall back t...
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
  /* 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...
603
604
605
  /* tipc_msg_reassemble() - clone a buffer chain of fragments and
   *                         reassemble the clones into one message
   */
2f5661245   Jon Paul Maloy   tipc: let broadca...
606
  bool tipc_msg_reassemble(struct sk_buff_head *list, struct sk_buff_head *rcvq)
078bec826   Jon Paul Maloy   tipc: add new fun...
607
  {
2f5661245   Jon Paul Maloy   tipc: let broadca...
608
  	struct sk_buff *skb, *_skb;
a6ca10944   Ying Xue   tipc: use generic...
609
  	struct sk_buff *frag = NULL;
078bec826   Jon Paul Maloy   tipc: add new fun...
610
  	struct sk_buff *head = NULL;
2f5661245   Jon Paul Maloy   tipc: let broadca...
611
  	int hdr_len;
078bec826   Jon Paul Maloy   tipc: add new fun...
612
613
  
  	/* Copy header if single buffer */
a6ca10944   Ying Xue   tipc: use generic...
614
615
  	if (skb_queue_len(list) == 1) {
  		skb = skb_peek(list);
2f5661245   Jon Paul Maloy   tipc: let broadca...
616
617
618
619
620
621
  		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...
622
623
624
  	}
  
  	/* Clone all fragments and reassemble */
a6ca10944   Ying Xue   tipc: use generic...
625
626
  	skb_queue_walk(list, skb) {
  		frag = skb_clone(skb, GFP_ATOMIC);
078bec826   Jon Paul Maloy   tipc: add new fun...
627
628
629
630
631
632
633
  		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...
634
  	}
2f5661245   Jon Paul Maloy   tipc: let broadca...
635
636
  	__skb_queue_tail(rcvq, frag);
  	return true;
078bec826   Jon Paul Maloy   tipc: add new fun...
637
638
639
640
  error:
  	pr_warn("Failed do clone local mcast rcv buffer
  ");
  	kfree_skb(head);
2f5661245   Jon Paul Maloy   tipc: let broadca...
641
  	return false;
078bec826   Jon Paul Maloy   tipc: add new fun...
642
  }
8306f99a5   Jon Paul Maloy   tipc: disallow pa...
643

a853e4c6d   Jon Paul Maloy   tipc: introduce r...
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
  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...
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
  /* 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...
690
691
692
693
694
695
696
  
  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);
  }