^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * SR-IPv6 implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * David Lebrun <david.lebrun@uclouvain.be>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * eBPF support: Mathieu Xhonneux <m.xhonneux@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <net/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <net/lwtunnel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <net/netevent.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/netns/generic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/ip6_fib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <net/route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/seg6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/seg6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/seg6_local.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <net/addrconf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <net/ip6_route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <net/dst_cache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <net/ip_tunnels.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #ifdef CONFIG_IPV6_SEG6_HMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <net/seg6_hmac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <net/seg6_local.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/bpf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct seg6_local_lwt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct seg6_action_desc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) unsigned long attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int (*input)(struct sk_buff *skb, struct seg6_local_lwt *slwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int static_headroom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct bpf_lwt_prog {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct bpf_prog *prog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct seg6_local_lwt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct in_addr nh4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct in6_addr nh6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int iif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int oif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct bpf_lwt_prog bpf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int headroom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct seg6_action_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static struct seg6_local_lwt *seg6_local_lwtunnel(struct lwtunnel_state *lwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return (struct seg6_local_lwt *)lwt->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static struct ipv6_sr_hdr *get_srh(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int len, srhoff = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (!pskb_may_pull(skb, srhoff + sizeof(*srh)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) len = (srh->hdrlen + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!pskb_may_pull(skb, srhoff + len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* note that pskb_may_pull may change pointers in header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * for this reason it is necessary to reload them when needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!seg6_validate_srh(srh, len, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static struct ipv6_sr_hdr *get_and_validate_srh(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) srh = get_srh(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (!srh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (srh->segments_left == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #ifdef CONFIG_IPV6_SEG6_HMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (!seg6_hmac_validate_skb(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static bool decap_and_validate(struct sk_buff *skb, int proto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned int off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) srh = get_srh(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (srh && srh->segments_left > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #ifdef CONFIG_IPV6_SEG6_HMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (srh && !seg6_hmac_validate_skb(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (ipv6_find_hdr(skb, &off, proto, NULL, NULL) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (!pskb_pull(skb, off))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) skb_postpull_rcsum(skb, skb_network_header(skb), off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (iptunnel_pull_offloads(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static void advance_nextseg(struct ipv6_sr_hdr *srh, struct in6_addr *daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct in6_addr *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) srh->segments_left--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) addr = srh->segments + srh->segments_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) *daddr = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) seg6_lookup_any_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) u32 tbl_id, bool local_delivery)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct net *net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct ipv6hdr *hdr = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int flags = RT6_LOOKUP_F_HAS_SADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct dst_entry *dst = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct rt6_info *rt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct flowi6 fl6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int dev_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) fl6.flowi6_iif = skb->dev->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) fl6.daddr = nhaddr ? *nhaddr : hdr->daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) fl6.saddr = hdr->saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) fl6.flowlabel = ip6_flowinfo(hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) fl6.flowi6_mark = skb->mark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) fl6.flowi6_proto = hdr->nexthdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (nhaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (!tbl_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) dst = ip6_route_input_lookup(net, skb->dev, &fl6, skb, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct fib6_table *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) table = fib6_get_table(net, tbl_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (!table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) rt = ip6_pol_route(net, table, 0, &fl6, skb, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) dst = &rt->dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* we want to discard traffic destined for local packet processing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * if @local_delivery is set to false.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (!local_delivery)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) dev_flags |= IFF_LOOPBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (dst && (dst->dev->flags & dev_flags) && !dst->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) dst_release(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) dst = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (!dst) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) rt = net->ipv6.ip6_blk_hole_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) dst = &rt->dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dst_hold(dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) skb_dst_drop(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) skb_dst_set(skb, dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return dst->error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int seg6_lookup_nexthop(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct in6_addr *nhaddr, u32 tbl_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return seg6_lookup_any_nexthop(skb, nhaddr, tbl_id, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /* regular endpoint function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static int input_action_end(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) srh = get_and_validate_srh(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (!srh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) seg6_lookup_nexthop(skb, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* regular endpoint, and forward to specified nexthop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static int input_action_end_x(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) srh = get_and_validate_srh(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (!srh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) seg6_lookup_nexthop(skb, &slwt->nh6, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static int input_action_end_t(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) srh = get_and_validate_srh(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (!srh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) seg6_lookup_nexthop(skb, NULL, slwt->table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* decapsulate and forward inner L2 frame on specified interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static int input_action_end_dx2(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct net *net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct net_device *odev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct ethhdr *eth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!decap_and_validate(skb, IPPROTO_ETHERNET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (!pskb_may_pull(skb, ETH_HLEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) skb_reset_mac_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) eth = (struct ethhdr *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* To determine the frame's protocol, we assume it is 802.3. This avoids
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * a call to eth_type_trans(), which is not really relevant for our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * use case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (!eth_proto_is_802_3(eth->h_proto))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) odev = dev_get_by_index_rcu(net, slwt->oif);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (!odev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* As we accept Ethernet frames, make sure the egress device is of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * the correct type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (odev->type != ARPHRD_ETHER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (!(odev->flags & IFF_UP) || !netif_carrier_ok(odev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) skb_orphan(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (skb_warn_if_lro(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) skb_forward_csum(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (skb->len - ETH_HLEN > odev->mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) skb->dev = odev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) skb->protocol = eth->h_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return dev_queue_xmit(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* decapsulate and forward to specified nexthop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static int input_action_end_dx6(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct in6_addr *nhaddr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /* this function accepts IPv6 encapsulated packets, with either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * an SRH with SL=0, or no SRH.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (!decap_and_validate(skb, IPPROTO_IPV6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* The inner packet is not associated to any local interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * so we do not call netif_rx().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * If slwt->nh6 is set to ::, then lookup the nexthop for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * inner packet's DA. Otherwise, use the specified nexthop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (!ipv6_addr_any(&slwt->nh6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) nhaddr = &slwt->nh6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) skb_set_transport_header(skb, sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) seg6_lookup_nexthop(skb, nhaddr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static int input_action_end_dx4(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct iphdr *iph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) __be32 nhaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (!decap_and_validate(skb, IPPROTO_IPIP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (!pskb_may_pull(skb, sizeof(struct iphdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) skb->protocol = htons(ETH_P_IP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) iph = ip_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) nhaddr = slwt->nh4.s_addr ?: iph->daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) skb_dst_drop(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) skb_set_transport_header(skb, sizeof(struct iphdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) err = ip_route_input(skb, nhaddr, iph->saddr, 0, skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static int input_action_end_dt6(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (!decap_and_validate(skb, IPPROTO_IPV6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) skb_set_transport_header(skb, sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) seg6_lookup_any_nexthop(skb, NULL, slwt->table, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* push an SRH on top of the current one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int input_action_end_b6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) int err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) srh = get_and_validate_srh(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (!srh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) err = seg6_do_srh_inline(skb, slwt->srh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) skb_set_transport_header(skb, sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) seg6_lookup_nexthop(skb, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* encapsulate within an outer IPv6 header and a specified SRH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static int input_action_end_b6_encap(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) srh = get_and_validate_srh(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!srh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) skb_reset_inner_headers(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) skb->encapsulation = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) err = seg6_do_srh_encap(skb, slwt->srh, IPPROTO_IPV6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) skb_set_transport_header(skb, sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) seg6_lookup_nexthop(skb, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) DEFINE_PER_CPU(struct seg6_bpf_srh_state, seg6_bpf_srh_states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) bool seg6_bpf_has_valid_srh(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) struct seg6_bpf_srh_state *srh_state =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) this_cpu_ptr(&seg6_bpf_srh_states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct ipv6_sr_hdr *srh = srh_state->srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (unlikely(srh == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (unlikely(!srh_state->valid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if ((srh_state->hdrlen & 7) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) srh->hdrlen = (u8)(srh_state->hdrlen >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) srh_state->valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static int input_action_end_bpf(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct seg6_bpf_srh_state *srh_state =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) this_cpu_ptr(&seg6_bpf_srh_states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) srh = get_and_validate_srh(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (!srh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* preempt_disable is needed to protect the per-CPU buffer srh_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * which is also accessed by the bpf_lwt_seg6_* helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) srh_state->srh = srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) srh_state->hdrlen = srh->hdrlen << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) srh_state->valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) bpf_compute_data_pointers(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ret = bpf_prog_run_save_cb(slwt->bpf.prog, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) case BPF_OK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) case BPF_REDIRECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) case BPF_DROP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) pr_warn_once("bpf-seg6local: Illegal return value %u\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (srh_state->srh && !seg6_bpf_has_valid_srh(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (ret != BPF_REDIRECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) seg6_lookup_nexthop(skb, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static struct seg6_action_desc seg6_action_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) .action = SEG6_LOCAL_ACTION_END,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) .attrs = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) .input = input_action_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) .action = SEG6_LOCAL_ACTION_END_X,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) .attrs = (1 << SEG6_LOCAL_NH6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) .input = input_action_end_x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) .action = SEG6_LOCAL_ACTION_END_T,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) .attrs = (1 << SEG6_LOCAL_TABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) .input = input_action_end_t,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) .action = SEG6_LOCAL_ACTION_END_DX2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) .attrs = (1 << SEG6_LOCAL_OIF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) .input = input_action_end_dx2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) .action = SEG6_LOCAL_ACTION_END_DX6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) .attrs = (1 << SEG6_LOCAL_NH6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) .input = input_action_end_dx6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .action = SEG6_LOCAL_ACTION_END_DX4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) .attrs = (1 << SEG6_LOCAL_NH4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .input = input_action_end_dx4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) .action = SEG6_LOCAL_ACTION_END_DT6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .attrs = (1 << SEG6_LOCAL_TABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) .input = input_action_end_dt6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) .action = SEG6_LOCAL_ACTION_END_B6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) .attrs = (1 << SEG6_LOCAL_SRH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) .input = input_action_end_b6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) .action = SEG6_LOCAL_ACTION_END_B6_ENCAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) .attrs = (1 << SEG6_LOCAL_SRH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) .input = input_action_end_b6_encap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) .static_headroom = sizeof(struct ipv6hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) .action = SEG6_LOCAL_ACTION_END_BPF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) .attrs = (1 << SEG6_LOCAL_BPF),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) .input = input_action_end_bpf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static struct seg6_action_desc *__get_action_desc(int action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct seg6_action_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) int i, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) count = ARRAY_SIZE(seg6_action_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) desc = &seg6_action_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (desc->action == action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static int seg6_local_input(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct dst_entry *orig_dst = skb_dst(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct seg6_action_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct seg6_local_lwt *slwt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (skb->protocol != htons(ETH_P_IPV6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) slwt = seg6_local_lwtunnel(orig_dst->lwtstate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) desc = slwt->desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) return desc->input(skb, slwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static const struct nla_policy seg6_local_policy[SEG6_LOCAL_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) [SEG6_LOCAL_ACTION] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) [SEG6_LOCAL_SRH] = { .type = NLA_BINARY },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) [SEG6_LOCAL_TABLE] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) [SEG6_LOCAL_NH4] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) .len = sizeof(struct in_addr) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) [SEG6_LOCAL_NH6] = { .type = NLA_BINARY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) .len = sizeof(struct in6_addr) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) [SEG6_LOCAL_IIF] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) [SEG6_LOCAL_OIF] = { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) [SEG6_LOCAL_BPF] = { .type = NLA_NESTED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static int parse_nla_srh(struct nlattr **attrs, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) srh = nla_data(attrs[SEG6_LOCAL_SRH]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) len = nla_len(attrs[SEG6_LOCAL_SRH]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /* SRH must contain at least one segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (len < sizeof(*srh) + sizeof(struct in6_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (!seg6_validate_srh(srh, len, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) slwt->srh = kmemdup(srh, len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (!slwt->srh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) slwt->headroom += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static int put_nla_srh(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) struct ipv6_sr_hdr *srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) struct nlattr *nla;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) srh = slwt->srh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) len = (srh->hdrlen + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) nla = nla_reserve(skb, SEG6_LOCAL_SRH, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (!nla)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) memcpy(nla_data(nla), srh, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) static int cmp_nla_srh(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int len = (a->srh->hdrlen + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (len != ((b->srh->hdrlen + 1) << 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return memcmp(a->srh, b->srh, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) static int parse_nla_table(struct nlattr **attrs, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) slwt->table = nla_get_u32(attrs[SEG6_LOCAL_TABLE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static int put_nla_table(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (nla_put_u32(skb, SEG6_LOCAL_TABLE, slwt->table))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static int cmp_nla_table(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (a->table != b->table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static int parse_nla_nh4(struct nlattr **attrs, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) memcpy(&slwt->nh4, nla_data(attrs[SEG6_LOCAL_NH4]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) sizeof(struct in_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) static int put_nla_nh4(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct nlattr *nla;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) nla = nla_reserve(skb, SEG6_LOCAL_NH4, sizeof(struct in_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (!nla)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) memcpy(nla_data(nla), &slwt->nh4, sizeof(struct in_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) static int cmp_nla_nh4(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return memcmp(&a->nh4, &b->nh4, sizeof(struct in_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) static int parse_nla_nh6(struct nlattr **attrs, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) memcpy(&slwt->nh6, nla_data(attrs[SEG6_LOCAL_NH6]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) sizeof(struct in6_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static int put_nla_nh6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) struct nlattr *nla;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) nla = nla_reserve(skb, SEG6_LOCAL_NH6, sizeof(struct in6_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (!nla)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) memcpy(nla_data(nla), &slwt->nh6, sizeof(struct in6_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) static int cmp_nla_nh6(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return memcmp(&a->nh6, &b->nh6, sizeof(struct in6_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static int parse_nla_iif(struct nlattr **attrs, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) slwt->iif = nla_get_u32(attrs[SEG6_LOCAL_IIF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static int put_nla_iif(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (nla_put_u32(skb, SEG6_LOCAL_IIF, slwt->iif))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) static int cmp_nla_iif(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (a->iif != b->iif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) static int parse_nla_oif(struct nlattr **attrs, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) slwt->oif = nla_get_u32(attrs[SEG6_LOCAL_OIF]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) static int put_nla_oif(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (nla_put_u32(skb, SEG6_LOCAL_OIF, slwt->oif))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static int cmp_nla_oif(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (a->oif != b->oif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) #define MAX_PROG_NAME 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) static const struct nla_policy bpf_prog_policy[SEG6_LOCAL_BPF_PROG_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) [SEG6_LOCAL_BPF_PROG] = { .type = NLA_U32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) [SEG6_LOCAL_BPF_PROG_NAME] = { .type = NLA_NUL_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) .len = MAX_PROG_NAME },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static int parse_nla_bpf(struct nlattr **attrs, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) struct nlattr *tb[SEG6_LOCAL_BPF_PROG_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct bpf_prog *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) u32 fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) ret = nla_parse_nested_deprecated(tb, SEG6_LOCAL_BPF_PROG_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) attrs[SEG6_LOCAL_BPF],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) bpf_prog_policy, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (!tb[SEG6_LOCAL_BPF_PROG] || !tb[SEG6_LOCAL_BPF_PROG_NAME])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) slwt->bpf.name = nla_memdup(tb[SEG6_LOCAL_BPF_PROG_NAME], GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (!slwt->bpf.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) fd = nla_get_u32(tb[SEG6_LOCAL_BPF_PROG]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) p = bpf_prog_get_type(fd, BPF_PROG_TYPE_LWT_SEG6LOCAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (IS_ERR(p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) kfree(slwt->bpf.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return PTR_ERR(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) slwt->bpf.prog = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static int put_nla_bpf(struct sk_buff *skb, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct nlattr *nest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (!slwt->bpf.prog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) nest = nla_nest_start_noflag(skb, SEG6_LOCAL_BPF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (!nest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (nla_put_u32(skb, SEG6_LOCAL_BPF_PROG, slwt->bpf.prog->aux->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (slwt->bpf.name &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) nla_put_string(skb, SEG6_LOCAL_BPF_PROG_NAME, slwt->bpf.name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return nla_nest_end(skb, nest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static int cmp_nla_bpf(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (!a->bpf.name && !b->bpf.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (!a->bpf.name || !b->bpf.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return strcmp(a->bpf.name, b->bpf.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct seg6_action_param {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int (*parse)(struct nlattr **attrs, struct seg6_local_lwt *slwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) int (*put)(struct sk_buff *skb, struct seg6_local_lwt *slwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) int (*cmp)(struct seg6_local_lwt *a, struct seg6_local_lwt *b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static struct seg6_action_param seg6_action_params[SEG6_LOCAL_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) [SEG6_LOCAL_SRH] = { .parse = parse_nla_srh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) .put = put_nla_srh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) .cmp = cmp_nla_srh },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) [SEG6_LOCAL_TABLE] = { .parse = parse_nla_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) .put = put_nla_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) .cmp = cmp_nla_table },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) [SEG6_LOCAL_NH4] = { .parse = parse_nla_nh4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .put = put_nla_nh4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .cmp = cmp_nla_nh4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) [SEG6_LOCAL_NH6] = { .parse = parse_nla_nh6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) .put = put_nla_nh6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) .cmp = cmp_nla_nh6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) [SEG6_LOCAL_IIF] = { .parse = parse_nla_iif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .put = put_nla_iif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) .cmp = cmp_nla_iif },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) [SEG6_LOCAL_OIF] = { .parse = parse_nla_oif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) .put = put_nla_oif,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) .cmp = cmp_nla_oif },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) [SEG6_LOCAL_BPF] = { .parse = parse_nla_bpf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) .put = put_nla_bpf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) .cmp = cmp_nla_bpf },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct seg6_action_param *param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) struct seg6_action_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) desc = __get_action_desc(slwt->action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (!desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (!desc->input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) slwt->desc = desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) slwt->headroom += desc->static_headroom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (desc->attrs & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (!attrs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) param = &seg6_action_params[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) err = param->parse(attrs, slwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) static int seg6_local_build_state(struct net *net, struct nlattr *nla,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) unsigned int family, const void *cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct lwtunnel_state **ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) struct nlattr *tb[SEG6_LOCAL_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) struct lwtunnel_state *newts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) struct seg6_local_lwt *slwt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (family != AF_INET6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) err = nla_parse_nested_deprecated(tb, SEG6_LOCAL_MAX, nla,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) seg6_local_policy, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) if (!tb[SEG6_LOCAL_ACTION])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) newts = lwtunnel_state_alloc(sizeof(*slwt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) if (!newts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) slwt = seg6_local_lwtunnel(newts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) slwt->action = nla_get_u32(tb[SEG6_LOCAL_ACTION]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) err = parse_nla_action(tb, slwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) newts->type = LWTUNNEL_ENCAP_SEG6_LOCAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) newts->flags = LWTUNNEL_STATE_INPUT_REDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) newts->headroom = slwt->headroom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) *ts = newts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) kfree(slwt->srh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) kfree(newts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) static void seg6_local_destroy_state(struct lwtunnel_state *lwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) kfree(slwt->srh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (slwt->desc->attrs & (1 << SEG6_LOCAL_BPF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) kfree(slwt->bpf.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) bpf_prog_put(slwt->bpf.prog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) static int seg6_local_fill_encap(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) struct lwtunnel_state *lwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) struct seg6_action_param *param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (nla_put_u32(skb, SEG6_LOCAL_ACTION, slwt->action))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (slwt->desc->attrs & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) param = &seg6_action_params[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) err = param->put(skb, slwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) static int seg6_local_get_encap_size(struct lwtunnel_state *lwt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) unsigned long attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) int nlsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) nlsize = nla_total_size(4); /* action */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) attrs = slwt->desc->attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (attrs & (1 << SEG6_LOCAL_SRH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) nlsize += nla_total_size((slwt->srh->hdrlen + 1) << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (attrs & (1 << SEG6_LOCAL_TABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) nlsize += nla_total_size(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (attrs & (1 << SEG6_LOCAL_NH4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) nlsize += nla_total_size(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (attrs & (1 << SEG6_LOCAL_NH6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) nlsize += nla_total_size(16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (attrs & (1 << SEG6_LOCAL_IIF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) nlsize += nla_total_size(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (attrs & (1 << SEG6_LOCAL_OIF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) nlsize += nla_total_size(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (attrs & (1 << SEG6_LOCAL_BPF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) nlsize += nla_total_size(sizeof(struct nlattr)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) nla_total_size(MAX_PROG_NAME) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) nla_total_size(4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) return nlsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) static int seg6_local_cmp_encap(struct lwtunnel_state *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) struct lwtunnel_state *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) struct seg6_local_lwt *slwt_a, *slwt_b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct seg6_action_param *param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) slwt_a = seg6_local_lwtunnel(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) slwt_b = seg6_local_lwtunnel(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (slwt_a->action != slwt_b->action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (slwt_a->desc->attrs != slwt_b->desc->attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (slwt_a->desc->attrs & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) param = &seg6_action_params[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (param->cmp(slwt_a, slwt_b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) static const struct lwtunnel_encap_ops seg6_local_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) .build_state = seg6_local_build_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) .destroy_state = seg6_local_destroy_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) .input = seg6_local_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) .fill_encap = seg6_local_fill_encap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) .get_encap_size = seg6_local_get_encap_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) .cmp_encap = seg6_local_cmp_encap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) int __init seg6_local_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) return lwtunnel_encap_add_ops(&seg6_local_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) LWTUNNEL_ENCAP_SEG6_LOCAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) void seg6_local_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) lwtunnel_encap_del_ops(&seg6_local_ops, LWTUNNEL_ENCAP_SEG6_LOCAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }