@@ -1135,6 +1135,74 @@ static void ip6_append_data_mtu(unsigned int *mtu,
11351135 }
11361136}
11371137
1138+ static int ip6_setup_cork (struct sock * sk , struct inet_cork_full * cork ,
1139+ struct inet6_cork * v6_cork ,
1140+ int hlimit , int tclass , struct ipv6_txoptions * opt ,
1141+ struct rt6_info * rt , struct flowi6 * fl6 )
1142+ {
1143+ struct ipv6_pinfo * np = inet6_sk (sk );
1144+ unsigned int mtu ;
1145+
1146+ /*
1147+ * setup for corking
1148+ */
1149+ if (opt ) {
1150+ if (WARN_ON (v6_cork -> opt ))
1151+ return - EINVAL ;
1152+
1153+ v6_cork -> opt = kzalloc (opt -> tot_len , sk -> sk_allocation );
1154+ if (unlikely (v6_cork -> opt == NULL ))
1155+ return - ENOBUFS ;
1156+
1157+ v6_cork -> opt -> tot_len = opt -> tot_len ;
1158+ v6_cork -> opt -> opt_flen = opt -> opt_flen ;
1159+ v6_cork -> opt -> opt_nflen = opt -> opt_nflen ;
1160+
1161+ v6_cork -> opt -> dst0opt = ip6_opt_dup (opt -> dst0opt ,
1162+ sk -> sk_allocation );
1163+ if (opt -> dst0opt && !v6_cork -> opt -> dst0opt )
1164+ return - ENOBUFS ;
1165+
1166+ v6_cork -> opt -> dst1opt = ip6_opt_dup (opt -> dst1opt ,
1167+ sk -> sk_allocation );
1168+ if (opt -> dst1opt && !v6_cork -> opt -> dst1opt )
1169+ return - ENOBUFS ;
1170+
1171+ v6_cork -> opt -> hopopt = ip6_opt_dup (opt -> hopopt ,
1172+ sk -> sk_allocation );
1173+ if (opt -> hopopt && !v6_cork -> opt -> hopopt )
1174+ return - ENOBUFS ;
1175+
1176+ v6_cork -> opt -> srcrt = ip6_rthdr_dup (opt -> srcrt ,
1177+ sk -> sk_allocation );
1178+ if (opt -> srcrt && !v6_cork -> opt -> srcrt )
1179+ return - ENOBUFS ;
1180+
1181+ /* need source address above miyazawa*/
1182+ }
1183+ dst_hold (& rt -> dst );
1184+ cork -> base .dst = & rt -> dst ;
1185+ cork -> fl .u .ip6 = * fl6 ;
1186+ v6_cork -> hop_limit = hlimit ;
1187+ v6_cork -> tclass = tclass ;
1188+ if (rt -> dst .flags & DST_XFRM_TUNNEL )
1189+ mtu = np -> pmtudisc >= IPV6_PMTUDISC_PROBE ?
1190+ rt -> dst .dev -> mtu : dst_mtu (& rt -> dst );
1191+ else
1192+ mtu = np -> pmtudisc >= IPV6_PMTUDISC_PROBE ?
1193+ rt -> dst .dev -> mtu : dst_mtu (rt -> dst .path );
1194+ if (np -> frag_size < mtu ) {
1195+ if (np -> frag_size )
1196+ mtu = np -> frag_size ;
1197+ }
1198+ cork -> base .fragsize = mtu ;
1199+ if (dst_allfrag (rt -> dst .path ))
1200+ cork -> base .flags |= IPCORK_ALLFRAG ;
1201+ cork -> base .length = 0 ;
1202+
1203+ return 0 ;
1204+ }
1205+
11381206int ip6_append_data (struct sock * sk , int getfrag (void * from , char * to ,
11391207 int offset , int len , int odd , struct sk_buff * skb ),
11401208 void * from , int length , int transhdrlen ,
@@ -1162,59 +1230,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
11621230 /*
11631231 * setup for corking
11641232 */
1165- if (opt ) {
1166- if (WARN_ON (np -> cork .opt ))
1167- return - EINVAL ;
1168-
1169- np -> cork .opt = kzalloc (opt -> tot_len , sk -> sk_allocation );
1170- if (unlikely (np -> cork .opt == NULL ))
1171- return - ENOBUFS ;
1172-
1173- np -> cork .opt -> tot_len = opt -> tot_len ;
1174- np -> cork .opt -> opt_flen = opt -> opt_flen ;
1175- np -> cork .opt -> opt_nflen = opt -> opt_nflen ;
1176-
1177- np -> cork .opt -> dst0opt = ip6_opt_dup (opt -> dst0opt ,
1178- sk -> sk_allocation );
1179- if (opt -> dst0opt && !np -> cork .opt -> dst0opt )
1180- return - ENOBUFS ;
1181-
1182- np -> cork .opt -> dst1opt = ip6_opt_dup (opt -> dst1opt ,
1183- sk -> sk_allocation );
1184- if (opt -> dst1opt && !np -> cork .opt -> dst1opt )
1185- return - ENOBUFS ;
1186-
1187- np -> cork .opt -> hopopt = ip6_opt_dup (opt -> hopopt ,
1188- sk -> sk_allocation );
1189- if (opt -> hopopt && !np -> cork .opt -> hopopt )
1190- return - ENOBUFS ;
1191-
1192- np -> cork .opt -> srcrt = ip6_rthdr_dup (opt -> srcrt ,
1193- sk -> sk_allocation );
1194- if (opt -> srcrt && !np -> cork .opt -> srcrt )
1195- return - ENOBUFS ;
1196-
1197- /* need source address above miyazawa*/
1198- }
1199- dst_hold (& rt -> dst );
1200- cork -> dst = & rt -> dst ;
1201- inet -> cork .fl .u .ip6 = * fl6 ;
1202- np -> cork .hop_limit = hlimit ;
1203- np -> cork .tclass = tclass ;
1204- if (rt -> dst .flags & DST_XFRM_TUNNEL )
1205- mtu = np -> pmtudisc >= IPV6_PMTUDISC_PROBE ?
1206- rt -> dst .dev -> mtu : dst_mtu (& rt -> dst );
1207- else
1208- mtu = np -> pmtudisc >= IPV6_PMTUDISC_PROBE ?
1209- rt -> dst .dev -> mtu : dst_mtu (rt -> dst .path );
1210- if (np -> frag_size < mtu ) {
1211- if (np -> frag_size )
1212- mtu = np -> frag_size ;
1213- }
1214- cork -> fragsize = mtu ;
1215- if (dst_allfrag (rt -> dst .path ))
1216- cork -> flags |= IPCORK_ALLFRAG ;
1217- cork -> length = 0 ;
1233+ err = ip6_setup_cork (sk , & inet -> cork , & np -> cork , hlimit ,
1234+ tclass , opt , rt , fl6 );
1235+ if (err )
1236+ return err ;
12181237 exthdrlen = (opt ? opt -> opt_flen : 0 );
12191238 length += exthdrlen ;
12201239 transhdrlen += exthdrlen ;
@@ -1226,8 +1245,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
12261245 transhdrlen = 0 ;
12271246 exthdrlen = 0 ;
12281247 dst_exthdrlen = 0 ;
1229- mtu = cork -> fragsize ;
12301248 }
1249+ mtu = cork -> fragsize ;
12311250 orig_mtu = mtu ;
12321251
12331252 hh_len = LL_RESERVED_SPACE (rt -> dst .dev );
@@ -1503,23 +1522,24 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
15031522}
15041523EXPORT_SYMBOL_GPL (ip6_append_data );
15051524
1506- static void ip6_cork_release (struct inet_sock * inet , struct ipv6_pinfo * np )
1525+ static void ip6_cork_release (struct inet_cork_full * cork ,
1526+ struct inet6_cork * v6_cork )
15071527{
1508- if (np -> cork . opt ) {
1509- kfree (np -> cork . opt -> dst0opt );
1510- kfree (np -> cork . opt -> dst1opt );
1511- kfree (np -> cork . opt -> hopopt );
1512- kfree (np -> cork . opt -> srcrt );
1513- kfree (np -> cork . opt );
1514- np -> cork . opt = NULL ;
1528+ if (v6_cork -> opt ) {
1529+ kfree (v6_cork -> opt -> dst0opt );
1530+ kfree (v6_cork -> opt -> dst1opt );
1531+ kfree (v6_cork -> opt -> hopopt );
1532+ kfree (v6_cork -> opt -> srcrt );
1533+ kfree (v6_cork -> opt );
1534+ v6_cork -> opt = NULL ;
15151535 }
15161536
1517- if (inet -> cork . base .dst ) {
1518- dst_release (inet -> cork . base .dst );
1519- inet -> cork . base .dst = NULL ;
1520- inet -> cork . base .flags &= ~IPCORK_ALLFRAG ;
1537+ if (cork -> base .dst ) {
1538+ dst_release (cork -> base .dst );
1539+ cork -> base .dst = NULL ;
1540+ cork -> base .flags &= ~IPCORK_ALLFRAG ;
15211541 }
1522- memset (& inet -> cork . fl , 0 , sizeof (inet -> cork . fl ));
1542+ memset (& cork -> fl , 0 , sizeof (cork -> fl ));
15231543}
15241544
15251545int ip6_push_pending_frames (struct sock * sk )
@@ -1599,7 +1619,7 @@ int ip6_push_pending_frames(struct sock *sk)
15991619 }
16001620
16011621out :
1602- ip6_cork_release (inet , np );
1622+ ip6_cork_release (& inet -> cork , & np -> cork );
16031623 return err ;
16041624error :
16051625 IP6_INC_STATS (net , rt -> rt6i_idev , IPSTATS_MIB_OUTDISCARDS );
@@ -1618,6 +1638,6 @@ void ip6_flush_pending_frames(struct sock *sk)
16181638 kfree_skb (skb );
16191639 }
16201640
1621- ip6_cork_release (inet_sk (sk ), inet6_sk (sk ));
1641+ ip6_cork_release (& inet_sk (sk )-> cork , & inet6_sk (sk )-> cork );
16221642}
16231643EXPORT_SYMBOL_GPL (ip6_flush_pending_frames );
0 commit comments