summaryrefslogtreecommitdiffstats
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c79
1 files changed, 39 insertions, 40 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d061465d6827..259f1b231038 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -524,7 +524,7 @@ csum_copy_err:
524 goto out; 524 goto out;
525} 525}
526 526
527static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, 527static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
528 struct raw6_sock *rp) 528 struct raw6_sock *rp)
529{ 529{
530 struct sk_buff *skb; 530 struct sk_buff *skb;
@@ -586,11 +586,10 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
586 if (unlikely(csum)) 586 if (unlikely(csum))
587 tmp_csum = csum_sub(tmp_csum, csum_unfold(csum)); 587 tmp_csum = csum_sub(tmp_csum, csum_unfold(csum));
588 588
589 csum = csum_ipv6_magic(&fl->fl6_src, 589 csum = csum_ipv6_magic(&fl6->saddr, &fl6->daddr,
590 &fl->fl6_dst, 590 total_len, fl6->flowi6_proto, tmp_csum);
591 total_len, fl->flowi_proto, tmp_csum);
592 591
593 if (csum == 0 && fl->flowi_proto == IPPROTO_UDP) 592 if (csum == 0 && fl6->flowi6_proto == IPPROTO_UDP)
594 csum = CSUM_MANGLED_0; 593 csum = CSUM_MANGLED_0;
595 594
596 if (skb_store_bits(skb, offset, &csum, 2)) 595 if (skb_store_bits(skb, offset, &csum, 2))
@@ -603,7 +602,7 @@ out:
603} 602}
604 603
605static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, 604static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
606 struct flowi *fl, struct dst_entry **dstp, 605 struct flowi6 *fl6, struct dst_entry **dstp,
607 unsigned int flags) 606 unsigned int flags)
608{ 607{
609 struct ipv6_pinfo *np = inet6_sk(sk); 608 struct ipv6_pinfo *np = inet6_sk(sk);
@@ -613,7 +612,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
613 struct rt6_info *rt = (struct rt6_info *)*dstp; 612 struct rt6_info *rt = (struct rt6_info *)*dstp;
614 613
615 if (length > rt->dst.dev->mtu) { 614 if (length > rt->dst.dev->mtu) {
616 ipv6_local_error(sk, EMSGSIZE, fl, rt->dst.dev->mtu); 615 ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu);
617 return -EMSGSIZE; 616 return -EMSGSIZE;
618 } 617 }
619 if (flags&MSG_PROBE) 618 if (flags&MSG_PROBE)
@@ -662,7 +661,7 @@ error:
662 return err; 661 return err;
663} 662}
664 663
665static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) 664static int rawv6_probe_proto_opt(struct flowi6 *fl6, struct msghdr *msg)
666{ 665{
667 struct iovec *iov; 666 struct iovec *iov;
668 u8 __user *type = NULL; 667 u8 __user *type = NULL;
@@ -679,7 +678,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
679 if (!iov) 678 if (!iov)
680 continue; 679 continue;
681 680
682 switch (fl->flowi_proto) { 681 switch (fl6->flowi6_proto) {
683 case IPPROTO_ICMPV6: 682 case IPPROTO_ICMPV6:
684 /* check if one-byte field is readable or not. */ 683 /* check if one-byte field is readable or not. */
685 if (iov->iov_base && iov->iov_len < 1) 684 if (iov->iov_base && iov->iov_len < 1)
@@ -694,8 +693,8 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
694 code = iov->iov_base; 693 code = iov->iov_base;
695 694
696 if (type && code) { 695 if (type && code) {
697 if (get_user(fl->fl6_icmp_type, type) || 696 if (get_user(fl6->uli.icmpt.type, type) ||
698 get_user(fl->fl6_icmp_code, code)) 697 get_user(fl6->uli.icmpt.code, code))
699 return -EFAULT; 698 return -EFAULT;
700 probed = 1; 699 probed = 1;
701 } 700 }
@@ -706,7 +705,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
706 /* check if type field is readable or not. */ 705 /* check if type field is readable or not. */
707 if (iov->iov_len > 2 - len) { 706 if (iov->iov_len > 2 - len) {
708 u8 __user *p = iov->iov_base; 707 u8 __user *p = iov->iov_base;
709 if (get_user(fl->fl6_mh_type, &p[2 - len])) 708 if (get_user(fl6->uli.mht.type, &p[2 - len]))
710 return -EFAULT; 709 return -EFAULT;
711 probed = 1; 710 probed = 1;
712 } else 711 } else
@@ -735,7 +734,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
735 struct ipv6_txoptions *opt = NULL; 734 struct ipv6_txoptions *opt = NULL;
736 struct ip6_flowlabel *flowlabel = NULL; 735 struct ip6_flowlabel *flowlabel = NULL;
737 struct dst_entry *dst = NULL; 736 struct dst_entry *dst = NULL;
738 struct flowi fl; 737 struct flowi6 fl6;
739 int addr_len = msg->msg_namelen; 738 int addr_len = msg->msg_namelen;
740 int hlimit = -1; 739 int hlimit = -1;
741 int tclass = -1; 740 int tclass = -1;
@@ -756,9 +755,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
756 /* 755 /*
757 * Get and verify the address. 756 * Get and verify the address.
758 */ 757 */
759 memset(&fl, 0, sizeof(fl)); 758 memset(&fl6, 0, sizeof(fl6));
760 759
761 fl.flowi_mark = sk->sk_mark; 760 fl6.flowi6_mark = sk->sk_mark;
762 761
763 if (sin6) { 762 if (sin6) {
764 if (addr_len < SIN6_LEN_RFC2133) 763 if (addr_len < SIN6_LEN_RFC2133)
@@ -780,9 +779,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
780 779
781 daddr = &sin6->sin6_addr; 780 daddr = &sin6->sin6_addr;
782 if (np->sndflow) { 781 if (np->sndflow) {
783 fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; 782 fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
784 if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { 783 if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
785 flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); 784 flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
786 if (flowlabel == NULL) 785 if (flowlabel == NULL)
787 return -EINVAL; 786 return -EINVAL;
788 daddr = &flowlabel->dst; 787 daddr = &flowlabel->dst;
@@ -800,32 +799,32 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
800 if (addr_len >= sizeof(struct sockaddr_in6) && 799 if (addr_len >= sizeof(struct sockaddr_in6) &&
801 sin6->sin6_scope_id && 800 sin6->sin6_scope_id &&
802 ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) 801 ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)
803 fl.flowi_oif = sin6->sin6_scope_id; 802 fl6.flowi6_oif = sin6->sin6_scope_id;
804 } else { 803 } else {
805 if (sk->sk_state != TCP_ESTABLISHED) 804 if (sk->sk_state != TCP_ESTABLISHED)
806 return -EDESTADDRREQ; 805 return -EDESTADDRREQ;
807 806
808 proto = inet->inet_num; 807 proto = inet->inet_num;
809 daddr = &np->daddr; 808 daddr = &np->daddr;
810 fl.fl6_flowlabel = np->flow_label; 809 fl6.flowlabel = np->flow_label;
811 } 810 }
812 811
813 if (fl.flowi_oif == 0) 812 if (fl6.flowi6_oif == 0)
814 fl.flowi_oif = sk->sk_bound_dev_if; 813 fl6.flowi6_oif = sk->sk_bound_dev_if;
815 814
816 if (msg->msg_controllen) { 815 if (msg->msg_controllen) {
817 opt = &opt_space; 816 opt = &opt_space;
818 memset(opt, 0, sizeof(struct ipv6_txoptions)); 817 memset(opt, 0, sizeof(struct ipv6_txoptions));
819 opt->tot_len = sizeof(struct ipv6_txoptions); 818 opt->tot_len = sizeof(struct ipv6_txoptions);
820 819
821 err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, 820 err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit,
822 &tclass, &dontfrag); 821 &tclass, &dontfrag);
823 if (err < 0) { 822 if (err < 0) {
824 fl6_sock_release(flowlabel); 823 fl6_sock_release(flowlabel);
825 return err; 824 return err;
826 } 825 }
827 if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { 826 if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
828 flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); 827 flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
829 if (flowlabel == NULL) 828 if (flowlabel == NULL)
830 return -EINVAL; 829 return -EINVAL;
831 } 830 }
@@ -838,31 +837,31 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
838 opt = fl6_merge_options(&opt_space, flowlabel, opt); 837 opt = fl6_merge_options(&opt_space, flowlabel, opt);
839 opt = ipv6_fixup_options(&opt_space, opt); 838 opt = ipv6_fixup_options(&opt_space, opt);
840 839
841 fl.flowi_proto = proto; 840 fl6.flowi6_proto = proto;
842 err = rawv6_probe_proto_opt(&fl, msg); 841 err = rawv6_probe_proto_opt(&fl6, msg);
843 if (err) 842 if (err)
844 goto out; 843 goto out;
845 844
846 if (!ipv6_addr_any(daddr)) 845 if (!ipv6_addr_any(daddr))
847 ipv6_addr_copy(&fl.fl6_dst, daddr); 846 ipv6_addr_copy(&fl6.daddr, daddr);
848 else 847 else
849 fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ 848 fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
850 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) 849 if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
851 ipv6_addr_copy(&fl.fl6_src, &np->saddr); 850 ipv6_addr_copy(&fl6.saddr, &np->saddr);
852 851
853 final_p = fl6_update_dst(&fl, opt, &final); 852 final_p = fl6_update_dst(&fl6, opt, &final);
854 853
855 if (!fl.flowi_oif && ipv6_addr_is_multicast(&fl.fl6_dst)) 854 if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
856 fl.flowi_oif = np->mcast_oif; 855 fl6.flowi6_oif = np->mcast_oif;
857 security_sk_classify_flow(sk, &fl); 856 security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
858 857
859 dst = ip6_dst_lookup_flow(sk, &fl, final_p, true); 858 dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
860 if (IS_ERR(dst)) { 859 if (IS_ERR(dst)) {
861 err = PTR_ERR(dst); 860 err = PTR_ERR(dst);
862 goto out; 861 goto out;
863 } 862 }
864 if (hlimit < 0) { 863 if (hlimit < 0) {
865 if (ipv6_addr_is_multicast(&fl.fl6_dst)) 864 if (ipv6_addr_is_multicast(&fl6.daddr))
866 hlimit = np->mcast_hops; 865 hlimit = np->mcast_hops;
867 else 866 else
868 hlimit = np->hop_limit; 867 hlimit = np->hop_limit;
@@ -881,17 +880,17 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
881 880
882back_from_confirm: 881back_from_confirm:
883 if (inet->hdrincl) 882 if (inet->hdrincl)
884 err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, &dst, msg->msg_flags); 883 err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl6, &dst, msg->msg_flags);
885 else { 884 else {
886 lock_sock(sk); 885 lock_sock(sk);
887 err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, 886 err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov,
888 len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, 887 len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info*)dst,
889 msg->msg_flags, dontfrag); 888 msg->msg_flags, dontfrag);
890 889
891 if (err) 890 if (err)
892 ip6_flush_pending_frames(sk); 891 ip6_flush_pending_frames(sk);
893 else if (!(msg->msg_flags & MSG_MORE)) 892 else if (!(msg->msg_flags & MSG_MORE))
894 err = rawv6_push_pending_frames(sk, &fl, rp); 893 err = rawv6_push_pending_frames(sk, &fl6, rp);
895 release_sock(sk); 894 release_sock(sk);
896 } 895 }
897done: 896done: