~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/samples/bpf/tc_l2_redirect_kern.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* Copyright (c) 2016 Facebook
  2  *
  3  * This program is free software; you can redistribute it and/or
  4  * modify it under the terms of version 2 of the GNU General Public
  5  * License as published by the Free Software Foundation.
  6  */
  7 #define KBUILD_MODNAME "foo"
  8 #include <uapi/linux/bpf.h>
  9 #include <uapi/linux/if_ether.h>
 10 #include <uapi/linux/if_packet.h>
 11 #include <uapi/linux/ip.h>
 12 #include <uapi/linux/ipv6.h>
 13 #include <uapi/linux/in.h>
 14 #include <uapi/linux/tcp.h>
 15 #include <uapi/linux/filter.h>
 16 #include <uapi/linux/pkt_cls.h>
 17 #include <net/ipv6.h>
 18 #include <bpf/bpf_helpers.h>
 19 
 20 #define _htonl __builtin_bswap32
 21 
 22 #define PIN_GLOBAL_NS           2
 23 struct bpf_elf_map {
 24         __u32 type;
 25         __u32 size_key;
 26         __u32 size_value;
 27         __u32 max_elem;
 28         __u32 flags;
 29         __u32 id;
 30         __u32 pinning;
 31 };
 32 
 33 /* copy of 'struct ethhdr' without __packed */
 34 struct eth_hdr {
 35         unsigned char   h_dest[ETH_ALEN];
 36         unsigned char   h_source[ETH_ALEN];
 37         unsigned short  h_proto;
 38 };
 39 
 40 struct bpf_elf_map SEC("maps") tun_iface = {
 41         .type = BPF_MAP_TYPE_ARRAY,
 42         .size_key = sizeof(int),
 43         .size_value = sizeof(int),
 44         .pinning = PIN_GLOBAL_NS,
 45         .max_elem = 1,
 46 };
 47 
 48 static __always_inline bool is_vip_addr(__be16 eth_proto, __be32 daddr)
 49 {
 50         if (eth_proto == htons(ETH_P_IP))
 51                 return (_htonl(0xffffff00) & daddr) == _htonl(0x0a0a0100);
 52         else if (eth_proto == htons(ETH_P_IPV6))
 53                 return (daddr == _htonl(0x2401face));
 54 
 55         return false;
 56 }
 57 
 58 SEC("l2_to_iptun_ingress_forward")
 59 int _l2_to_iptun_ingress_forward(struct __sk_buff *skb)
 60 {
 61         struct bpf_tunnel_key tkey = {};
 62         void *data = (void *)(long)skb->data;
 63         struct eth_hdr *eth = data;
 64         void *data_end = (void *)(long)skb->data_end;
 65         int key = 0, *ifindex;
 66 
 67         int ret;
 68 
 69         if (data + sizeof(*eth) > data_end)
 70                 return TC_ACT_OK;
 71 
 72         ifindex = bpf_map_lookup_elem(&tun_iface, &key);
 73         if (!ifindex)
 74                 return TC_ACT_OK;
 75 
 76         if (eth->h_proto == htons(ETH_P_IP)) {
 77                 char fmt4[] = "ingress forward to ifindex:%d daddr4:%x\n";
 78                 struct iphdr *iph = data + sizeof(*eth);
 79 
 80                 if (data + sizeof(*eth) + sizeof(*iph) > data_end)
 81                         return TC_ACT_OK;
 82 
 83                 if (iph->protocol != IPPROTO_IPIP)
 84                         return TC_ACT_OK;
 85 
 86                 bpf_trace_printk(fmt4, sizeof(fmt4), *ifindex,
 87                                  _htonl(iph->daddr));
 88                 return bpf_redirect(*ifindex, BPF_F_INGRESS);
 89         } else if (eth->h_proto == htons(ETH_P_IPV6)) {
 90                 char fmt6[] = "ingress forward to ifindex:%d daddr6:%x::%x\n";
 91                 struct ipv6hdr *ip6h = data + sizeof(*eth);
 92 
 93                 if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
 94                         return TC_ACT_OK;
 95 
 96                 if (ip6h->nexthdr != IPPROTO_IPIP &&
 97                     ip6h->nexthdr != IPPROTO_IPV6)
 98                         return TC_ACT_OK;
 99 
100                 bpf_trace_printk(fmt6, sizeof(fmt6), *ifindex,
101                                  _htonl(ip6h->daddr.s6_addr32[0]),
102                                  _htonl(ip6h->daddr.s6_addr32[3]));
103                 return bpf_redirect(*ifindex, BPF_F_INGRESS);
104         }
105 
106         return TC_ACT_OK;
107 }
108 
109 SEC("l2_to_iptun_ingress_redirect")
110 int _l2_to_iptun_ingress_redirect(struct __sk_buff *skb)
111 {
112         struct bpf_tunnel_key tkey = {};
113         void *data = (void *)(long)skb->data;
114         struct eth_hdr *eth = data;
115         void *data_end = (void *)(long)skb->data_end;
116         int key = 0, *ifindex;
117 
118         int ret;
119 
120         if (data + sizeof(*eth) > data_end)
121                 return TC_ACT_OK;
122 
123         ifindex = bpf_map_lookup_elem(&tun_iface, &key);
124         if (!ifindex)
125                 return TC_ACT_OK;
126 
127         if (eth->h_proto == htons(ETH_P_IP)) {
128                 char fmt4[] = "e/ingress redirect daddr4:%x to ifindex:%d\n";
129                 struct iphdr *iph = data + sizeof(*eth);
130                 __be32 daddr = iph->daddr;
131 
132                 if (data + sizeof(*eth) + sizeof(*iph) > data_end)
133                         return TC_ACT_OK;
134 
135                 if (!is_vip_addr(eth->h_proto, daddr))
136                         return TC_ACT_OK;
137 
138                 bpf_trace_printk(fmt4, sizeof(fmt4), _htonl(daddr), *ifindex);
139         } else {
140                 return TC_ACT_OK;
141         }
142 
143         tkey.tunnel_id = 10000;
144         tkey.tunnel_ttl = 64;
145         tkey.remote_ipv4 = 0x0a020166; /* 10.2.1.102 */
146         bpf_skb_set_tunnel_key(skb, &tkey, sizeof(tkey), 0);
147         return bpf_redirect(*ifindex, 0);
148 }
149 
150 SEC("l2_to_ip6tun_ingress_redirect")
151 int _l2_to_ip6tun_ingress_redirect(struct __sk_buff *skb)
152 {
153         struct bpf_tunnel_key tkey = {};
154         void *data = (void *)(long)skb->data;
155         struct eth_hdr *eth = data;
156         void *data_end = (void *)(long)skb->data_end;
157         int key = 0, *ifindex;
158 
159         if (data + sizeof(*eth) > data_end)
160                 return TC_ACT_OK;
161 
162         ifindex = bpf_map_lookup_elem(&tun_iface, &key);
163         if (!ifindex)
164                 return TC_ACT_OK;
165 
166         if (eth->h_proto == htons(ETH_P_IP)) {
167                 char fmt4[] = "e/ingress redirect daddr4:%x to ifindex:%d\n";
168                 struct iphdr *iph = data + sizeof(*eth);
169 
170                 if (data + sizeof(*eth) + sizeof(*iph) > data_end)
171                         return TC_ACT_OK;
172 
173                 if (!is_vip_addr(eth->h_proto, iph->daddr))
174                         return TC_ACT_OK;
175 
176                 bpf_trace_printk(fmt4, sizeof(fmt4), _htonl(iph->daddr),
177                                  *ifindex);
178         } else if (eth->h_proto == htons(ETH_P_IPV6)) {
179                 char fmt6[] = "e/ingress redirect daddr6:%x to ifindex:%d\n";
180                 struct ipv6hdr *ip6h = data + sizeof(*eth);
181 
182                 if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
183                         return TC_ACT_OK;
184 
185                 if (!is_vip_addr(eth->h_proto, ip6h->daddr.s6_addr32[0]))
186                         return TC_ACT_OK;
187 
188                 bpf_trace_printk(fmt6, sizeof(fmt6),
189                                  _htonl(ip6h->daddr.s6_addr32[0]), *ifindex);
190         } else {
191                 return TC_ACT_OK;
192         }
193 
194         tkey.tunnel_id = 10000;
195         tkey.tunnel_ttl = 64;
196         /* 2401:db02:0:0:0:0:0:66 */
197         tkey.remote_ipv6[0] = _htonl(0x2401db02);
198         tkey.remote_ipv6[1] = 0;
199         tkey.remote_ipv6[2] = 0;
200         tkey.remote_ipv6[3] = _htonl(0x00000066);
201         bpf_skb_set_tunnel_key(skb, &tkey, sizeof(tkey), BPF_F_TUNINFO_IPV6);
202         return bpf_redirect(*ifindex, 0);
203 }
204 
205 SEC("drop_non_tun_vip")
206 int _drop_non_tun_vip(struct __sk_buff *skb)
207 {
208         struct bpf_tunnel_key tkey = {};
209         void *data = (void *)(long)skb->data;
210         struct eth_hdr *eth = data;
211         void *data_end = (void *)(long)skb->data_end;
212 
213         if (data + sizeof(*eth) > data_end)
214                 return TC_ACT_OK;
215 
216         if (eth->h_proto == htons(ETH_P_IP)) {
217                 struct iphdr *iph = data + sizeof(*eth);
218 
219                 if (data + sizeof(*eth) + sizeof(*iph) > data_end)
220                         return TC_ACT_OK;
221 
222                 if (is_vip_addr(eth->h_proto, iph->daddr))
223                         return TC_ACT_SHOT;
224         } else if (eth->h_proto == htons(ETH_P_IPV6)) {
225                 struct ipv6hdr *ip6h = data + sizeof(*eth);
226 
227                 if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
228                         return TC_ACT_OK;
229 
230                 if (is_vip_addr(eth->h_proto, ip6h->daddr.s6_addr32[0]))
231                         return TC_ACT_SHOT;
232         }
233 
234         return TC_ACT_OK;
235 }
236 
237 char _license[] SEC("license") = "GPL";
238 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php