diff options
-rw-r--r-- | net/tipc/msg.c | 58 |
1 files changed, 28 insertions, 30 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index b61891054709..00fbb5c4b2ef 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -499,54 +499,52 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg, | |||
499 | /** | 499 | /** |
500 | * tipc_msg_reverse(): swap source and destination addresses and add error code | 500 | * tipc_msg_reverse(): swap source and destination addresses and add error code |
501 | * @own_node: originating node id for reversed message | 501 | * @own_node: originating node id for reversed message |
502 | * @skb: buffer containing message to be reversed; may be replaced. | 502 | * @skb: buffer containing message to be reversed; will be consumed |
503 | * @err: error code to be set in message, if any | 503 | * @err: error code to be set in message, if any |
504 | * Consumes buffer at failure | 504 | * Replaces consumed buffer with new one when successful |
505 | * Returns true if success, otherwise false | 505 | * Returns true if success, otherwise false |
506 | */ | 506 | */ |
507 | bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, int err) | 507 | bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, int err) |
508 | { | 508 | { |
509 | struct sk_buff *_skb = *skb; | 509 | struct sk_buff *_skb = *skb; |
510 | struct tipc_msg *hdr; | 510 | struct tipc_msg *_hdr, *hdr; |
511 | struct tipc_msg ohdr; | 511 | int hlen, dlen; |
512 | int dlen; | ||
513 | 512 | ||
514 | if (skb_linearize(_skb)) | 513 | if (skb_linearize(_skb)) |
515 | goto exit; | 514 | goto exit; |
516 | hdr = buf_msg(_skb); | 515 | _hdr = buf_msg(_skb); |
517 | dlen = min_t(uint, msg_data_sz(hdr), MAX_FORWARD_SIZE); | 516 | dlen = min_t(uint, msg_data_sz(_hdr), MAX_FORWARD_SIZE); |
518 | if (msg_dest_droppable(hdr)) | 517 | hlen = msg_hdr_sz(_hdr); |
518 | |||
519 | if (msg_dest_droppable(_hdr)) | ||
519 | goto exit; | 520 | goto exit; |
520 | if (msg_errcode(hdr)) | 521 | if (msg_errcode(_hdr)) |
521 | goto exit; | 522 | goto exit; |
522 | 523 | ||
523 | /* Take a copy of original header before altering message */ | 524 | /* Never return SHORT header */ |
524 | memcpy(&ohdr, hdr, msg_hdr_sz(hdr)); | 525 | if (hlen == SHORT_H_SIZE) |
525 | 526 | hlen = BASIC_H_SIZE; | |
526 | /* Never return SHORT header; expand by replacing buffer if necessary */ | ||
527 | if (msg_short(hdr)) { | ||
528 | *skb = tipc_buf_acquire(BASIC_H_SIZE + dlen, GFP_ATOMIC); | ||
529 | if (!*skb) | ||
530 | goto exit; | ||
531 | memcpy((*skb)->data + BASIC_H_SIZE, msg_data(hdr), dlen); | ||
532 | kfree_skb(_skb); | ||
533 | _skb = *skb; | ||
534 | hdr = buf_msg(_skb); | ||
535 | memcpy(hdr, &ohdr, BASIC_H_SIZE); | ||
536 | msg_set_hdr_sz(hdr, BASIC_H_SIZE); | ||
537 | } | ||
538 | 527 | ||
539 | /* Now reverse the concerned fields */ | 528 | /* Allocate new buffer to return */ |
529 | *skb = tipc_buf_acquire(hlen + dlen, GFP_ATOMIC); | ||
530 | if (!*skb) | ||
531 | goto exit; | ||
532 | memcpy((*skb)->data, _skb->data, msg_hdr_sz(_hdr)); | ||
533 | memcpy((*skb)->data + hlen, msg_data(_hdr), dlen); | ||
534 | |||
535 | /* Build reverse header in new buffer */ | ||
536 | hdr = buf_msg(*skb); | ||
537 | msg_set_hdr_sz(hdr, hlen); | ||
540 | msg_set_errcode(hdr, err); | 538 | msg_set_errcode(hdr, err); |
541 | msg_set_non_seq(hdr, 0); | 539 | msg_set_non_seq(hdr, 0); |
542 | msg_set_origport(hdr, msg_destport(&ohdr)); | 540 | msg_set_origport(hdr, msg_destport(_hdr)); |
543 | msg_set_destport(hdr, msg_origport(&ohdr)); | 541 | msg_set_destport(hdr, msg_origport(_hdr)); |
544 | msg_set_destnode(hdr, msg_prevnode(&ohdr)); | 542 | msg_set_destnode(hdr, msg_prevnode(_hdr)); |
545 | msg_set_prevnode(hdr, own_node); | 543 | msg_set_prevnode(hdr, own_node); |
546 | msg_set_orignode(hdr, own_node); | 544 | msg_set_orignode(hdr, own_node); |
547 | msg_set_size(hdr, msg_hdr_sz(hdr) + dlen); | 545 | msg_set_size(hdr, hlen + dlen); |
548 | skb_trim(_skb, msg_size(hdr)); | ||
549 | skb_orphan(_skb); | 546 | skb_orphan(_skb); |
547 | kfree_skb(_skb); | ||
550 | return true; | 548 | return true; |
551 | exit: | 549 | exit: |
552 | kfree_skb(_skb); | 550 | kfree_skb(_skb); |