aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c32
1 files changed, 14 insertions, 18 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 4a4dcbe4f8b..e677937a07f 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -602,31 +602,33 @@ out:
602} 602}
603 603
604static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, 604static 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
894back_from_confirm: 890back_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,