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

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

Version: ~ [ linux-5.6-rc7 ] ~ [ linux-5.5.11 ] ~ [ linux-5.4.27 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.112 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.174 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.217 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.217 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.82 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
  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  * This program is distributed in the hope that it will be useful, but
  8  * WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 10  * General Public License for more details.
 11  */
 12 
 13 #include <stdint.h>
 14 #include <stddef.h>
 15 #include <linux/bpf.h>
 16 #include <linux/ip.h>
 17 #include <linux/in.h>
 18 #include <linux/in6.h>
 19 #include <linux/tcp.h>
 20 #include <linux/udp.h>
 21 #include <linux/icmpv6.h>
 22 #include <linux/if_ether.h>
 23 #include "bpf_helpers.h"
 24 #include <string.h>
 25 
 26 # define printk(fmt, ...)                                               \
 27                 ({                                                      \
 28                         char ____fmt[] = fmt;                           \
 29                         bpf_trace_printk(____fmt, sizeof(____fmt),      \
 30                                      ##__VA_ARGS__);                    \
 31                 })
 32 
 33 #define CB_MAGIC 1234
 34 
 35 /* Test: Pass all packets through */
 36 SEC("nop")
 37 int do_nop(struct __sk_buff *skb)
 38 {
 39         return BPF_OK;
 40 }
 41 
 42 /* Test: Verify context information can be accessed */
 43 SEC("test_ctx")
 44 int do_test_ctx(struct __sk_buff *skb)
 45 {
 46         skb->cb[0] = CB_MAGIC;
 47         printk("len %d hash %d protocol %d\n", skb->len, skb->hash,
 48                skb->protocol);
 49         printk("cb %d ingress_ifindex %d ifindex %d\n", skb->cb[0],
 50                skb->ingress_ifindex, skb->ifindex);
 51 
 52         return BPF_OK;
 53 }
 54 
 55 /* Test: Ensure skb->cb[] buffer is cleared */
 56 SEC("test_cb")
 57 int do_test_cb(struct __sk_buff *skb)
 58 {
 59         printk("cb0: %x cb1: %x cb2: %x\n", skb->cb[0], skb->cb[1],
 60                skb->cb[2]);
 61         printk("cb3: %x cb4: %x\n", skb->cb[3], skb->cb[4]);
 62 
 63         return BPF_OK;
 64 }
 65 
 66 /* Test: Verify skb data can be read */
 67 SEC("test_data")
 68 int do_test_data(struct __sk_buff *skb)
 69 {
 70         void *data = (void *)(long)skb->data;
 71         void *data_end = (void *)(long)skb->data_end;
 72         struct iphdr *iph = data;
 73 
 74         if (data + sizeof(*iph) > data_end) {
 75                 printk("packet truncated\n");
 76                 return BPF_DROP;
 77         }
 78 
 79         printk("src: %x dst: %x\n", iph->saddr, iph->daddr);
 80 
 81         return BPF_OK;
 82 }
 83 
 84 #define IP_CSUM_OFF offsetof(struct iphdr, check)
 85 #define IP_DST_OFF offsetof(struct iphdr, daddr)
 86 #define IP_SRC_OFF offsetof(struct iphdr, saddr)
 87 #define IP_PROTO_OFF offsetof(struct iphdr, protocol)
 88 #define TCP_CSUM_OFF offsetof(struct tcphdr, check)
 89 #define UDP_CSUM_OFF offsetof(struct udphdr, check)
 90 #define IS_PSEUDO 0x10
 91 
 92 static inline int rewrite(struct __sk_buff *skb, uint32_t old_ip,
 93                           uint32_t new_ip, int rw_daddr)
 94 {
 95         int ret, off = 0, flags = IS_PSEUDO;
 96         uint8_t proto;
 97 
 98         ret = bpf_skb_load_bytes(skb, IP_PROTO_OFF, &proto, 1);
 99         if (ret < 0) {
100                 printk("bpf_l4_csum_replace failed: %d\n", ret);
101                 return BPF_DROP;
102         }
103 
104         switch (proto) {
105         case IPPROTO_TCP:
106                 off = TCP_CSUM_OFF;
107                 break;
108 
109         case IPPROTO_UDP:
110                 off = UDP_CSUM_OFF;
111                 flags |= BPF_F_MARK_MANGLED_0;
112                 break;
113 
114         case IPPROTO_ICMPV6:
115                 off = offsetof(struct icmp6hdr, icmp6_cksum);
116                 break;
117         }
118 
119         if (off) {
120                 ret = bpf_l4_csum_replace(skb, off, old_ip, new_ip,
121                                           flags | sizeof(new_ip));
122                 if (ret < 0) {
123                         printk("bpf_l4_csum_replace failed: %d\n");
124                         return BPF_DROP;
125                 }
126         }
127 
128         ret = bpf_l3_csum_replace(skb, IP_CSUM_OFF, old_ip, new_ip, sizeof(new_ip));
129         if (ret < 0) {
130                 printk("bpf_l3_csum_replace failed: %d\n", ret);
131                 return BPF_DROP;
132         }
133 
134         if (rw_daddr)
135                 ret = bpf_skb_store_bytes(skb, IP_DST_OFF, &new_ip, sizeof(new_ip), 0);
136         else
137                 ret = bpf_skb_store_bytes(skb, IP_SRC_OFF, &new_ip, sizeof(new_ip), 0);
138 
139         if (ret < 0) {
140                 printk("bpf_skb_store_bytes() failed: %d\n", ret);
141                 return BPF_DROP;
142         }
143 
144         return BPF_OK;
145 }
146 
147 /* Test: Verify skb data can be modified */
148 SEC("test_rewrite")
149 int do_test_rewrite(struct __sk_buff *skb)
150 {
151         uint32_t old_ip, new_ip = 0x3fea8c0;
152         int ret;
153 
154         ret = bpf_skb_load_bytes(skb, IP_DST_OFF, &old_ip, 4);
155         if (ret < 0) {
156                 printk("bpf_skb_load_bytes failed: %d\n", ret);
157                 return BPF_DROP;
158         }
159 
160         if (old_ip == 0x2fea8c0) {
161                 printk("out: rewriting from %x to %x\n", old_ip, new_ip);
162                 return rewrite(skb, old_ip, new_ip, 1);
163         }
164 
165         return BPF_OK;
166 }
167 
168 static inline int __do_push_ll_and_redirect(struct __sk_buff *skb)
169 {
170         uint64_t smac = SRC_MAC, dmac = DST_MAC;
171         int ret, ifindex = DST_IFINDEX;
172         struct ethhdr ehdr;
173 
174         ret = bpf_skb_change_head(skb, 14, 0);
175         if (ret < 0) {
176                 printk("skb_change_head() failed: %d\n", ret);
177         }
178 
179         ehdr.h_proto = __constant_htons(ETH_P_IP);
180         memcpy(&ehdr.h_source, &smac, 6);
181         memcpy(&ehdr.h_dest, &dmac, 6);
182 
183         ret = bpf_skb_store_bytes(skb, 0, &ehdr, sizeof(ehdr), 0);
184         if (ret < 0) {
185                 printk("skb_store_bytes() failed: %d\n", ret);
186                 return BPF_DROP;
187         }
188 
189         return bpf_redirect(ifindex, 0);
190 }
191 
192 SEC("push_ll_and_redirect_silent")
193 int do_push_ll_and_redirect_silent(struct __sk_buff *skb)
194 {
195         return __do_push_ll_and_redirect(skb);
196 }
197 
198 SEC("push_ll_and_redirect")
199 int do_push_ll_and_redirect(struct __sk_buff *skb)
200 {
201         int ret, ifindex = DST_IFINDEX;
202 
203         ret = __do_push_ll_and_redirect(skb);
204         if (ret >= 0)
205                 printk("redirected to %d\n", ifindex);
206 
207         return ret;
208 }
209 
210 static inline void __fill_garbage(struct __sk_buff *skb)
211 {
212         uint64_t f = 0xFFFFFFFFFFFFFFFF;
213 
214         bpf_skb_store_bytes(skb, 0, &f, sizeof(f), 0);
215         bpf_skb_store_bytes(skb, 8, &f, sizeof(f), 0);
216         bpf_skb_store_bytes(skb, 16, &f, sizeof(f), 0);
217         bpf_skb_store_bytes(skb, 24, &f, sizeof(f), 0);
218         bpf_skb_store_bytes(skb, 32, &f, sizeof(f), 0);
219         bpf_skb_store_bytes(skb, 40, &f, sizeof(f), 0);
220         bpf_skb_store_bytes(skb, 48, &f, sizeof(f), 0);
221         bpf_skb_store_bytes(skb, 56, &f, sizeof(f), 0);
222         bpf_skb_store_bytes(skb, 64, &f, sizeof(f), 0);
223         bpf_skb_store_bytes(skb, 72, &f, sizeof(f), 0);
224         bpf_skb_store_bytes(skb, 80, &f, sizeof(f), 0);
225         bpf_skb_store_bytes(skb, 88, &f, sizeof(f), 0);
226 }
227 
228 SEC("fill_garbage")
229 int do_fill_garbage(struct __sk_buff *skb)
230 {
231         __fill_garbage(skb);
232         printk("Set initial 96 bytes of header to FF\n");
233         return BPF_OK;
234 }
235 
236 SEC("fill_garbage_and_redirect")
237 int do_fill_garbage_and_redirect(struct __sk_buff *skb)
238 {
239         int ifindex = DST_IFINDEX;
240         __fill_garbage(skb);
241         printk("redirected to %d\n", ifindex);
242         return bpf_redirect(ifindex, 0);
243 }
244 
245 /* Drop all packets */
246 SEC("drop_all")
247 int do_drop_all(struct __sk_buff *skb)
248 {
249         printk("dropping with: %d\n", BPF_DROP);
250         return BPF_DROP;
251 }
252 
253 char _license[] SEC("license") = "GPL";
254 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp