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.c125
1 files changed, 67 insertions, 58 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 86c39526ba5e..4a1c3b46c56b 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -31,6 +31,7 @@
31#include <linux/netfilter.h> 31#include <linux/netfilter.h>
32#include <linux/netfilter_ipv6.h> 32#include <linux/netfilter_ipv6.h>
33#include <linux/skbuff.h> 33#include <linux/skbuff.h>
34#include <linux/compat.h>
34#include <asm/uaccess.h> 35#include <asm/uaccess.h>
35#include <asm/ioctls.h> 36#include <asm/ioctls.h>
36 37
@@ -123,18 +124,18 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
123} 124}
124 125
125#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 126#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
126static int (*mh_filter)(struct sock *sock, struct sk_buff *skb); 127typedef int mh_filter_t(struct sock *sock, struct sk_buff *skb);
127 128
128int rawv6_mh_filter_register(int (*filter)(struct sock *sock, 129static mh_filter_t __rcu *mh_filter __read_mostly;
129 struct sk_buff *skb)) 130
131int rawv6_mh_filter_register(mh_filter_t filter)
130{ 132{
131 rcu_assign_pointer(mh_filter, filter); 133 rcu_assign_pointer(mh_filter, filter);
132 return 0; 134 return 0;
133} 135}
134EXPORT_SYMBOL(rawv6_mh_filter_register); 136EXPORT_SYMBOL(rawv6_mh_filter_register);
135 137
136int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock, 138int rawv6_mh_filter_unregister(mh_filter_t filter)
137 struct sk_buff *skb))
138{ 139{
139 rcu_assign_pointer(mh_filter, NULL); 140 rcu_assign_pointer(mh_filter, NULL);
140 synchronize_rcu(); 141 synchronize_rcu();
@@ -192,10 +193,10 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
192 * policy is placed in rawv6_rcv() because it is 193 * policy is placed in rawv6_rcv() because it is
193 * required for each socket. 194 * required for each socket.
194 */ 195 */
195 int (*filter)(struct sock *sock, struct sk_buff *skb); 196 mh_filter_t *filter;
196 197
197 filter = rcu_dereference(mh_filter); 198 filter = rcu_dereference(mh_filter);
198 filtered = filter ? filter(sk, skb) : 0; 199 filtered = filter ? (*filter)(sk, skb) : 0;
199 break; 200 break;
200 } 201 }
201#endif 202#endif
@@ -523,7 +524,7 @@ csum_copy_err:
523 goto out; 524 goto out;
524} 525}
525 526
526static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, 527static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
527 struct raw6_sock *rp) 528 struct raw6_sock *rp)
528{ 529{
529 struct sk_buff *skb; 530 struct sk_buff *skb;
@@ -585,11 +586,10 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
585 if (unlikely(csum)) 586 if (unlikely(csum))
586 tmp_csum = csum_sub(tmp_csum, csum_unfold(csum)); 587 tmp_csum = csum_sub(tmp_csum, csum_unfold(csum));
587 588
588 csum = csum_ipv6_magic(&fl->fl6_src, 589 csum = csum_ipv6_magic(&fl6->saddr, &fl6->daddr,
589 &fl->fl6_dst, 590 total_len, fl6->flowi6_proto, tmp_csum);
590 total_len, fl->proto, tmp_csum);
591 591
592 if (csum == 0 && fl->proto == IPPROTO_UDP) 592 if (csum == 0 && fl6->flowi6_proto == IPPROTO_UDP)
593 csum = CSUM_MANGLED_0; 593 csum = CSUM_MANGLED_0;
594 594
595 if (skb_store_bits(skb, offset, &csum, 2)) 595 if (skb_store_bits(skb, offset, &csum, 2))
@@ -602,7 +602,7 @@ 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 dst_entry **dstp, 605 struct flowi6 *fl6, 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);
@@ -612,7 +612,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
612 struct rt6_info *rt = (struct rt6_info *)*dstp; 612 struct rt6_info *rt = (struct rt6_info *)*dstp;
613 613
614 if (length > rt->dst.dev->mtu) { 614 if (length > rt->dst.dev->mtu) {
615 ipv6_local_error(sk, EMSGSIZE, fl, rt->dst.dev->mtu); 615 ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu);
616 return -EMSGSIZE; 616 return -EMSGSIZE;
617 } 617 }
618 if (flags&MSG_PROBE) 618 if (flags&MSG_PROBE)
@@ -661,7 +661,7 @@ error:
661 return err; 661 return err;
662} 662}
663 663
664static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) 664static int rawv6_probe_proto_opt(struct flowi6 *fl6, struct msghdr *msg)
665{ 665{
666 struct iovec *iov; 666 struct iovec *iov;
667 u8 __user *type = NULL; 667 u8 __user *type = NULL;
@@ -678,7 +678,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
678 if (!iov) 678 if (!iov)
679 continue; 679 continue;
680 680
681 switch (fl->proto) { 681 switch (fl6->flowi6_proto) {
682 case IPPROTO_ICMPV6: 682 case IPPROTO_ICMPV6:
683 /* check if one-byte field is readable or not. */ 683 /* check if one-byte field is readable or not. */
684 if (iov->iov_base && iov->iov_len < 1) 684 if (iov->iov_base && iov->iov_len < 1)
@@ -693,8 +693,8 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
693 code = iov->iov_base; 693 code = iov->iov_base;
694 694
695 if (type && code) { 695 if (type && code) {
696 if (get_user(fl->fl_icmp_type, type) || 696 if (get_user(fl6->fl6_icmp_type, type) ||
697 get_user(fl->fl_icmp_code, code)) 697 get_user(fl6->fl6_icmp_code, code))
698 return -EFAULT; 698 return -EFAULT;
699 probed = 1; 699 probed = 1;
700 } 700 }
@@ -705,7 +705,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
705 /* check if type field is readable or not. */ 705 /* check if type field is readable or not. */
706 if (iov->iov_len > 2 - len) { 706 if (iov->iov_len > 2 - len) {
707 u8 __user *p = iov->iov_base; 707 u8 __user *p = iov->iov_base;
708 if (get_user(fl->fl_mh_type, &p[2 - len])) 708 if (get_user(fl6->fl6_mh_type, &p[2 - len]))
709 return -EFAULT; 709 return -EFAULT;
710 probed = 1; 710 probed = 1;
711 } else 711 } else
@@ -734,7 +734,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
734 struct ipv6_txoptions *opt = NULL; 734 struct ipv6_txoptions *opt = NULL;
735 struct ip6_flowlabel *flowlabel = NULL; 735 struct ip6_flowlabel *flowlabel = NULL;
736 struct dst_entry *dst = NULL; 736 struct dst_entry *dst = NULL;
737 struct flowi fl; 737 struct flowi6 fl6;
738 int addr_len = msg->msg_namelen; 738 int addr_len = msg->msg_namelen;
739 int hlimit = -1; 739 int hlimit = -1;
740 int tclass = -1; 740 int tclass = -1;
@@ -755,9 +755,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
755 /* 755 /*
756 * Get and verify the address. 756 * Get and verify the address.
757 */ 757 */
758 memset(&fl, 0, sizeof(fl)); 758 memset(&fl6, 0, sizeof(fl6));
759 759
760 fl.mark = sk->sk_mark; 760 fl6.flowi6_mark = sk->sk_mark;
761 761
762 if (sin6) { 762 if (sin6) {
763 if (addr_len < SIN6_LEN_RFC2133) 763 if (addr_len < SIN6_LEN_RFC2133)
@@ -779,9 +779,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
779 779
780 daddr = &sin6->sin6_addr; 780 daddr = &sin6->sin6_addr;
781 if (np->sndflow) { 781 if (np->sndflow) {
782 fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; 782 fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
783 if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { 783 if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
784 flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); 784 flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
785 if (flowlabel == NULL) 785 if (flowlabel == NULL)
786 return -EINVAL; 786 return -EINVAL;
787 daddr = &flowlabel->dst; 787 daddr = &flowlabel->dst;
@@ -799,32 +799,32 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
799 if (addr_len >= sizeof(struct sockaddr_in6) && 799 if (addr_len >= sizeof(struct sockaddr_in6) &&
800 sin6->sin6_scope_id && 800 sin6->sin6_scope_id &&
801 ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) 801 ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)
802 fl.oif = sin6->sin6_scope_id; 802 fl6.flowi6_oif = sin6->sin6_scope_id;
803 } else { 803 } else {
804 if (sk->sk_state != TCP_ESTABLISHED) 804 if (sk->sk_state != TCP_ESTABLISHED)
805 return -EDESTADDRREQ; 805 return -EDESTADDRREQ;
806 806
807 proto = inet->inet_num; 807 proto = inet->inet_num;
808 daddr = &np->daddr; 808 daddr = &np->daddr;
809 fl.fl6_flowlabel = np->flow_label; 809 fl6.flowlabel = np->flow_label;
810 } 810 }
811 811
812 if (fl.oif == 0) 812 if (fl6.flowi6_oif == 0)
813 fl.oif = sk->sk_bound_dev_if; 813 fl6.flowi6_oif = sk->sk_bound_dev_if;
814 814
815 if (msg->msg_controllen) { 815 if (msg->msg_controllen) {
816 opt = &opt_space; 816 opt = &opt_space;
817 memset(opt, 0, sizeof(struct ipv6_txoptions)); 817 memset(opt, 0, sizeof(struct ipv6_txoptions));
818 opt->tot_len = sizeof(struct ipv6_txoptions); 818 opt->tot_len = sizeof(struct ipv6_txoptions);
819 819
820 err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, 820 err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit,
821 &tclass, &dontfrag); 821 &tclass, &dontfrag);
822 if (err < 0) { 822 if (err < 0) {
823 fl6_sock_release(flowlabel); 823 fl6_sock_release(flowlabel);
824 return err; 824 return err;
825 } 825 }
826 if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { 826 if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
827 flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); 827 flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
828 if (flowlabel == NULL) 828 if (flowlabel == NULL)
829 return -EINVAL; 829 return -EINVAL;
830 } 830 }
@@ -837,40 +837,31 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
837 opt = fl6_merge_options(&opt_space, flowlabel, opt); 837 opt = fl6_merge_options(&opt_space, flowlabel, opt);
838 opt = ipv6_fixup_options(&opt_space, opt); 838 opt = ipv6_fixup_options(&opt_space, opt);
839 839
840 fl.proto = proto; 840 fl6.flowi6_proto = proto;
841 err = rawv6_probe_proto_opt(&fl, msg); 841 err = rawv6_probe_proto_opt(&fl6, msg);
842 if (err) 842 if (err)
843 goto out; 843 goto out;
844 844
845 if (!ipv6_addr_any(daddr)) 845 if (!ipv6_addr_any(daddr))
846 ipv6_addr_copy(&fl.fl6_dst, daddr); 846 ipv6_addr_copy(&fl6.daddr, daddr);
847 else 847 else
848 fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ 848 fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
849 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) 849 if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
850 ipv6_addr_copy(&fl.fl6_src, &np->saddr); 850 ipv6_addr_copy(&fl6.saddr, &np->saddr);
851 851
852 final_p = fl6_update_dst(&fl, opt, &final); 852 final_p = fl6_update_dst(&fl6, opt, &final);
853 853
854 if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) 854 if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
855 fl.oif = np->mcast_oif; 855 fl6.flowi6_oif = np->mcast_oif;
856 security_sk_classify_flow(sk, &fl); 856 security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
857 857
858 err = ip6_dst_lookup(sk, &dst, &fl); 858 dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
859 if (err) 859 if (IS_ERR(dst)) {
860 err = PTR_ERR(dst);
860 goto out; 861 goto out;
861 if (final_p)
862 ipv6_addr_copy(&fl.fl6_dst, final_p);
863
864 err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT);
865 if (err < 0) {
866 if (err == -EREMOTE)
867 err = ip6_dst_blackhole(sk, &dst, &fl);
868 if (err < 0)
869 goto out;
870 } 862 }
871
872 if (hlimit < 0) { 863 if (hlimit < 0) {
873 if (ipv6_addr_is_multicast(&fl.fl6_dst)) 864 if (ipv6_addr_is_multicast(&fl6.daddr))
874 hlimit = np->mcast_hops; 865 hlimit = np->mcast_hops;
875 else 866 else
876 hlimit = np->hop_limit; 867 hlimit = np->hop_limit;
@@ -889,17 +880,17 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
889 880
890back_from_confirm: 881back_from_confirm:
891 if (inet->hdrincl) 882 if (inet->hdrincl)
892 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);
893 else { 884 else {
894 lock_sock(sk); 885 lock_sock(sk);
895 err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, 886 err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov,
896 len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, 887 len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info*)dst,
897 msg->msg_flags, dontfrag); 888 msg->msg_flags, dontfrag);
898 889
899 if (err) 890 if (err)
900 ip6_flush_pending_frames(sk); 891 ip6_flush_pending_frames(sk);
901 else if (!(msg->msg_flags & MSG_MORE)) 892 else if (!(msg->msg_flags & MSG_MORE))
902 err = rawv6_push_pending_frames(sk, &fl, rp); 893 err = rawv6_push_pending_frames(sk, &fl6, rp);
903 release_sock(sk); 894 release_sock(sk);
904 } 895 }
905done: 896done:
@@ -1157,6 +1148,23 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
1157 } 1148 }
1158} 1149}
1159 1150
1151#ifdef CONFIG_COMPAT
1152static int compat_rawv6_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
1153{
1154 switch (cmd) {
1155 case SIOCOUTQ:
1156 case SIOCINQ:
1157 return -ENOIOCTLCMD;
1158 default:
1159#ifdef CONFIG_IPV6_MROUTE
1160 return ip6mr_compat_ioctl(sk, cmd, compat_ptr(arg));
1161#else
1162 return -ENOIOCTLCMD;
1163#endif
1164 }
1165}
1166#endif
1167
1160static void rawv6_close(struct sock *sk, long timeout) 1168static void rawv6_close(struct sock *sk, long timeout)
1161{ 1169{
1162 if (inet_sk(sk)->inet_num == IPPROTO_RAW) 1170 if (inet_sk(sk)->inet_num == IPPROTO_RAW)
@@ -1215,6 +1223,7 @@ struct proto rawv6_prot = {
1215#ifdef CONFIG_COMPAT 1223#ifdef CONFIG_COMPAT
1216 .compat_setsockopt = compat_rawv6_setsockopt, 1224 .compat_setsockopt = compat_rawv6_setsockopt,
1217 .compat_getsockopt = compat_rawv6_getsockopt, 1225 .compat_getsockopt = compat_rawv6_getsockopt,
1226 .compat_ioctl = compat_rawv6_ioctl,
1218#endif 1227#endif
1219}; 1228};
1220 1229