aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r--net/tipc/msg.c153
1 files changed, 106 insertions, 47 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index a687b30a699c..b6eb90cd3ef7 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -34,6 +34,7 @@
34 * POSSIBILITY OF SUCH DAMAGE. 34 * POSSIBILITY OF SUCH DAMAGE.
35 */ 35 */
36 36
37#include <net/sock.h>
37#include "core.h" 38#include "core.h"
38#include "msg.h" 39#include "msg.h"
39#include "addr.h" 40#include "addr.h"
@@ -46,25 +47,48 @@ static unsigned int align(unsigned int i)
46 return (i + 3) & ~3u; 47 return (i + 3) & ~3u;
47} 48}
48 49
49void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, 50/**
50 u32 destnode) 51 * tipc_buf_acquire - creates a TIPC message buffer
52 * @size: message size (including TIPC header)
53 *
54 * Returns a new buffer with data pointers set to the specified size.
55 *
56 * NOTE: Headroom is reserved to allow prepending of a data link header.
57 * There may also be unrequested tailroom present at the buffer's end.
58 */
59struct sk_buff *tipc_buf_acquire(u32 size)
60{
61 struct sk_buff *skb;
62 unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
63
64 skb = alloc_skb_fclone(buf_size, GFP_ATOMIC);
65 if (skb) {
66 skb_reserve(skb, BUF_HEADROOM);
67 skb_put(skb, size);
68 skb->next = NULL;
69 }
70 return skb;
71}
72
73void tipc_msg_init(u32 own_node, struct tipc_msg *m, u32 user, u32 type,
74 u32 hsize, u32 dnode)
51{ 75{
52 memset(m, 0, hsize); 76 memset(m, 0, hsize);
53 msg_set_version(m); 77 msg_set_version(m);
54 msg_set_user(m, user); 78 msg_set_user(m, user);
55 msg_set_hdr_sz(m, hsize); 79 msg_set_hdr_sz(m, hsize);
56 msg_set_size(m, hsize); 80 msg_set_size(m, hsize);
57 msg_set_prevnode(m, tipc_own_addr); 81 msg_set_prevnode(m, own_node);
58 msg_set_type(m, type); 82 msg_set_type(m, type);
59 if (hsize > SHORT_H_SIZE) { 83 if (hsize > SHORT_H_SIZE) {
60 msg_set_orignode(m, tipc_own_addr); 84 msg_set_orignode(m, own_node);
61 msg_set_destnode(m, destnode); 85 msg_set_destnode(m, dnode);
62 } 86 }
63} 87}
64 88
65struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, 89struct sk_buff *tipc_msg_create(uint user, uint type,
66 uint data_sz, u32 dnode, u32 onode, 90 uint hdr_sz, uint data_sz, u32 dnode,
67 u32 dport, u32 oport, int errcode) 91 u32 onode, u32 dport, u32 oport, int errcode)
68{ 92{
69 struct tipc_msg *msg; 93 struct tipc_msg *msg;
70 struct sk_buff *buf; 94 struct sk_buff *buf;
@@ -74,9 +98,8 @@ struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz,
74 return NULL; 98 return NULL;
75 99
76 msg = buf_msg(buf); 100 msg = buf_msg(buf);
77 tipc_msg_init(msg, user, type, hdr_sz, dnode); 101 tipc_msg_init(onode, msg, user, type, hdr_sz, dnode);
78 msg_set_size(msg, hdr_sz + data_sz); 102 msg_set_size(msg, hdr_sz + data_sz);
79 msg_set_prevnode(msg, onode);
80 msg_set_origport(msg, oport); 103 msg_set_origport(msg, oport);
81 msg_set_destport(msg, dport); 104 msg_set_destport(msg, dport);
82 msg_set_errcode(msg, errcode); 105 msg_set_errcode(msg, errcode);
@@ -163,15 +186,14 @@ err:
163 * tipc_msg_build - create buffer chain containing specified header and data 186 * tipc_msg_build - create buffer chain containing specified header and data
164 * @mhdr: Message header, to be prepended to data 187 * @mhdr: Message header, to be prepended to data
165 * @m: User message 188 * @m: User message
166 * @offset: Posision in iov to start copying from
167 * @dsz: Total length of user data 189 * @dsz: Total length of user data
168 * @pktmax: Max packet size that can be used 190 * @pktmax: Max packet size that can be used
169 * @list: Buffer or chain of buffers to be returned to caller 191 * @list: Buffer or chain of buffers to be returned to caller
170 * 192 *
171 * Returns message data size or errno: -ENOMEM, -EFAULT 193 * Returns message data size or errno: -ENOMEM, -EFAULT
172 */ 194 */
173int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, 195int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
174 int dsz, int pktmax, struct sk_buff_head *list) 196 int offset, int dsz, int pktmax, struct sk_buff_head *list)
175{ 197{
176 int mhsz = msg_hdr_sz(mhdr); 198 int mhsz = msg_hdr_sz(mhdr);
177 int msz = mhsz + dsz; 199 int msz = mhsz + dsz;
@@ -191,19 +213,19 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
191 skb = tipc_buf_acquire(msz); 213 skb = tipc_buf_acquire(msz);
192 if (unlikely(!skb)) 214 if (unlikely(!skb))
193 return -ENOMEM; 215 return -ENOMEM;
216 skb_orphan(skb);
194 __skb_queue_tail(list, skb); 217 __skb_queue_tail(list, skb);
195 skb_copy_to_linear_data(skb, mhdr, mhsz); 218 skb_copy_to_linear_data(skb, mhdr, mhsz);
196 pktpos = skb->data + mhsz; 219 pktpos = skb->data + mhsz;
197 if (!dsz || !memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset, 220 if (copy_from_iter(pktpos, dsz, &m->msg_iter) == dsz)
198 dsz))
199 return dsz; 221 return dsz;
200 rc = -EFAULT; 222 rc = -EFAULT;
201 goto error; 223 goto error;
202 } 224 }
203 225
204 /* Prepare reusable fragment header */ 226 /* Prepare reusable fragment header */
205 tipc_msg_init(&pkthdr, MSG_FRAGMENTER, FIRST_FRAGMENT, 227 tipc_msg_init(msg_prevnode(mhdr), &pkthdr, MSG_FRAGMENTER,
206 INT_H_SIZE, msg_destnode(mhdr)); 228 FIRST_FRAGMENT, INT_H_SIZE, msg_destnode(mhdr));
207 msg_set_size(&pkthdr, pktmax); 229 msg_set_size(&pkthdr, pktmax);
208 msg_set_fragm_no(&pkthdr, pktno); 230 msg_set_fragm_no(&pkthdr, pktno);
209 231
@@ -211,6 +233,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
211 skb = tipc_buf_acquire(pktmax); 233 skb = tipc_buf_acquire(pktmax);
212 if (!skb) 234 if (!skb)
213 return -ENOMEM; 235 return -ENOMEM;
236 skb_orphan(skb);
214 __skb_queue_tail(list, skb); 237 __skb_queue_tail(list, skb);
215 pktpos = skb->data; 238 pktpos = skb->data;
216 skb_copy_to_linear_data(skb, &pkthdr, INT_H_SIZE); 239 skb_copy_to_linear_data(skb, &pkthdr, INT_H_SIZE);
@@ -224,12 +247,11 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
224 if (drem < pktrem) 247 if (drem < pktrem)
225 pktrem = drem; 248 pktrem = drem;
226 249
227 if (memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset, pktrem)) { 250 if (copy_from_iter(pktpos, pktrem, &m->msg_iter) != pktrem) {
228 rc = -EFAULT; 251 rc = -EFAULT;
229 goto error; 252 goto error;
230 } 253 }
231 drem -= pktrem; 254 drem -= pktrem;
232 offset += pktrem;
233 255
234 if (!drem) 256 if (!drem)
235 break; 257 break;
@@ -244,6 +266,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
244 rc = -ENOMEM; 266 rc = -ENOMEM;
245 goto error; 267 goto error;
246 } 268 }
269 skb_orphan(skb);
247 __skb_queue_tail(list, skb); 270 __skb_queue_tail(list, skb);
248 msg_set_type(&pkthdr, FRAGMENT); 271 msg_set_type(&pkthdr, FRAGMENT);
249 msg_set_size(&pkthdr, pktsz); 272 msg_set_size(&pkthdr, pktsz);
@@ -304,6 +327,40 @@ bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu)
304} 327}
305 328
306/** 329/**
330 * tipc_msg_extract(): extract bundled inner packet from buffer
331 * @skb: linear outer buffer, to be extracted from.
332 * @iskb: extracted inner buffer, to be returned
333 * @pos: position of msg to be extracted. Returns with pointer of next msg
334 * Consumes outer buffer when last packet extracted
335 * Returns true when when there is an extracted buffer, otherwise false
336 */
337bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos)
338{
339 struct tipc_msg *msg = buf_msg(skb);
340 int imsz;
341 struct tipc_msg *imsg = (struct tipc_msg *)(msg_data(msg) + *pos);
342
343 /* Is there space left for shortest possible message? */
344 if (*pos > (msg_data_sz(msg) - SHORT_H_SIZE))
345 goto none;
346 imsz = msg_size(imsg);
347
348 /* Is there space left for current message ? */
349 if ((*pos + imsz) > msg_data_sz(msg))
350 goto none;
351 *iskb = tipc_buf_acquire(imsz);
352 if (!*iskb)
353 goto none;
354 skb_copy_to_linear_data(*iskb, imsg, imsz);
355 *pos += align(imsz);
356 return true;
357none:
358 kfree_skb(skb);
359 *iskb = NULL;
360 return false;
361}
362
363/**
307 * tipc_msg_make_bundle(): Create bundle buf and append message to its tail 364 * tipc_msg_make_bundle(): Create bundle buf and append message to its tail
308 * @list: the buffer chain 365 * @list: the buffer chain
309 * @skb: buffer to be appended and replaced 366 * @skb: buffer to be appended and replaced
@@ -312,8 +369,8 @@ bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu)
312 * Replaces buffer if successful 369 * Replaces buffer if successful
313 * Returns true if success, otherwise false 370 * Returns true if success, otherwise false
314 */ 371 */
315bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb, 372bool tipc_msg_make_bundle(struct sk_buff_head *list,
316 u32 mtu, u32 dnode) 373 struct sk_buff *skb, u32 mtu, u32 dnode)
317{ 374{
318 struct sk_buff *bskb; 375 struct sk_buff *bskb;
319 struct tipc_msg *bmsg; 376 struct tipc_msg *bmsg;
@@ -336,7 +393,8 @@ bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb,
336 393
337 skb_trim(bskb, INT_H_SIZE); 394 skb_trim(bskb, INT_H_SIZE);
338 bmsg = buf_msg(bskb); 395 bmsg = buf_msg(bskb);
339 tipc_msg_init(bmsg, MSG_BUNDLER, 0, INT_H_SIZE, dnode); 396 tipc_msg_init(msg_prevnode(msg), bmsg, MSG_BUNDLER, 0,
397 INT_H_SIZE, dnode);
340 msg_set_seqno(bmsg, msg_seqno(msg)); 398 msg_set_seqno(bmsg, msg_seqno(msg));
341 msg_set_ack(bmsg, msg_ack(msg)); 399 msg_set_ack(bmsg, msg_ack(msg));
342 msg_set_bcast_ack(bmsg, msg_bcast_ack(msg)); 400 msg_set_bcast_ack(bmsg, msg_bcast_ack(msg));
@@ -353,7 +411,8 @@ bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb,
353 * Consumes buffer if failure 411 * Consumes buffer if failure
354 * Returns true if success, otherwise false 412 * Returns true if success, otherwise false
355 */ 413 */
356bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err) 414bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode,
415 int err)
357{ 416{
358 struct tipc_msg *msg = buf_msg(buf); 417 struct tipc_msg *msg = buf_msg(buf);
359 uint imp = msg_importance(msg); 418 uint imp = msg_importance(msg);
@@ -374,7 +433,7 @@ bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err)
374 msg_set_errcode(msg, err); 433 msg_set_errcode(msg, err);
375 msg_set_origport(msg, msg_destport(&ohdr)); 434 msg_set_origport(msg, msg_destport(&ohdr));
376 msg_set_destport(msg, msg_origport(&ohdr)); 435 msg_set_destport(msg, msg_origport(&ohdr));
377 msg_set_prevnode(msg, tipc_own_addr); 436 msg_set_prevnode(msg, own_addr);
378 if (!msg_short(msg)) { 437 if (!msg_short(msg)) {
379 msg_set_orignode(msg, msg_destnode(&ohdr)); 438 msg_set_orignode(msg, msg_destnode(&ohdr));
380 msg_set_destnode(msg, msg_orignode(&ohdr)); 439 msg_set_destnode(msg, msg_orignode(&ohdr));
@@ -386,43 +445,43 @@ bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err)
386 return true; 445 return true;
387exit: 446exit:
388 kfree_skb(buf); 447 kfree_skb(buf);
448 *dnode = 0;
389 return false; 449 return false;
390} 450}
391 451
392/** 452/**
393 * tipc_msg_eval: determine fate of message that found no destination 453 * tipc_msg_lookup_dest(): try to find new destination for named message
394 * @buf: the buffer containing the message. 454 * @skb: the buffer containing the message.
395 * @dnode: return value: next-hop node, if message to be forwarded 455 * @dnode: return value: next-hop node, if destination found
396 * @err: error code to use, if message to be rejected 456 * @err: return value: error code to use, if message to be rejected
397 *
398 * Does not consume buffer 457 * Does not consume buffer
399 * Returns 0 (TIPC_OK) if message ok and we can try again, -TIPC error 458 * Returns true if a destination is found, false otherwise
400 * code if message to be rejected
401 */ 459 */
402int tipc_msg_eval(struct sk_buff *buf, u32 *dnode) 460bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb,
461 u32 *dnode, int *err)
403{ 462{
404 struct tipc_msg *msg = buf_msg(buf); 463 struct tipc_msg *msg = buf_msg(skb);
405 u32 dport; 464 u32 dport;
406 465
407 if (msg_type(msg) != TIPC_NAMED_MSG) 466 if (!msg_isdata(msg))
408 return -TIPC_ERR_NO_PORT; 467 return false;
409 if (skb_linearize(buf)) 468 if (!msg_named(msg))
410 return -TIPC_ERR_NO_NAME; 469 return false;
411 if (msg_data_sz(msg) > MAX_FORWARD_SIZE) 470 *err = -TIPC_ERR_NO_NAME;
412 return -TIPC_ERR_NO_NAME; 471 if (skb_linearize(skb))
472 return false;
413 if (msg_reroute_cnt(msg) > 0) 473 if (msg_reroute_cnt(msg) > 0)
414 return -TIPC_ERR_NO_NAME; 474 return false;
415 475 *dnode = addr_domain(net, msg_lookup_scope(msg));
416 *dnode = addr_domain(msg_lookup_scope(msg)); 476 dport = tipc_nametbl_translate(net, msg_nametype(msg),
417 dport = tipc_nametbl_translate(msg_nametype(msg), 477 msg_nameinst(msg), dnode);
418 msg_nameinst(msg),
419 dnode);
420 if (!dport) 478 if (!dport)
421 return -TIPC_ERR_NO_NAME; 479 return false;
422 msg_incr_reroute_cnt(msg); 480 msg_incr_reroute_cnt(msg);
423 msg_set_destnode(msg, *dnode); 481 msg_set_destnode(msg, *dnode);
424 msg_set_destport(msg, dport); 482 msg_set_destport(msg, dport);
425 return TIPC_OK; 483 *err = TIPC_OK;
484 return true;
426} 485}
427 486
428/* tipc_msg_reassemble() - clone a buffer chain of fragments and 487/* tipc_msg_reassemble() - clone a buffer chain of fragments and