hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/net/ipv6/xfrm6_protocol.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* xfrm6_protocol.c - Generic xfrm protocol multiplexer for ipv6.
23 *
34 * Copyright (C) 2013 secunet Security Networks AG
....@@ -7,17 +8,13 @@
78 *
89 * Based on:
910 * net/ipv4/xfrm4_protocol.c
10
- *
11
- * This program is free software; you can redistribute it and/or
12
- * modify it under the terms of the GNU General Public License
13
- * as published by the Free Software Foundation; either version
14
- * 2 of the License, or (at your option) any later version.
1511 */
1612
1713 #include <linux/init.h>
1814 #include <linux/mutex.h>
1915 #include <linux/skbuff.h>
2016 #include <linux/icmpv6.h>
17
+#include <net/ip6_route.h>
2118 #include <net/ipv6.h>
2219 #include <net/protocol.h>
2320 #include <net/xfrm.h>
....@@ -46,7 +43,7 @@
4643 handler != NULL; \
4744 handler = rcu_dereference(handler->next)) \
4845
49
-int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
46
+static int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
5047 {
5148 int ret;
5249 struct xfrm6_protocol *handler;
....@@ -61,7 +58,53 @@
6158
6259 return 0;
6360 }
64
-EXPORT_SYMBOL(xfrm6_rcv_cb);
61
+
62
+int xfrm6_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
63
+ int encap_type)
64
+{
65
+ int ret;
66
+ struct xfrm6_protocol *handler;
67
+ struct xfrm6_protocol __rcu **head = proto_handlers(nexthdr);
68
+
69
+ XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
70
+ XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
71
+ XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
72
+
73
+ if (!head)
74
+ goto out;
75
+
76
+ if (!skb_dst(skb)) {
77
+ const struct ipv6hdr *ip6h = ipv6_hdr(skb);
78
+ int flags = RT6_LOOKUP_F_HAS_SADDR;
79
+ struct dst_entry *dst;
80
+ struct flowi6 fl6 = {
81
+ .flowi6_iif = skb->dev->ifindex,
82
+ .daddr = ip6h->daddr,
83
+ .saddr = ip6h->saddr,
84
+ .flowlabel = ip6_flowinfo(ip6h),
85
+ .flowi6_mark = skb->mark,
86
+ .flowi6_proto = ip6h->nexthdr,
87
+ };
88
+
89
+ dst = ip6_route_input_lookup(dev_net(skb->dev), skb->dev, &fl6,
90
+ skb, flags);
91
+ if (dst->error)
92
+ goto drop;
93
+ skb_dst_set(skb, dst);
94
+ }
95
+
96
+ for_each_protocol_rcu(*head, handler)
97
+ if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL)
98
+ return ret;
99
+
100
+out:
101
+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
102
+
103
+drop:
104
+ kfree_skb(skb);
105
+ return 0;
106
+}
107
+EXPORT_SYMBOL(xfrm6_rcv_encap);
65108
66109 static int xfrm6_esp_rcv(struct sk_buff *skb)
67110 {
....@@ -80,14 +123,16 @@
80123 return 0;
81124 }
82125
83
-static void xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
126
+static int xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
84127 u8 type, u8 code, int offset, __be32 info)
85128 {
86129 struct xfrm6_protocol *handler;
87130
88131 for_each_protocol_rcu(esp6_handlers, handler)
89132 if (!handler->err_handler(skb, opt, type, code, offset, info))
90
- break;
133
+ return 0;
134
+
135
+ return -ENOENT;
91136 }
92137
93138 static int xfrm6_ah_rcv(struct sk_buff *skb)
....@@ -107,14 +152,16 @@
107152 return 0;
108153 }
109154
110
-static void xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
155
+static int xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
111156 u8 type, u8 code, int offset, __be32 info)
112157 {
113158 struct xfrm6_protocol *handler;
114159
115160 for_each_protocol_rcu(ah6_handlers, handler)
116161 if (!handler->err_handler(skb, opt, type, code, offset, info))
117
- break;
162
+ return 0;
163
+
164
+ return -ENOENT;
118165 }
119166
120167 static int xfrm6_ipcomp_rcv(struct sk_buff *skb)
....@@ -134,14 +181,16 @@
134181 return 0;
135182 }
136183
137
-static void xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
184
+static int xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
138185 u8 type, u8 code, int offset, __be32 info)
139186 {
140187 struct xfrm6_protocol *handler;
141188
142189 for_each_protocol_rcu(ipcomp6_handlers, handler)
143190 if (!handler->err_handler(skb, opt, type, code, offset, info))
144
- break;
191
+ return 0;
192
+
193
+ return -ENOENT;
145194 }
146195
147196 static const struct inet6_protocol esp6_protocol = {