@@ -1564,30 +1564,31 @@ static void ip6_cork_release(struct inet_cork_full *cork,
15641564 memset (& cork -> fl , 0 , sizeof (cork -> fl ));
15651565}
15661566
1567- int ip6_push_pending_frames (struct sock * sk )
1567+ struct sk_buff * __ip6_make_skb (struct sock * sk ,
1568+ struct sk_buff_head * queue ,
1569+ struct inet_cork_full * cork ,
1570+ struct inet6_cork * v6_cork )
15681571{
15691572 struct sk_buff * skb , * tmp_skb ;
15701573 struct sk_buff * * tail_skb ;
15711574 struct in6_addr final_dst_buf , * final_dst = & final_dst_buf ;
1572- struct inet_sock * inet = inet_sk (sk );
15731575 struct ipv6_pinfo * np = inet6_sk (sk );
15741576 struct net * net = sock_net (sk );
15751577 struct ipv6hdr * hdr ;
1576- struct ipv6_txoptions * opt = np -> cork . opt ;
1577- struct rt6_info * rt = (struct rt6_info * )inet -> cork . base .dst ;
1578- struct flowi6 * fl6 = & inet -> cork . fl .u .ip6 ;
1578+ struct ipv6_txoptions * opt = v6_cork -> opt ;
1579+ struct rt6_info * rt = (struct rt6_info * )cork -> base .dst ;
1580+ struct flowi6 * fl6 = & cork -> fl .u .ip6 ;
15791581 unsigned char proto = fl6 -> flowi6_proto ;
1580- int err = 0 ;
15811582
1582- skb = __skb_dequeue (& sk -> sk_write_queue );
1583+ skb = __skb_dequeue (queue );
15831584 if (skb == NULL )
15841585 goto out ;
15851586 tail_skb = & (skb_shinfo (skb )-> frag_list );
15861587
15871588 /* move skb->data to ip header from ext header */
15881589 if (skb -> data < skb_network_header (skb ))
15891590 __skb_pull (skb , skb_network_offset (skb ));
1590- while ((tmp_skb = __skb_dequeue (& sk -> sk_write_queue )) != NULL ) {
1591+ while ((tmp_skb = __skb_dequeue (queue )) != NULL ) {
15911592 __skb_pull (tmp_skb , skb_network_header_len (skb ));
15921593 * tail_skb = tmp_skb ;
15931594 tail_skb = & (tmp_skb -> next );
@@ -1612,10 +1613,10 @@ int ip6_push_pending_frames(struct sock *sk)
16121613 skb_reset_network_header (skb );
16131614 hdr = ipv6_hdr (skb );
16141615
1615- ip6_flow_hdr (hdr , np -> cork . tclass ,
1616+ ip6_flow_hdr (hdr , v6_cork -> tclass ,
16161617 ip6_make_flowlabel (net , skb , fl6 -> flowlabel ,
16171618 np -> autoflowlabel ));
1618- hdr -> hop_limit = np -> cork . hop_limit ;
1619+ hdr -> hop_limit = v6_cork -> hop_limit ;
16191620 hdr -> nexthdr = proto ;
16201621 hdr -> saddr = fl6 -> saddr ;
16211622 hdr -> daddr = * final_dst ;
@@ -1632,25 +1633,45 @@ int ip6_push_pending_frames(struct sock *sk)
16321633 ICMP6_INC_STATS (net , idev , ICMP6_MIB_OUTMSGS );
16331634 }
16341635
1636+ ip6_cork_release (cork , v6_cork );
1637+ out :
1638+ return skb ;
1639+ }
1640+
1641+ int ip6_send_skb (struct sk_buff * skb )
1642+ {
1643+ struct net * net = sock_net (skb -> sk );
1644+ struct rt6_info * rt = (struct rt6_info * )skb_dst (skb );
1645+ int err ;
1646+
16351647 err = ip6_local_out (skb );
16361648 if (err ) {
16371649 if (err > 0 )
16381650 err = net_xmit_errno (err );
16391651 if (err )
1640- goto error ;
1652+ IP6_INC_STATS (net , rt -> rt6i_idev ,
1653+ IPSTATS_MIB_OUTDISCARDS );
16411654 }
16421655
1643- out :
1644- ip6_cork_release (& inet -> cork , & np -> cork );
16451656 return err ;
1646- error :
1647- IP6_INC_STATS (net , rt -> rt6i_idev , IPSTATS_MIB_OUTDISCARDS );
1648- goto out ;
1657+ }
1658+
1659+ int ip6_push_pending_frames (struct sock * sk )
1660+ {
1661+ struct sk_buff * skb ;
1662+
1663+ skb = ip6_finish_skb (sk );
1664+ if (!skb )
1665+ return 0 ;
1666+
1667+ return ip6_send_skb (skb );
16491668}
16501669EXPORT_SYMBOL_GPL (ip6_push_pending_frames );
16511670
16521671static void __ip6_flush_pending_frames (struct sock * sk ,
1653- struct sk_buff_head * queue )
1672+ struct sk_buff_head * queue ,
1673+ struct inet_cork_full * cork ,
1674+ struct inet6_cork * v6_cork )
16541675{
16551676 struct sk_buff * skb ;
16561677
@@ -1661,11 +1682,55 @@ static void __ip6_flush_pending_frames(struct sock *sk,
16611682 kfree_skb (skb );
16621683 }
16631684
1664- ip6_cork_release (& inet_sk ( sk ) -> cork , & inet6_sk ( sk ) -> cork );
1685+ ip6_cork_release (cork , v6_cork );
16651686}
16661687
16671688void ip6_flush_pending_frames (struct sock * sk )
16681689{
1669- __ip6_flush_pending_frames (sk , & sk -> sk_write_queue );
1690+ __ip6_flush_pending_frames (sk , & sk -> sk_write_queue ,
1691+ & inet_sk (sk )-> cork , & inet6_sk (sk )-> cork );
16701692}
16711693EXPORT_SYMBOL_GPL (ip6_flush_pending_frames );
1694+
1695+ struct sk_buff * ip6_make_skb (struct sock * sk ,
1696+ int getfrag (void * from , char * to , int offset ,
1697+ int len , int odd , struct sk_buff * skb ),
1698+ void * from , int length , int transhdrlen ,
1699+ int hlimit , int tclass ,
1700+ struct ipv6_txoptions * opt , struct flowi6 * fl6 ,
1701+ struct rt6_info * rt , unsigned int flags ,
1702+ int dontfrag )
1703+ {
1704+ struct inet_cork_full cork ;
1705+ struct inet6_cork v6_cork ;
1706+ struct sk_buff_head queue ;
1707+ int exthdrlen = (opt ? opt -> opt_flen : 0 );
1708+ int err ;
1709+
1710+ if (flags & MSG_PROBE )
1711+ return NULL ;
1712+
1713+ __skb_queue_head_init (& queue );
1714+
1715+ cork .base .flags = 0 ;
1716+ cork .base .addr = 0 ;
1717+ cork .base .opt = NULL ;
1718+ v6_cork .opt = NULL ;
1719+ err = ip6_setup_cork (sk , & cork , & v6_cork , hlimit , tclass , opt , rt , fl6 );
1720+ if (err )
1721+ return ERR_PTR (err );
1722+
1723+ if (dontfrag < 0 )
1724+ dontfrag = inet6_sk (sk )-> dontfrag ;
1725+
1726+ err = __ip6_append_data (sk , fl6 , & queue , & cork .base , & v6_cork ,
1727+ & current -> task_frag , getfrag , from ,
1728+ length + exthdrlen , transhdrlen + exthdrlen ,
1729+ flags , dontfrag );
1730+ if (err ) {
1731+ __ip6_flush_pending_frames (sk , & queue , & cork , & v6_cork );
1732+ return ERR_PTR (err );
1733+ }
1734+
1735+ return __ip6_make_skb (sk , & queue , & cork , & v6_cork );
1736+ }
0 commit comments