.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * RAW sockets for IPv6 |
---|
3 | 4 | * Linux INET6 implementation |
---|
.. | .. |
---|
11 | 12 | * Hideaki YOSHIFUJI : sin6_scope_id support |
---|
12 | 13 | * YOSHIFUJI,H.@USAGI : raw checksum (RFC2292(bis) compliance) |
---|
13 | 14 | * Kazunori MIYAZAWA @USAGI: change process style to use ip6_append_data |
---|
14 | | - * |
---|
15 | | - * This program is free software; you can redistribute it and/or |
---|
16 | | - * modify it under the terms of the GNU General Public License |
---|
17 | | - * as published by the Free Software Foundation; either version |
---|
18 | | - * 2 of the License, or (at your option) any later version. |
---|
19 | 15 | */ |
---|
20 | 16 | |
---|
21 | 17 | #include <linux/errno.h> |
---|
.. | .. |
---|
86 | 82 | !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) |
---|
87 | 83 | continue; |
---|
88 | 84 | |
---|
89 | | - if (sk->sk_bound_dev_if && |
---|
90 | | - sk->sk_bound_dev_if != dif && |
---|
91 | | - sk->sk_bound_dev_if != sdif) |
---|
| 85 | + if (!raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, |
---|
| 86 | + dif, sdif)) |
---|
92 | 87 | continue; |
---|
93 | 88 | |
---|
94 | 89 | if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { |
---|
.. | .. |
---|
220 | 215 | |
---|
221 | 216 | /* Not releasing hash table! */ |
---|
222 | 217 | if (clone) { |
---|
223 | | - nf_reset(clone); |
---|
| 218 | + nf_reset_ct(clone); |
---|
224 | 219 | rawv6_rcv(sk, clone); |
---|
225 | 220 | } |
---|
226 | 221 | } |
---|
.. | .. |
---|
651 | 646 | |
---|
652 | 647 | skb->protocol = htons(ETH_P_IPV6); |
---|
653 | 648 | skb->priority = sk->sk_priority; |
---|
654 | | - skb->mark = sk->sk_mark; |
---|
| 649 | + skb->mark = sockc->mark; |
---|
655 | 650 | skb->tstamp = sockc->transmit_time; |
---|
656 | 651 | |
---|
657 | 652 | skb_put(skb, length); |
---|
.. | .. |
---|
660 | 655 | |
---|
661 | 656 | skb->ip_summed = CHECKSUM_NONE; |
---|
662 | 657 | |
---|
663 | | - sock_tx_timestamp(sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags); |
---|
| 658 | + skb_setup_tx_timestamp(skb, sockc->tsflags); |
---|
664 | 659 | |
---|
665 | 660 | if (flags & MSG_CONFIRM) |
---|
666 | 661 | skb_set_dst_pending_confirm(skb, 1); |
---|
.. | .. |
---|
751 | 746 | skb->csum = csum_block_add( |
---|
752 | 747 | skb->csum, |
---|
753 | 748 | csum_partial_copy_nocheck(rfv->c + offset, |
---|
754 | | - to, copy, 0), |
---|
| 749 | + to, copy), |
---|
755 | 750 | odd); |
---|
756 | 751 | |
---|
757 | 752 | odd = 0; |
---|
.. | .. |
---|
815 | 810 | |
---|
816 | 811 | ipcm6_init(&ipc6); |
---|
817 | 812 | ipc6.sockc.tsflags = sk->sk_tsflags; |
---|
| 813 | + ipc6.sockc.mark = sk->sk_mark; |
---|
818 | 814 | |
---|
819 | 815 | if (sin6) { |
---|
820 | 816 | if (addr_len < SIN6_LEN_RFC2133) |
---|
.. | .. |
---|
839 | 835 | fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; |
---|
840 | 836 | if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { |
---|
841 | 837 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
---|
842 | | - if (!flowlabel) |
---|
| 838 | + if (IS_ERR(flowlabel)) |
---|
843 | 839 | return -EINVAL; |
---|
844 | 840 | } |
---|
845 | 841 | } |
---|
.. | .. |
---|
881 | 877 | } |
---|
882 | 878 | if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { |
---|
883 | 879 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
---|
884 | | - if (!flowlabel) |
---|
| 880 | + if (IS_ERR(flowlabel)) |
---|
885 | 881 | return -EINVAL; |
---|
886 | 882 | } |
---|
887 | 883 | if (!(opt->opt_nflen|opt->opt_flen)) |
---|
.. | .. |
---|
896 | 892 | opt = ipv6_fixup_options(&opt_space, opt); |
---|
897 | 893 | |
---|
898 | 894 | fl6.flowi6_proto = proto; |
---|
| 895 | + fl6.flowi6_mark = ipc6.sockc.mark; |
---|
899 | 896 | |
---|
900 | 897 | if (!hdrincl) { |
---|
901 | 898 | rfv.msg = msg; |
---|
.. | .. |
---|
918 | 915 | fl6.flowi6_oif = np->mcast_oif; |
---|
919 | 916 | else if (!fl6.flowi6_oif) |
---|
920 | 917 | fl6.flowi6_oif = np->ucast_oif; |
---|
921 | | - security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
---|
| 918 | + security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6)); |
---|
922 | 919 | |
---|
923 | 920 | if (hdrincl) |
---|
924 | 921 | fl6.flowi6_flags |= FLOWI_FLAG_KNOWN_NH; |
---|
.. | .. |
---|
975 | 972 | } |
---|
976 | 973 | |
---|
977 | 974 | static int rawv6_seticmpfilter(struct sock *sk, int level, int optname, |
---|
978 | | - char __user *optval, int optlen) |
---|
| 975 | + sockptr_t optval, int optlen) |
---|
979 | 976 | { |
---|
980 | 977 | switch (optname) { |
---|
981 | 978 | case ICMPV6_FILTER: |
---|
982 | 979 | if (optlen > sizeof(struct icmp6_filter)) |
---|
983 | 980 | optlen = sizeof(struct icmp6_filter); |
---|
984 | | - if (copy_from_user(&raw6_sk(sk)->filter, optval, optlen)) |
---|
| 981 | + if (copy_from_sockptr(&raw6_sk(sk)->filter, optval, optlen)) |
---|
985 | 982 | return -EFAULT; |
---|
986 | 983 | return 0; |
---|
987 | 984 | default: |
---|
.. | .. |
---|
1018 | 1015 | |
---|
1019 | 1016 | |
---|
1020 | 1017 | static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, |
---|
1021 | | - char __user *optval, unsigned int optlen) |
---|
| 1018 | + sockptr_t optval, unsigned int optlen) |
---|
1022 | 1019 | { |
---|
1023 | 1020 | struct raw6_sock *rp = raw6_sk(sk); |
---|
1024 | 1021 | int val; |
---|
1025 | 1022 | |
---|
1026 | | - if (get_user(val, (int __user *)optval)) |
---|
| 1023 | + if (optlen < sizeof(val)) |
---|
| 1024 | + return -EINVAL; |
---|
| 1025 | + |
---|
| 1026 | + if (copy_from_sockptr(&val, optval, sizeof(val))) |
---|
1027 | 1027 | return -EFAULT; |
---|
1028 | 1028 | |
---|
1029 | 1029 | switch (optname) { |
---|
.. | .. |
---|
1065 | 1065 | } |
---|
1066 | 1066 | |
---|
1067 | 1067 | static int rawv6_setsockopt(struct sock *sk, int level, int optname, |
---|
1068 | | - char __user *optval, unsigned int optlen) |
---|
| 1068 | + sockptr_t optval, unsigned int optlen) |
---|
1069 | 1069 | { |
---|
1070 | 1070 | switch (level) { |
---|
1071 | 1071 | case SOL_RAW: |
---|
.. | .. |
---|
1079 | 1079 | if (optname == IPV6_CHECKSUM || |
---|
1080 | 1080 | optname == IPV6_HDRINCL) |
---|
1081 | 1081 | break; |
---|
1082 | | - /* fall through */ |
---|
| 1082 | + fallthrough; |
---|
1083 | 1083 | default: |
---|
1084 | 1084 | return ipv6_setsockopt(sk, level, optname, optval, optlen); |
---|
1085 | 1085 | } |
---|
1086 | 1086 | |
---|
1087 | 1087 | return do_rawv6_setsockopt(sk, level, optname, optval, optlen); |
---|
1088 | 1088 | } |
---|
1089 | | - |
---|
1090 | | -#ifdef CONFIG_COMPAT |
---|
1091 | | -static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname, |
---|
1092 | | - char __user *optval, unsigned int optlen) |
---|
1093 | | -{ |
---|
1094 | | - switch (level) { |
---|
1095 | | - case SOL_RAW: |
---|
1096 | | - break; |
---|
1097 | | - case SOL_ICMPV6: |
---|
1098 | | - if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6) |
---|
1099 | | - return -EOPNOTSUPP; |
---|
1100 | | - return rawv6_seticmpfilter(sk, level, optname, optval, optlen); |
---|
1101 | | - case SOL_IPV6: |
---|
1102 | | - if (optname == IPV6_CHECKSUM || |
---|
1103 | | - optname == IPV6_HDRINCL) |
---|
1104 | | - break; |
---|
1105 | | - /* fall through */ |
---|
1106 | | - default: |
---|
1107 | | - return compat_ipv6_setsockopt(sk, level, optname, |
---|
1108 | | - optval, optlen); |
---|
1109 | | - } |
---|
1110 | | - return do_rawv6_setsockopt(sk, level, optname, optval, optlen); |
---|
1111 | | -} |
---|
1112 | | -#endif |
---|
1113 | 1089 | |
---|
1114 | 1090 | static int do_rawv6_getsockopt(struct sock *sk, int level, int optname, |
---|
1115 | 1091 | char __user *optval, int __user *optlen) |
---|
.. | .. |
---|
1164 | 1140 | if (optname == IPV6_CHECKSUM || |
---|
1165 | 1141 | optname == IPV6_HDRINCL) |
---|
1166 | 1142 | break; |
---|
1167 | | - /* fall through */ |
---|
| 1143 | + fallthrough; |
---|
1168 | 1144 | default: |
---|
1169 | 1145 | return ipv6_getsockopt(sk, level, optname, optval, optlen); |
---|
1170 | 1146 | } |
---|
1171 | 1147 | |
---|
1172 | 1148 | return do_rawv6_getsockopt(sk, level, optname, optval, optlen); |
---|
1173 | 1149 | } |
---|
1174 | | - |
---|
1175 | | -#ifdef CONFIG_COMPAT |
---|
1176 | | -static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname, |
---|
1177 | | - char __user *optval, int __user *optlen) |
---|
1178 | | -{ |
---|
1179 | | - switch (level) { |
---|
1180 | | - case SOL_RAW: |
---|
1181 | | - break; |
---|
1182 | | - case SOL_ICMPV6: |
---|
1183 | | - if (inet_sk(sk)->inet_num != IPPROTO_ICMPV6) |
---|
1184 | | - return -EOPNOTSUPP; |
---|
1185 | | - return rawv6_geticmpfilter(sk, level, optname, optval, optlen); |
---|
1186 | | - case SOL_IPV6: |
---|
1187 | | - if (optname == IPV6_CHECKSUM || |
---|
1188 | | - optname == IPV6_HDRINCL) |
---|
1189 | | - break; |
---|
1190 | | - /* fall through */ |
---|
1191 | | - default: |
---|
1192 | | - return compat_ipv6_getsockopt(sk, level, optname, |
---|
1193 | | - optval, optlen); |
---|
1194 | | - } |
---|
1195 | | - return do_rawv6_getsockopt(sk, level, optname, optval, optlen); |
---|
1196 | | -} |
---|
1197 | | -#endif |
---|
1198 | 1150 | |
---|
1199 | 1151 | static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) |
---|
1200 | 1152 | { |
---|
.. | .. |
---|
1300 | 1252 | .usersize = sizeof_field(struct raw6_sock, filter), |
---|
1301 | 1253 | .h.raw_hash = &raw_v6_hashinfo, |
---|
1302 | 1254 | #ifdef CONFIG_COMPAT |
---|
1303 | | - .compat_setsockopt = compat_rawv6_setsockopt, |
---|
1304 | | - .compat_getsockopt = compat_rawv6_getsockopt, |
---|
1305 | 1255 | .compat_ioctl = compat_rawv6_ioctl, |
---|
1306 | 1256 | #endif |
---|
1307 | 1257 | .diag_destroy = raw_abort, |
---|
.. | .. |
---|
1370 | 1320 | .getname = inet6_getname, |
---|
1371 | 1321 | .poll = datagram_poll, /* ok */ |
---|
1372 | 1322 | .ioctl = inet6_ioctl, /* must change */ |
---|
| 1323 | + .gettstamp = sock_gettstamp, |
---|
1373 | 1324 | .listen = sock_no_listen, /* ok */ |
---|
1374 | 1325 | .shutdown = inet_shutdown, /* ok */ |
---|
1375 | 1326 | .setsockopt = sock_common_setsockopt, /* ok */ |
---|
.. | .. |
---|
1379 | 1330 | .mmap = sock_no_mmap, |
---|
1380 | 1331 | .sendpage = sock_no_sendpage, |
---|
1381 | 1332 | #ifdef CONFIG_COMPAT |
---|
1382 | | - .compat_setsockopt = compat_sock_common_setsockopt, |
---|
1383 | | - .compat_getsockopt = compat_sock_common_getsockopt, |
---|
| 1333 | + .compat_ioctl = inet6_compat_ioctl, |
---|
1384 | 1334 | #endif |
---|
1385 | 1335 | }; |
---|
1386 | 1336 | |
---|