diff options
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r-- | net/tipc/msg.c | 67 |
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 | */ |
472 | bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, | 472 | bool 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; |
500 | exit: | 515 | exit: |
501 | kfree_skb(buf); | 516 | kfree_skb(_skb); |
502 | *dnode = 0; | 517 | *skb = NULL; |
503 | return false; | 518 | return false; |
504 | } | 519 | } |
505 | 520 | ||