@@ -499,61 +499,79 @@ bool tipc_msg_make_bundle(struct sk_buff **skb, struct tipc_msg *msg,
499
499
/**
500
500
* tipc_msg_reverse(): swap source and destination addresses and add error code
501
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
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
505
* Returns true if success, otherwise false
506
506
*/
507
507
bool tipc_msg_reverse (u32 own_node , struct sk_buff * * skb , int err )
508
508
{
509
509
struct sk_buff * _skb = * skb ;
510
- struct tipc_msg * hdr ;
511
- struct tipc_msg ohdr ;
512
- int dlen ;
510
+ struct tipc_msg * _hdr , * hdr ;
511
+ int hlen , dlen ;
513
512
514
513
if (skb_linearize (_skb ))
515
514
goto exit ;
516
- hdr = buf_msg (_skb );
517
- dlen = min_t (uint , msg_data_sz (hdr ), MAX_FORWARD_SIZE );
518
- if (msg_dest_droppable (hdr ))
515
+ _hdr = buf_msg (_skb );
516
+ dlen = min_t (uint , msg_data_sz (_hdr ), MAX_FORWARD_SIZE );
517
+ hlen = msg_hdr_sz (_hdr );
518
+
519
+ if (msg_dest_droppable (_hdr ))
519
520
goto exit ;
520
- if (msg_errcode (hdr ))
521
+ if (msg_errcode (_hdr ))
521
522
goto exit ;
522
523
523
- /* Take a copy of original header before altering message */
524
- memcpy (& ohdr , hdr , msg_hdr_sz (hdr ));
525
-
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
- }
524
+ /* Never return SHORT header */
525
+ if (hlen == SHORT_H_SIZE )
526
+ hlen = BASIC_H_SIZE ;
527
+
528
+ /* Don't return data along with SYN+, - sender has a clone */
529
+ if (msg_is_syn (_hdr ) && err == TIPC_ERR_OVERLOAD )
530
+ dlen = 0 ;
531
+
532
+ /* Allocate new buffer to return */
533
+ * skb = tipc_buf_acquire (hlen + dlen , GFP_ATOMIC );
534
+ if (!* skb )
535
+ goto exit ;
536
+ memcpy ((* skb )-> data , _skb -> data , msg_hdr_sz (_hdr ));
537
+ memcpy ((* skb )-> data + hlen , msg_data (_hdr ), dlen );
538
538
539
- /* Now reverse the concerned fields */
539
+ /* Build reverse header in new buffer */
540
+ hdr = buf_msg (* skb );
541
+ msg_set_hdr_sz (hdr , hlen );
540
542
msg_set_errcode (hdr , err );
541
543
msg_set_non_seq (hdr , 0 );
542
- msg_set_origport (hdr , msg_destport (& ohdr ));
543
- msg_set_destport (hdr , msg_origport (& ohdr ));
544
- msg_set_destnode (hdr , msg_prevnode (& ohdr ));
544
+ msg_set_origport (hdr , msg_destport (_hdr ));
545
+ msg_set_destport (hdr , msg_origport (_hdr ));
546
+ msg_set_destnode (hdr , msg_prevnode (_hdr ));
545
547
msg_set_prevnode (hdr , own_node );
546
548
msg_set_orignode (hdr , own_node );
547
- msg_set_size (hdr , msg_hdr_sz (hdr ) + dlen );
548
- skb_trim (_skb , msg_size (hdr ));
549
+ msg_set_size (hdr , hlen + dlen );
549
550
skb_orphan (_skb );
551
+ kfree_skb (_skb );
550
552
return true;
551
553
exit :
552
554
kfree_skb (_skb );
553
555
* skb = NULL ;
554
556
return false;
555
557
}
556
558
559
+ bool tipc_msg_skb_clone (struct sk_buff_head * msg , struct sk_buff_head * cpy )
560
+ {
561
+ struct sk_buff * skb , * _skb ;
562
+
563
+ skb_queue_walk (msg , skb ) {
564
+ _skb = skb_clone (skb , GFP_ATOMIC );
565
+ if (!_skb ) {
566
+ __skb_queue_purge (cpy );
567
+ pr_err_ratelimited ("Failed to clone buffer chain\n" );
568
+ return false;
569
+ }
570
+ __skb_queue_tail (cpy , _skb );
571
+ }
572
+ return true;
573
+ }
574
+
557
575
/**
558
576
* tipc_msg_lookup_dest(): try to find new destination for named message
559
577
* @skb: the buffer containing the message.
0 commit comments