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.c67
1 files changed, 41 insertions, 26 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 08b4cc7d496d..4339aab93034 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -463,43 +463,58 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg,
463 463
464/** 464/**
465 * tipc_msg_reverse(): swap source and destination addresses and add error code 465 * tipc_msg_reverse(): swap source and destination addresses and add error code
466 * @buf: buffer containing message to be reversed 466 * @own_node: originating node id for reversed message
467 * @dnode: return value: node where to send message after reversal 467 * @skb: buffer containing message to be reversed; may be replaced.
468 * @err: error code to be set in message 468 * @err: error code to be set in message, if any
469 * Consumes buffer if failure 469 * Consumes buffer at failure
470 * Returns true if success, otherwise false 470 * Returns true if success, otherwise false
471 */ 471 */
472bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, 472bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, u32 *dnode, int err)
473 int err)
474{ 473{
475 struct tipc_msg *msg = buf_msg(buf); 474 struct sk_buff *_skb = *skb;
475 struct tipc_msg *hdr = buf_msg(_skb);
476 struct tipc_msg ohdr; 476 struct tipc_msg ohdr;
477 uint rdsz = min_t(uint, msg_data_sz(msg), MAX_FORWARD_SIZE); 477 int dlen = min_t(uint, msg_data_sz(hdr), MAX_FORWARD_SIZE);
478 478
479 if (skb_linearize(buf)) 479 if (skb_linearize(_skb))
480 goto exit; 480 goto exit;
481 msg = buf_msg(buf); 481 hdr = buf_msg(_skb);
482 if (msg_dest_droppable(msg)) 482 if (msg_dest_droppable(hdr))
483 goto exit; 483 goto exit;
484 if (msg_errcode(msg)) 484 if (msg_errcode(hdr))
485 goto exit; 485 goto exit;
486 memcpy(&ohdr, msg, msg_hdr_sz(msg)); 486
487 msg_set_errcode(msg, err); 487 /* Take a copy of original header before altering message */
488 msg_set_origport(msg, msg_destport(&ohdr)); 488 memcpy(&ohdr, hdr, msg_hdr_sz(hdr));
489 msg_set_destport(msg, msg_origport(&ohdr)); 489
490 msg_set_prevnode(msg, own_addr); 490 /* Never return SHORT header; expand by replacing buffer if necessary */
491 if (!msg_short(msg)) { 491 if (msg_short(hdr)) {
492 msg_set_orignode(msg, msg_destnode(&ohdr)); 492 *skb = tipc_buf_acquire(BASIC_H_SIZE + dlen);
493 msg_set_destnode(msg, msg_orignode(&ohdr)); 493 if (!*skb)
494 goto exit;
495 memcpy((*skb)->data + BASIC_H_SIZE, msg_data(hdr), dlen);
496 kfree_skb(_skb);
497 _skb = *skb;
498 hdr = buf_msg(_skb);
499 memcpy(hdr, &ohdr, BASIC_H_SIZE);
500 msg_set_hdr_sz(hdr, BASIC_H_SIZE);
494 } 501 }
495 msg_set_size(msg, msg_hdr_sz(msg) + rdsz); 502
496 skb_trim(buf, msg_size(msg)); 503 /* Now reverse the concerned fields */
497 skb_orphan(buf); 504 msg_set_errcode(hdr, err);
498 *dnode = msg_orignode(&ohdr); 505 msg_set_origport(hdr, msg_destport(&ohdr));
506 msg_set_destport(hdr, msg_origport(&ohdr));
507 msg_set_destnode(hdr, msg_prevnode(&ohdr));
508 msg_set_prevnode(hdr, own_node);
509 msg_set_orignode(hdr, own_node);
510 msg_set_size(hdr, msg_hdr_sz(hdr) + dlen);
511 *dnode = msg_destnode(hdr);
512 skb_trim(_skb, msg_size(hdr));
513 skb_orphan(_skb);
499 return true; 514 return true;
500exit: 515exit:
501 kfree_skb(buf); 516 kfree_skb(_skb);
502 *dnode = 0; 517 *skb = NULL;
503 return false; 518 return false;
504} 519}
505 520