hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/ipv6/datagram.c
....@@ -1,14 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * common UDP/RAW code
34 * Linux INET6 implementation
45 *
56 * Authors:
67 * 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.
128 */
139
1410 #include <linux/capability.h>
....@@ -23,6 +19,7 @@
2319 #include <linux/route.h>
2420 #include <linux/slab.h>
2521 #include <linux/export.h>
22
+#include <linux/icmp.h>
2623
2724 #include <net/ipv6.h>
2825 #include <net/ndisc.h>
....@@ -54,7 +51,7 @@
5451 fl6->flowi6_mark = sk->sk_mark;
5552 fl6->fl6_dport = inet->inet_dport;
5653 fl6->fl6_sport = inet->inet_sport;
57
- fl6->flowlabel = np->flow_label;
54
+ fl6->flowlabel = ip6_make_flowinfo(np->tclass, np->flow_label);
5855 fl6->flowi6_uid = sk->sk_uid;
5956
6057 if (!fl6->flowi6_oif)
....@@ -63,7 +60,7 @@
6360 if (!fl6->flowi6_oif && ipv6_addr_is_multicast(&fl6->daddr))
6461 fl6->flowi6_oif = np->mcast_oif;
6562
66
- security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
63
+ security_sk_classify_flow(sk, flowi6_to_flowi_common(fl6));
6764 }
6865
6966 int ip6_datagram_dst_update(struct sock *sk, bool fix_sk_saddr)
....@@ -79,7 +76,7 @@
7976
8077 if (np->sndflow && (np->flow_label & IPV6_FLOWLABEL_MASK)) {
8178 flowlabel = fl6_sock_lookup(sk, np->flow_label);
82
- if (!flowlabel)
79
+ if (IS_ERR(flowlabel))
8380 return -EINVAL;
8481 }
8582 ip6_datagram_flow_key_init(&fl6, sk);
....@@ -259,7 +256,7 @@
259256 goto out;
260257 }
261258
262
- reuseport_has_conns(sk, true);
259
+ reuseport_has_conns_set(sk);
263260 sk->sk_state = TCP_ESTABLISHED;
264261 sk_set_txhash(sk);
265262 out:
....@@ -287,6 +284,17 @@
287284 return ip6_datagram_connect(sk, uaddr, addr_len);
288285 }
289286 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
+}
290298
291299 void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
292300 __be16 port, u32 info, u8 *payload)
....@@ -317,6 +325,10 @@
317325 serr->port = port;
318326
319327 __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
+
320332 skb_reset_transport_header(skb);
321333
322334 if (sock_queue_err_skb(sk, skb))
....@@ -773,6 +785,7 @@
773785 case IPV6_2292PKTINFO:
774786 {
775787 struct net_device *dev = NULL;
788
+ int src_idx;
776789
777790 if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) {
778791 err = -EINVAL;
....@@ -780,12 +793,15 @@
780793 }
781794
782795 src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
796
+ src_idx = src_info->ipi6_ifindex;
783797
784
- if (src_info->ipi6_ifindex) {
798
+ if (src_idx) {
785799 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)))
787803 return -EINVAL;
788
- fl6->flowi6_oif = src_info->ipi6_ifindex;
804
+ fl6->flowi6_oif = src_idx;
789805 }
790806
791807 addr_type = __ipv6_addr_type(&src_info->ipi6_addr);
....@@ -1032,7 +1048,7 @@
10321048 src = &sp->sk_v6_rcv_saddr;
10331049 seq_printf(seq,
10341050 "%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",
10361052 bucket,
10371053 src->s6_addr32[0], src->s6_addr32[1],
10381054 src->s6_addr32[2], src->s6_addr32[3], srcp,