diff options
Diffstat (limited to 'net/ipv6/raw.c')
| -rw-r--r-- | net/ipv6/raw.c | 32 | 
1 files changed, 14 insertions, 18 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4a4dcbe4f8b2..e677937a07fc 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c  | |||
| @@ -602,31 +602,33 @@ out: | |||
| 602 | } | 602 | } | 
| 603 | 603 | ||
| 604 | static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | 604 | static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | 
| 605 | struct flowi *fl, struct rt6_info *rt, | 605 | struct flowi *fl, struct dst_entry **dstp, | 
| 606 | unsigned int flags) | 606 | unsigned int flags) | 
| 607 | { | 607 | { | 
| 608 | struct ipv6_pinfo *np = inet6_sk(sk); | 608 | struct ipv6_pinfo *np = inet6_sk(sk); | 
| 609 | struct ipv6hdr *iph; | 609 | struct ipv6hdr *iph; | 
| 610 | struct sk_buff *skb; | 610 | struct sk_buff *skb; | 
| 611 | int err; | 611 | int err; | 
| 612 | struct rt6_info *rt = (struct rt6_info *)*dstp; | ||
| 612 | 613 | ||
| 613 | if (length > rt->u.dst.dev->mtu) { | 614 | if (length > rt->dst.dev->mtu) { | 
| 614 | ipv6_local_error(sk, EMSGSIZE, fl, rt->u.dst.dev->mtu); | 615 | ipv6_local_error(sk, EMSGSIZE, fl, rt->dst.dev->mtu); | 
| 615 | return -EMSGSIZE; | 616 | return -EMSGSIZE; | 
| 616 | } | 617 | } | 
| 617 | if (flags&MSG_PROBE) | 618 | if (flags&MSG_PROBE) | 
| 618 | goto out; | 619 | goto out; | 
| 619 | 620 | ||
| 620 | skb = sock_alloc_send_skb(sk, | 621 | skb = sock_alloc_send_skb(sk, | 
| 621 | length + LL_ALLOCATED_SPACE(rt->u.dst.dev) + 15, | 622 | length + LL_ALLOCATED_SPACE(rt->dst.dev) + 15, | 
| 622 | flags & MSG_DONTWAIT, &err); | 623 | flags & MSG_DONTWAIT, &err); | 
| 623 | if (skb == NULL) | 624 | if (skb == NULL) | 
| 624 | goto error; | 625 | goto error; | 
| 625 | skb_reserve(skb, LL_RESERVED_SPACE(rt->u.dst.dev)); | 626 | skb_reserve(skb, LL_RESERVED_SPACE(rt->dst.dev)); | 
| 626 | 627 | ||
| 627 | skb->priority = sk->sk_priority; | 628 | skb->priority = sk->sk_priority; | 
| 628 | skb->mark = sk->sk_mark; | 629 | skb->mark = sk->sk_mark; | 
| 629 | skb_dst_set(skb, dst_clone(&rt->u.dst)); | 630 | skb_dst_set(skb, &rt->dst); | 
| 631 | *dstp = NULL; | ||
| 630 | 632 | ||
| 631 | skb_put(skb, length); | 633 | skb_put(skb, length); | 
| 632 | skb_reset_network_header(skb); | 634 | skb_reset_network_header(skb); | 
| @@ -641,7 +643,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
| 641 | 643 | ||
| 642 | IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); | 644 | IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); | 
| 643 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, | 645 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, | 
| 644 | rt->u.dst.dev, dst_output); | 646 | rt->dst.dev, dst_output); | 
| 645 | if (err > 0) | 647 | if (err > 0) | 
| 646 | err = net_xmit_errno(err); | 648 | err = net_xmit_errno(err); | 
| 647 | if (err) | 649 | if (err) | 
| @@ -725,7 +727,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 725 | { | 727 | { | 
| 726 | struct ipv6_txoptions opt_space; | 728 | struct ipv6_txoptions opt_space; | 
| 727 | struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; | 729 | struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name; | 
| 728 | struct in6_addr *daddr, *final_p = NULL, final; | 730 | struct in6_addr *daddr, *final_p, final; | 
| 729 | struct inet_sock *inet = inet_sk(sk); | 731 | struct inet_sock *inet = inet_sk(sk); | 
| 730 | struct ipv6_pinfo *np = inet6_sk(sk); | 732 | struct ipv6_pinfo *np = inet6_sk(sk); | 
| 731 | struct raw6_sock *rp = raw6_sk(sk); | 733 | struct raw6_sock *rp = raw6_sk(sk); | 
| @@ -847,13 +849,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 847 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 849 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 
| 848 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 850 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 
| 849 | 851 | ||
| 850 | /* merge ip6_build_xmit from ip6_output */ | 852 | final_p = fl6_update_dst(&fl, opt, &final); | 
| 851 | if (opt && opt->srcrt) { | ||
| 852 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | ||
| 853 | ipv6_addr_copy(&final, &fl.fl6_dst); | ||
| 854 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | ||
| 855 | final_p = &final; | ||
| 856 | } | ||
| 857 | 853 | ||
| 858 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 854 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) | 
| 859 | fl.oif = np->mcast_oif; | 855 | fl.oif = np->mcast_oif; | 
| @@ -892,9 +888,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 892 | goto do_confirm; | 888 | goto do_confirm; | 
| 893 | 889 | ||
| 894 | back_from_confirm: | 890 | back_from_confirm: | 
| 895 | if (inet->hdrincl) { | 891 | if (inet->hdrincl) | 
| 896 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, (struct rt6_info*)dst, msg->msg_flags); | 892 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, &dst, msg->msg_flags); | 
| 897 | } else { | 893 | else { | 
| 898 | lock_sock(sk); | 894 | lock_sock(sk); | 
| 899 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 895 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 
| 900 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, | 896 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, | 
