.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * common UDP/RAW code |
---|
3 | 4 | * Linux INET6 implementation |
---|
4 | 5 | * |
---|
5 | 6 | * Authors: |
---|
6 | 7 | * Pedro Roque <roque@di.fc.ul.pt> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or |
---|
9 | | - * modify it under the terms of the GNU General Public License |
---|
10 | | - * as published by the Free Software Foundation; either version |
---|
11 | | - * 2 of the License, or (at your option) any later version. |
---|
12 | 8 | */ |
---|
13 | 9 | |
---|
14 | 10 | #include <linux/capability.h> |
---|
.. | .. |
---|
23 | 19 | #include <linux/route.h> |
---|
24 | 20 | #include <linux/slab.h> |
---|
25 | 21 | #include <linux/export.h> |
---|
| 22 | +#include <linux/icmp.h> |
---|
26 | 23 | |
---|
27 | 24 | #include <net/ipv6.h> |
---|
28 | 25 | #include <net/ndisc.h> |
---|
.. | .. |
---|
54 | 51 | fl6->flowi6_mark = sk->sk_mark; |
---|
55 | 52 | fl6->fl6_dport = inet->inet_dport; |
---|
56 | 53 | fl6->fl6_sport = inet->inet_sport; |
---|
57 | | - fl6->flowlabel = np->flow_label; |
---|
| 54 | + fl6->flowlabel = ip6_make_flowinfo(np->tclass, np->flow_label); |
---|
58 | 55 | fl6->flowi6_uid = sk->sk_uid; |
---|
59 | 56 | |
---|
60 | 57 | if (!fl6->flowi6_oif) |
---|
.. | .. |
---|
63 | 60 | if (!fl6->flowi6_oif && ipv6_addr_is_multicast(&fl6->daddr)) |
---|
64 | 61 | fl6->flowi6_oif = np->mcast_oif; |
---|
65 | 62 | |
---|
66 | | - security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); |
---|
| 63 | + security_sk_classify_flow(sk, flowi6_to_flowi_common(fl6)); |
---|
67 | 64 | } |
---|
68 | 65 | |
---|
69 | 66 | int ip6_datagram_dst_update(struct sock *sk, bool fix_sk_saddr) |
---|
.. | .. |
---|
79 | 76 | |
---|
80 | 77 | if (np->sndflow && (np->flow_label & IPV6_FLOWLABEL_MASK)) { |
---|
81 | 78 | flowlabel = fl6_sock_lookup(sk, np->flow_label); |
---|
82 | | - if (!flowlabel) |
---|
| 79 | + if (IS_ERR(flowlabel)) |
---|
83 | 80 | return -EINVAL; |
---|
84 | 81 | } |
---|
85 | 82 | ip6_datagram_flow_key_init(&fl6, sk); |
---|
.. | .. |
---|
259 | 256 | goto out; |
---|
260 | 257 | } |
---|
261 | 258 | |
---|
262 | | - reuseport_has_conns(sk, true); |
---|
| 259 | + reuseport_has_conns_set(sk); |
---|
263 | 260 | sk->sk_state = TCP_ESTABLISHED; |
---|
264 | 261 | sk_set_txhash(sk); |
---|
265 | 262 | out: |
---|
.. | .. |
---|
287 | 284 | return ip6_datagram_connect(sk, uaddr, addr_len); |
---|
288 | 285 | } |
---|
289 | 286 | EXPORT_SYMBOL_GPL(ip6_datagram_connect_v6_only); |
---|
| 287 | + |
---|
| 288 | +static void ipv6_icmp_error_rfc4884(const struct sk_buff *skb, |
---|
| 289 | + struct sock_ee_data_rfc4884 *out) |
---|
| 290 | +{ |
---|
| 291 | + switch (icmp6_hdr(skb)->icmp6_type) { |
---|
| 292 | + case ICMPV6_TIME_EXCEED: |
---|
| 293 | + case ICMPV6_DEST_UNREACH: |
---|
| 294 | + ip_icmp_error_rfc4884(skb, out, sizeof(struct icmp6hdr), |
---|
| 295 | + icmp6_hdr(skb)->icmp6_datagram_len * 8); |
---|
| 296 | + } |
---|
| 297 | +} |
---|
290 | 298 | |
---|
291 | 299 | void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, |
---|
292 | 300 | __be16 port, u32 info, u8 *payload) |
---|
.. | .. |
---|
317 | 325 | serr->port = port; |
---|
318 | 326 | |
---|
319 | 327 | __skb_pull(skb, payload - skb->data); |
---|
| 328 | + |
---|
| 329 | + if (inet6_sk(sk)->recverr_rfc4884) |
---|
| 330 | + ipv6_icmp_error_rfc4884(skb, &serr->ee.ee_rfc4884); |
---|
| 331 | + |
---|
320 | 332 | skb_reset_transport_header(skb); |
---|
321 | 333 | |
---|
322 | 334 | if (sock_queue_err_skb(sk, skb)) |
---|
.. | .. |
---|
773 | 785 | case IPV6_2292PKTINFO: |
---|
774 | 786 | { |
---|
775 | 787 | struct net_device *dev = NULL; |
---|
| 788 | + int src_idx; |
---|
776 | 789 | |
---|
777 | 790 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) { |
---|
778 | 791 | err = -EINVAL; |
---|
.. | .. |
---|
780 | 793 | } |
---|
781 | 794 | |
---|
782 | 795 | src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); |
---|
| 796 | + src_idx = src_info->ipi6_ifindex; |
---|
783 | 797 | |
---|
784 | | - if (src_info->ipi6_ifindex) { |
---|
| 798 | + if (src_idx) { |
---|
785 | 799 | if (fl6->flowi6_oif && |
---|
786 | | - src_info->ipi6_ifindex != fl6->flowi6_oif) |
---|
| 800 | + src_idx != fl6->flowi6_oif && |
---|
| 801 | + (sk->sk_bound_dev_if != fl6->flowi6_oif || |
---|
| 802 | + !sk_dev_equal_l3scope(sk, src_idx))) |
---|
787 | 803 | return -EINVAL; |
---|
788 | | - fl6->flowi6_oif = src_info->ipi6_ifindex; |
---|
| 804 | + fl6->flowi6_oif = src_idx; |
---|
789 | 805 | } |
---|
790 | 806 | |
---|
791 | 807 | addr_type = __ipv6_addr_type(&src_info->ipi6_addr); |
---|
.. | .. |
---|
1032 | 1048 | src = &sp->sk_v6_rcv_saddr; |
---|
1033 | 1049 | seq_printf(seq, |
---|
1034 | 1050 | "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " |
---|
1035 | | - "%02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d\n", |
---|
| 1051 | + "%02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %u\n", |
---|
1036 | 1052 | bucket, |
---|
1037 | 1053 | src->s6_addr32[0], src->s6_addr32[1], |
---|
1038 | 1054 | src->s6_addr32[2], src->s6_addr32[3], srcp, |
---|