hc
2023-12-11 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4
kernel/net/ipv6/seg6_local.c
....@@ -1,15 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * SR-IPv6 implementation
34 *
45 * Authors:
56 * David Lebrun <david.lebrun@uclouvain.be>
67 * eBPF support: Mathieu Xhonneux <m.xhonneux@gmail.com>
7
- *
8
- *
9
- * This program is free software; you can redistribute it and/or
10
- * modify it under the terms of the GNU General Public License
11
- * as published by the Free Software Foundation; either version
12
- * 2 of the License, or (at your option) any later version.
138 */
149
1510 #include <linux/types.h>
....@@ -87,7 +82,12 @@
8782 if (!pskb_may_pull(skb, srhoff + len))
8883 return NULL;
8984
90
- if (!seg6_validate_srh(srh, len))
85
+ /* note that pskb_may_pull may change pointers in header;
86
+ * for this reason it is necessary to reload them when needed.
87
+ */
88
+ srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
89
+
90
+ if (!seg6_validate_srh(srh, len, true))
9191 return NULL;
9292
9393 return srh;
....@@ -151,8 +151,9 @@
151151 *daddr = *addr;
152152 }
153153
154
-int seg6_lookup_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
155
- u32 tbl_id)
154
+static int
155
+seg6_lookup_any_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
156
+ u32 tbl_id, bool local_delivery)
156157 {
157158 struct net *net = dev_net(skb->dev);
158159 struct ipv6hdr *hdr = ipv6_hdr(skb);
....@@ -160,6 +161,7 @@
160161 struct dst_entry *dst = NULL;
161162 struct rt6_info *rt;
162163 struct flowi6 fl6;
164
+ int dev_flags = 0;
163165
164166 fl6.flowi6_iif = skb->dev->ifindex;
165167 fl6.daddr = nhaddr ? *nhaddr : hdr->daddr;
....@@ -184,7 +186,13 @@
184186 dst = &rt->dst;
185187 }
186188
187
- if (dst && dst->dev->flags & IFF_LOOPBACK && !dst->error) {
189
+ /* we want to discard traffic destined for local packet processing,
190
+ * if @local_delivery is set to false.
191
+ */
192
+ if (!local_delivery)
193
+ dev_flags |= IFF_LOOPBACK;
194
+
195
+ if (dst && (dst->dev->flags & dev_flags) && !dst->error) {
188196 dst_release(dst);
189197 dst = NULL;
190198 }
....@@ -199,6 +207,12 @@
199207 skb_dst_drop(skb);
200208 skb_dst_set(skb, dst);
201209 return dst->error;
210
+}
211
+
212
+int seg6_lookup_nexthop(struct sk_buff *skb,
213
+ struct in6_addr *nhaddr, u32 tbl_id)
214
+{
215
+ return seg6_lookup_any_nexthop(skb, nhaddr, tbl_id, false);
202216 }
203217
204218 /* regular endpoint function */
....@@ -268,7 +282,7 @@
268282 struct net_device *odev;
269283 struct ethhdr *eth;
270284
271
- if (!decap_and_validate(skb, NEXTHDR_NONE))
285
+ if (!decap_and_validate(skb, IPPROTO_ETHERNET))
272286 goto drop;
273287
274288 if (!pskb_may_pull(skb, ETH_HLEN))
....@@ -343,6 +357,8 @@
343357 if (!ipv6_addr_any(&slwt->nh6))
344358 nhaddr = &slwt->nh6;
345359
360
+ skb_set_transport_header(skb, sizeof(struct ipv6hdr));
361
+
346362 seg6_lookup_nexthop(skb, nhaddr, 0);
347363
348364 return dst_input(skb);
....@@ -372,6 +388,8 @@
372388
373389 skb_dst_drop(skb);
374390
391
+ skb_set_transport_header(skb, sizeof(struct iphdr));
392
+
375393 err = ip_route_input(skb, nhaddr, iph->saddr, 0, skb->dev);
376394 if (err)
377395 goto drop;
....@@ -392,7 +410,9 @@
392410 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
393411 goto drop;
394412
395
- seg6_lookup_nexthop(skb, NULL, slwt->table);
413
+ skb_set_transport_header(skb, sizeof(struct ipv6hdr));
414
+
415
+ seg6_lookup_any_nexthop(skb, NULL, slwt->table, true);
396416
397417 return dst_input(skb);
398418
....@@ -415,7 +435,6 @@
415435 if (err)
416436 goto drop;
417437
418
- ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
419438 skb_set_transport_header(skb, sizeof(struct ipv6hdr));
420439
421440 seg6_lookup_nexthop(skb, NULL, 0);
....@@ -447,7 +466,6 @@
447466 if (err)
448467 goto drop;
449468
450
- ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
451469 skb_set_transport_header(skb, sizeof(struct ipv6hdr));
452470
453471 seg6_lookup_nexthop(skb, NULL, 0);
....@@ -475,7 +493,7 @@
475493 return false;
476494
477495 srh->hdrlen = (u8)(srh_state->hdrlen >> 3);
478
- if (!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3))
496
+ if (!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3, true))
479497 return false;
480498
481499 srh_state->valid = true;
....@@ -650,7 +668,7 @@
650668 if (len < sizeof(*srh) + sizeof(struct in6_addr))
651669 return -EINVAL;
652670
653
- if (!seg6_validate_srh(srh, len))
671
+ if (!seg6_validate_srh(srh, len, false))
654672 return -EINVAL;
655673
656674 slwt->srh = kmemdup(srh, len, GFP_KERNEL);
....@@ -825,8 +843,9 @@
825843 int ret;
826844 u32 fd;
827845
828
- ret = nla_parse_nested(tb, SEG6_LOCAL_BPF_PROG_MAX,
829
- attrs[SEG6_LOCAL_BPF], bpf_prog_policy, NULL);
846
+ ret = nla_parse_nested_deprecated(tb, SEG6_LOCAL_BPF_PROG_MAX,
847
+ attrs[SEG6_LOCAL_BPF],
848
+ bpf_prog_policy, NULL);
830849 if (ret < 0)
831850 return ret;
832851
....@@ -855,7 +874,7 @@
855874 if (!slwt->bpf.prog)
856875 return 0;
857876
858
- nest = nla_nest_start(skb, SEG6_LOCAL_BPF);
877
+ nest = nla_nest_start_noflag(skb, SEG6_LOCAL_BPF);
859878 if (!nest)
860879 return -EMSGSIZE;
861880
....@@ -949,8 +968,9 @@
949968 return 0;
950969 }
951970
952
-static int seg6_local_build_state(struct nlattr *nla, unsigned int family,
953
- const void *cfg, struct lwtunnel_state **ts,
971
+static int seg6_local_build_state(struct net *net, struct nlattr *nla,
972
+ unsigned int family, const void *cfg,
973
+ struct lwtunnel_state **ts,
954974 struct netlink_ext_ack *extack)
955975 {
956976 struct nlattr *tb[SEG6_LOCAL_MAX + 1];
....@@ -961,8 +981,8 @@
961981 if (family != AF_INET6)
962982 return -EINVAL;
963983
964
- err = nla_parse_nested(tb, SEG6_LOCAL_MAX, nla, seg6_local_policy,
965
- extack);
984
+ err = nla_parse_nested_deprecated(tb, SEG6_LOCAL_MAX, nla,
985
+ seg6_local_policy, extack);
966986
967987 if (err < 0)
968988 return err;