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.c86
1 files changed, 49 insertions, 37 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 08b4cc7d496d..562c926a51cc 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -463,60 +463,72 @@ 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, 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 skb_trim(_skb, msg_size(hdr));
512 skb_orphan(_skb);
499 return true; 513 return true;
500exit: 514exit:
501 kfree_skb(buf); 515 kfree_skb(_skb);
502 *dnode = 0; 516 *skb = NULL;
503 return false; 517 return false;
504} 518}
505 519
506/** 520/**
507 * tipc_msg_lookup_dest(): try to find new destination for named message 521 * tipc_msg_lookup_dest(): try to find new destination for named message
508 * @skb: the buffer containing the message. 522 * @skb: the buffer containing the message.
509 * @dnode: return value: next-hop node, if destination found 523 * @err: error code to be used by caller if lookup fails
510 * @err: return value: error code to use, if message to be rejected
511 * Does not consume buffer 524 * Does not consume buffer
512 * Returns true if a destination is found, false otherwise 525 * Returns true if a destination is found, false otherwise
513 */ 526 */
514bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, 527bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
515 u32 *dnode, int *err)
516{ 528{
517 struct tipc_msg *msg = buf_msg(skb); 529 struct tipc_msg *msg = buf_msg(skb);
518 u32 dport; 530 u32 dport, dnode;
519 u32 own_addr = tipc_own_addr(net); 531 u32 onode = tipc_own_addr(net);
520 532
521 if (!msg_isdata(msg)) 533 if (!msg_isdata(msg))
522 return false; 534 return false;
@@ -529,15 +541,15 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb,
529 return false; 541 return false;
530 if (msg_reroute_cnt(msg)) 542 if (msg_reroute_cnt(msg))
531 return false; 543 return false;
532 *dnode = addr_domain(net, msg_lookup_scope(msg)); 544 dnode = addr_domain(net, msg_lookup_scope(msg));
533 dport = tipc_nametbl_translate(net, msg_nametype(msg), 545 dport = tipc_nametbl_translate(net, msg_nametype(msg),
534 msg_nameinst(msg), dnode); 546 msg_nameinst(msg), &dnode);
535 if (!dport) 547 if (!dport)
536 return false; 548 return false;
537 msg_incr_reroute_cnt(msg); 549 msg_incr_reroute_cnt(msg);
538 if (*dnode != own_addr) 550 if (dnode != onode)
539 msg_set_prevnode(msg, own_addr); 551 msg_set_prevnode(msg, onode);
540 msg_set_destnode(msg, *dnode); 552 msg_set_destnode(msg, dnode);
541 msg_set_destport(msg, dport); 553 msg_set_destport(msg, dport);
542 *err = TIPC_OK; 554 *err = TIPC_OK;
543 return true; 555 return true;