.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * INET An implementation of the TCP/IP protocol suite for the LINUX |
---|
3 | 4 | * operating system. INET is implemented using the BSD Socket |
---|
.. | .. |
---|
30 | 31 | * Alan Cox : Added IP_HDRINCL option. |
---|
31 | 32 | * Alan Cox : Skip broadcast check if BSDism set. |
---|
32 | 33 | * David S. Miller : New socket lookup architecture. |
---|
33 | | - * |
---|
34 | | - * This program is free software; you can redistribute it and/or |
---|
35 | | - * modify it under the terms of the GNU General Public License |
---|
36 | | - * as published by the Free Software Foundation; either version |
---|
37 | | - * 2 of the License, or (at your option) any later version. |
---|
38 | 34 | */ |
---|
39 | 35 | |
---|
40 | 36 | #include <linux/types.h> |
---|
.. | .. |
---|
131 | 127 | if (net_eq(sock_net(sk), net) && inet->inet_num == num && |
---|
132 | 128 | !(inet->inet_daddr && inet->inet_daddr != raddr) && |
---|
133 | 129 | !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && |
---|
134 | | - !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif && |
---|
135 | | - sk->sk_bound_dev_if != sdif)) |
---|
| 130 | + raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif)) |
---|
136 | 131 | goto found; /* gotcha */ |
---|
137 | 132 | } |
---|
138 | 133 | sk = NULL; |
---|
.. | .. |
---|
265 | 260 | err = EHOSTUNREACH; |
---|
266 | 261 | if (code > NR_ICMP_UNREACH) |
---|
267 | 262 | break; |
---|
268 | | - err = icmp_err_convert[code].errno; |
---|
269 | | - harderr = icmp_err_convert[code].fatal; |
---|
270 | 263 | if (code == ICMP_FRAG_NEEDED) { |
---|
271 | 264 | harderr = inet->pmtudisc != IP_PMTUDISC_DONT; |
---|
272 | 265 | err = EMSGSIZE; |
---|
| 266 | + } else { |
---|
| 267 | + err = icmp_err_convert[code].errno; |
---|
| 268 | + harderr = icmp_err_convert[code].fatal; |
---|
273 | 269 | } |
---|
274 | 270 | } |
---|
275 | 271 | |
---|
.. | .. |
---|
337 | 333 | kfree_skb(skb); |
---|
338 | 334 | return NET_RX_DROP; |
---|
339 | 335 | } |
---|
340 | | - nf_reset(skb); |
---|
| 336 | + nf_reset_ct(skb); |
---|
341 | 337 | |
---|
342 | 338 | skb_push(skb, skb->data - skb_network_header(skb)); |
---|
343 | 339 | |
---|
.. | .. |
---|
380 | 376 | skb_reserve(skb, hlen); |
---|
381 | 377 | |
---|
382 | 378 | skb->priority = sk->sk_priority; |
---|
383 | | - skb->mark = sk->sk_mark; |
---|
| 379 | + skb->mark = sockc->mark; |
---|
384 | 380 | skb->tstamp = sockc->transmit_time; |
---|
385 | 381 | skb_dst_set(skb, &rt->dst); |
---|
386 | 382 | *rtp = NULL; |
---|
.. | .. |
---|
391 | 387 | |
---|
392 | 388 | skb->ip_summed = CHECKSUM_NONE; |
---|
393 | 389 | |
---|
394 | | - sock_tx_timestamp(sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags); |
---|
| 390 | + skb_setup_tx_timestamp(skb, sockc->tsflags); |
---|
395 | 391 | |
---|
396 | 392 | if (flags & MSG_CONFIRM) |
---|
397 | 393 | skb_set_dst_pending_confirm(skb, 1); |
---|
.. | .. |
---|
483 | 479 | skb->csum = csum_block_add( |
---|
484 | 480 | skb->csum, |
---|
485 | 481 | csum_partial_copy_nocheck(rfv->hdr.c + offset, |
---|
486 | | - to, copy, 0), |
---|
| 482 | + to, copy), |
---|
487 | 483 | odd); |
---|
488 | 484 | |
---|
489 | 485 | odd = 0; |
---|
.. | .. |
---|
563 | 559 | } |
---|
564 | 560 | |
---|
565 | 561 | ipcm_init_sk(&ipc, inet); |
---|
| 562 | + /* Keep backward compat */ |
---|
| 563 | + if (hdrincl) |
---|
| 564 | + ipc.protocol = IPPROTO_RAW; |
---|
566 | 565 | |
---|
567 | 566 | if (msg->msg_controllen) { |
---|
568 | 567 | err = ip_cmsg_send(sk, msg, &ipc, false); |
---|
.. | .. |
---|
608 | 607 | tos |= RTO_ONLINK; |
---|
609 | 608 | |
---|
610 | 609 | if (ipv4_is_multicast(daddr)) { |
---|
611 | | - if (!ipc.oif) |
---|
| 610 | + if (!ipc.oif || netif_index_is_l3_master(sock_net(sk), ipc.oif)) |
---|
612 | 611 | ipc.oif = inet->mc_index; |
---|
613 | 612 | if (!saddr) |
---|
614 | 613 | saddr = inet->mc_addr; |
---|
615 | 614 | } else if (!ipc.oif) { |
---|
616 | 615 | ipc.oif = inet->uc_index; |
---|
617 | 616 | } else if (ipv4_is_lbcast(daddr) && inet->uc_index) { |
---|
618 | | - /* oif is set, packet is to local broadcast and |
---|
| 617 | + /* oif is set, packet is to local broadcast |
---|
619 | 618 | * and uc_index is set. oif is most likely set |
---|
620 | 619 | * by sk_bound_dev_if. If uc_index != oif check if the |
---|
621 | 620 | * oif is an L3 master and uc_index is an L3 slave. |
---|
.. | .. |
---|
628 | 627 | } |
---|
629 | 628 | } |
---|
630 | 629 | |
---|
631 | | - flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, |
---|
| 630 | + flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, tos, |
---|
632 | 631 | RT_SCOPE_UNIVERSE, |
---|
633 | | - hdrincl ? IPPROTO_RAW : sk->sk_protocol, |
---|
| 632 | + hdrincl ? ipc.protocol : sk->sk_protocol, |
---|
634 | 633 | inet_sk_flowi_flags(sk) | |
---|
635 | 634 | (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), |
---|
636 | 635 | daddr, saddr, 0, 0, sk->sk_uid); |
---|
.. | .. |
---|
644 | 643 | goto done; |
---|
645 | 644 | } |
---|
646 | 645 | |
---|
647 | | - security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); |
---|
| 646 | + security_sk_classify_flow(sk, flowi4_to_flowi_common(&fl4)); |
---|
648 | 647 | rt = ip_route_output_flow(net, &fl4, sk); |
---|
649 | 648 | if (IS_ERR(rt)) { |
---|
650 | 649 | err = PTR_ERR(rt); |
---|
.. | .. |
---|
808 | 807 | return copied; |
---|
809 | 808 | } |
---|
810 | 809 | |
---|
811 | | -static int raw_init(struct sock *sk) |
---|
| 810 | +static int raw_sk_init(struct sock *sk) |
---|
812 | 811 | { |
---|
813 | 812 | struct raw_sock *rp = raw_sk(sk); |
---|
814 | 813 | |
---|
.. | .. |
---|
817 | 816 | return 0; |
---|
818 | 817 | } |
---|
819 | 818 | |
---|
820 | | -static int raw_seticmpfilter(struct sock *sk, char __user *optval, int optlen) |
---|
| 819 | +static int raw_seticmpfilter(struct sock *sk, sockptr_t optval, int optlen) |
---|
821 | 820 | { |
---|
822 | 821 | if (optlen > sizeof(struct icmp_filter)) |
---|
823 | 822 | optlen = sizeof(struct icmp_filter); |
---|
824 | | - if (copy_from_user(&raw_sk(sk)->filter, optval, optlen)) |
---|
| 823 | + if (copy_from_sockptr(&raw_sk(sk)->filter, optval, optlen)) |
---|
825 | 824 | return -EFAULT; |
---|
826 | 825 | return 0; |
---|
827 | 826 | } |
---|
.. | .. |
---|
846 | 845 | } |
---|
847 | 846 | |
---|
848 | 847 | static int do_raw_setsockopt(struct sock *sk, int level, int optname, |
---|
849 | | - char __user *optval, unsigned int optlen) |
---|
| 848 | + sockptr_t optval, unsigned int optlen) |
---|
850 | 849 | { |
---|
851 | 850 | if (optname == ICMP_FILTER) { |
---|
852 | 851 | if (inet_sk(sk)->inet_num != IPPROTO_ICMP) |
---|
.. | .. |
---|
858 | 857 | } |
---|
859 | 858 | |
---|
860 | 859 | static int raw_setsockopt(struct sock *sk, int level, int optname, |
---|
861 | | - char __user *optval, unsigned int optlen) |
---|
| 860 | + sockptr_t optval, unsigned int optlen) |
---|
862 | 861 | { |
---|
863 | 862 | if (level != SOL_RAW) |
---|
864 | 863 | return ip_setsockopt(sk, level, optname, optval, optlen); |
---|
865 | 864 | return do_raw_setsockopt(sk, level, optname, optval, optlen); |
---|
866 | 865 | } |
---|
867 | | - |
---|
868 | | -#ifdef CONFIG_COMPAT |
---|
869 | | -static int compat_raw_setsockopt(struct sock *sk, int level, int optname, |
---|
870 | | - char __user *optval, unsigned int optlen) |
---|
871 | | -{ |
---|
872 | | - if (level != SOL_RAW) |
---|
873 | | - return compat_ip_setsockopt(sk, level, optname, optval, optlen); |
---|
874 | | - return do_raw_setsockopt(sk, level, optname, optval, optlen); |
---|
875 | | -} |
---|
876 | | -#endif |
---|
877 | 866 | |
---|
878 | 867 | static int do_raw_getsockopt(struct sock *sk, int level, int optname, |
---|
879 | 868 | char __user *optval, int __user *optlen) |
---|
.. | .. |
---|
894 | 883 | return ip_getsockopt(sk, level, optname, optval, optlen); |
---|
895 | 884 | return do_raw_getsockopt(sk, level, optname, optval, optlen); |
---|
896 | 885 | } |
---|
897 | | - |
---|
898 | | -#ifdef CONFIG_COMPAT |
---|
899 | | -static int compat_raw_getsockopt(struct sock *sk, int level, int optname, |
---|
900 | | - char __user *optval, int __user *optlen) |
---|
901 | | -{ |
---|
902 | | - if (level != SOL_RAW) |
---|
903 | | - return compat_ip_getsockopt(sk, level, optname, optval, optlen); |
---|
904 | | - return do_raw_getsockopt(sk, level, optname, optval, optlen); |
---|
905 | | -} |
---|
906 | | -#endif |
---|
907 | 886 | |
---|
908 | 887 | static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg) |
---|
909 | 888 | { |
---|
.. | .. |
---|
973 | 952 | .connect = ip4_datagram_connect, |
---|
974 | 953 | .disconnect = __udp_disconnect, |
---|
975 | 954 | .ioctl = raw_ioctl, |
---|
976 | | - .init = raw_init, |
---|
| 955 | + .init = raw_sk_init, |
---|
977 | 956 | .setsockopt = raw_setsockopt, |
---|
978 | 957 | .getsockopt = raw_getsockopt, |
---|
979 | 958 | .sendmsg = raw_sendmsg, |
---|
.. | .. |
---|
988 | 967 | .usersize = sizeof_field(struct raw_sock, filter), |
---|
989 | 968 | .h.raw_hash = &raw_v4_hashinfo, |
---|
990 | 969 | #ifdef CONFIG_COMPAT |
---|
991 | | - .compat_setsockopt = compat_raw_setsockopt, |
---|
992 | | - .compat_getsockopt = compat_raw_getsockopt, |
---|
993 | 970 | .compat_ioctl = compat_raw_ioctl, |
---|
994 | 971 | #endif |
---|
995 | 972 | .diag_destroy = raw_abort, |
---|
.. | .. |
---|
1042 | 1019 | } |
---|
1043 | 1020 | |
---|
1044 | 1021 | void *raw_seq_start(struct seq_file *seq, loff_t *pos) |
---|
| 1022 | + __acquires(&h->lock) |
---|
1045 | 1023 | { |
---|
1046 | 1024 | struct raw_hashinfo *h = PDE_DATA(file_inode(seq->file)); |
---|
1047 | 1025 | |
---|
.. | .. |
---|
1064 | 1042 | EXPORT_SYMBOL_GPL(raw_seq_next); |
---|
1065 | 1043 | |
---|
1066 | 1044 | void raw_seq_stop(struct seq_file *seq, void *v) |
---|
| 1045 | + __releases(&h->lock) |
---|
1067 | 1046 | { |
---|
1068 | 1047 | struct raw_hashinfo *h = PDE_DATA(file_inode(seq->file)); |
---|
1069 | 1048 | |
---|
.. | .. |
---|
1080 | 1059 | srcp = inet->inet_num; |
---|
1081 | 1060 | |
---|
1082 | 1061 | seq_printf(seq, "%4d: %08X:%04X %08X:%04X" |
---|
1083 | | - " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d\n", |
---|
| 1062 | + " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %u\n", |
---|
1084 | 1063 | i, src, srcp, dest, destp, sp->sk_state, |
---|
1085 | 1064 | sk_wmem_alloc_get(sp), |
---|
1086 | 1065 | sk_rmem_alloc_get(sp), |
---|
.. | .. |
---|
1137 | 1116 | unregister_pernet_subsys(&raw_net_ops); |
---|
1138 | 1117 | } |
---|
1139 | 1118 | #endif /* CONFIG_PROC_FS */ |
---|
| 1119 | + |
---|
| 1120 | +static void raw_sysctl_init_net(struct net *net) |
---|
| 1121 | +{ |
---|
| 1122 | +#ifdef CONFIG_NET_L3_MASTER_DEV |
---|
| 1123 | + net->ipv4.sysctl_raw_l3mdev_accept = 1; |
---|
| 1124 | +#endif |
---|
| 1125 | +} |
---|
| 1126 | + |
---|
| 1127 | +static int __net_init raw_sysctl_init(struct net *net) |
---|
| 1128 | +{ |
---|
| 1129 | + raw_sysctl_init_net(net); |
---|
| 1130 | + return 0; |
---|
| 1131 | +} |
---|
| 1132 | + |
---|
| 1133 | +static struct pernet_operations __net_initdata raw_sysctl_ops = { |
---|
| 1134 | + .init = raw_sysctl_init, |
---|
| 1135 | +}; |
---|
| 1136 | + |
---|
| 1137 | +void __init raw_init(void) |
---|
| 1138 | +{ |
---|
| 1139 | + raw_sysctl_init_net(&init_net); |
---|
| 1140 | + if (register_pernet_subsys(&raw_sysctl_ops)) |
---|
| 1141 | + panic("RAW: failed to init sysctl parameters.\n"); |
---|
| 1142 | +} |
---|