int ip6_output(struct sk_buff *skb)
{
- if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) ||
+ if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) ||
dst_allfrag(skb->dst))
return ip6_fragment(skb, ip6_output2);
else
int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
struct ipv6_txoptions *opt, int ipfragok)
{
- struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_pinfo *np = sk ? inet6_sk(sk) : NULL;
struct in6_addr *first_hop = &fl->fl6_dst;
struct dst_entry *dst = skb->dst;
struct ipv6hdr *hdr;
if (*dst) {
struct rt6_info *rt = (struct rt6_info*)*dst;
- /* Yes, checking route validity in not connected
- * case is not very simple. Take into account,
- * that we do not support routing by source, TOS,
- * and MSG_DONTROUTE --ANK (980726)
- *
- * 1. If route was host route, check that
- * cached destination is current.
- * If it is network route, we still may
- * check its validity using saved pointer
- * to the last used address: daddr_cache.
- * We do not want to save whole address now,
- * (because main consumer of this service
- * is tcp, which has not this problem),
- * so that the last trick works only on connected
- * sockets.
- * 2. oif also should be the same.
- */
+ /* Yes, checking route validity in not connected
+ case is not very simple. Take into account,
+ that we do not support routing by source, TOS,
+ and MSG_DONTROUTE --ANK (980726)
+
+ 1. If route was host route, check that
+ cached destination is current.
+ If it is network route, we still may
+ check its validity using saved pointer
+ to the last used address: daddr_cache.
+ We do not want to save whole address now,
+ (because main consumer of this service
+ is tcp, which has not this problem),
+ so that the last trick works only on connected
+ sockets.
+ 2. oif also should be the same.
+ */
+
if (((rt->rt6i_dst.plen != 128 ||
- !ipv6_addr_equal(&fl->fl6_dst,
- &rt->rt6i_dst.addr))
+ !ipv6_addr_equal(&fl->fl6_dst, &rt->rt6i_dst.addr))
&& (np->daddr_cache == NULL ||
- !ipv6_addr_equal(&fl->fl6_dst,
- np->daddr_cache)))
+ !ipv6_addr_equal(&fl->fl6_dst, np->daddr_cache)))
|| (fl->oif && fl->oif != (*dst)->dev->ifindex)) {
dst_release(*dst);
*dst = NULL;
struct frag_hdr fhdr;
/* specify the length of each IP datagram fragment*/
- skb_shinfo(skb)->gso_size = mtu - fragheaderlen -
- sizeof(struct frag_hdr);
- skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
+ skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) -
+ sizeof(struct frag_hdr);
ipv6_select_ident(skb, &fhdr);
skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
__skb_queue_tail(&sk->sk_write_queue, skb);
np->cork.hop_limit = hlimit;
np->cork.tclass = tclass;
mtu = dst_mtu(rt->u.dst.path);
- if (np->frag_size < mtu) {
+ if (np && np->frag_size < mtu) {
if (np->frag_size)
mtu = np->frag_size;
}
skb_prev->csum = csum_sub(skb_prev->csum,
skb->csum);
data += fraggap;
- pskb_trim_unique(skb_prev, maxfraglen);
+ skb_trim(skb_prev, maxfraglen);
}
copy = datalen - transhdrlen - fraggap;
if (copy < 0) {