cregit-Linux how code gets into the kernel

Release 4.16 samples/bpf/test_lwt_bpf.c

Directory: samples/bpf
/* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 */

#include <stdint.h>
#include <stddef.h>
#include <linux/bpf.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmpv6.h>
#include <linux/if_ether.h>
#include "bpf_helpers.h"
#include <string.h>


# define printk(fmt, ...)						\
		({                                                      \
                        char ____fmt[] = fmt;                           \
                        bpf_trace_printk(____fmt, sizeof(____fmt),      \
                                     ##__VA_ARGS__);                    \
                })


#define CB_MAGIC 1234

/* Test: Pass all packets through */
SEC("nop")

int do_nop(struct __sk_buff *skb) { return BPF_OK; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf13100.00%1100.00%
Total13100.00%1100.00%

/* Test: Verify context information can be accessed */ SEC("test_ctx")
int do_test_ctx(struct __sk_buff *skb) { skb->cb[0] = CB_MAGIC; printk("len %d hash %d protocol %d\n", skb->len, skb->hash, skb->protocol); printk("cb %d ingress_ifindex %d ifindex %d\n", skb->cb[0], skb->ingress_ifindex, skb->ifindex); return BPF_OK; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf59100.00%1100.00%
Total59100.00%1100.00%

/* Test: Ensure skb->cb[] buffer is cleared */ SEC("test_cb")
int do_test_cb(struct __sk_buff *skb) { printk("cb0: %x cb1: %x cb2: %x\n", skb->cb[0], skb->cb[1], skb->cb[2]); printk("cb3: %x cb4: %x\n", skb->cb[3], skb->cb[4]); return BPF_OK; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf58100.00%1100.00%
Total58100.00%1100.00%

/* Test: Verify skb data can be read */ SEC("test_data")
int do_test_data(struct __sk_buff *skb) { void *data = (void *)(long)skb->data; void *data_end = (void *)(long)skb->data_end; struct iphdr *iph = data; if (data + sizeof(*iph) > data_end) { printk("packet truncated\n"); return BPF_DROP; } printk("src: %x dst: %x\n", iph->saddr, iph->daddr); return BPF_OK; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf85100.00%1100.00%
Total85100.00%1100.00%

#define IP_CSUM_OFF offsetof(struct iphdr, check) #define IP_DST_OFF offsetof(struct iphdr, daddr) #define IP_SRC_OFF offsetof(struct iphdr, saddr) #define IP_PROTO_OFF offsetof(struct iphdr, protocol) #define TCP_CSUM_OFF offsetof(struct tcphdr, check) #define UDP_CSUM_OFF offsetof(struct udphdr, check) #define IS_PSEUDO 0x10
static inline int rewrite(struct __sk_buff *skb, uint32_t old_ip, uint32_t new_ip, int rw_daddr) { int ret, off = 0, flags = IS_PSEUDO; uint8_t proto; ret = bpf_skb_load_bytes(skb, IP_PROTO_OFF, &proto, 1); if (ret < 0) { printk("bpf_l4_csum_replace failed: %d\n", ret); return BPF_DROP; } switch (proto) { case IPPROTO_TCP: off = TCP_CSUM_OFF; break; case IPPROTO_UDP: off = UDP_CSUM_OFF; flags |= BPF_F_MARK_MANGLED_0; break; case IPPROTO_ICMPV6: off = offsetof(struct icmp6hdr, icmp6_cksum); break; } if (off) { ret = bpf_l4_csum_replace(skb, off, old_ip, new_ip, flags | sizeof(new_ip)); if (ret < 0) { printk("bpf_l4_csum_replace failed: %d\n"); return BPF_DROP; } } ret = bpf_l3_csum_replace(skb, IP_CSUM_OFF, old_ip, new_ip, sizeof(new_ip)); if (ret < 0) { printk("bpf_l3_csum_replace failed: %d\n", ret); return BPF_DROP; } if (rw_daddr) ret = bpf_skb_store_bytes(skb, IP_DST_OFF, &new_ip, sizeof(new_ip), 0); else ret = bpf_skb_store_bytes(skb, IP_SRC_OFF, &new_ip, sizeof(new_ip), 0); if (ret < 0) { printk("bpf_skb_store_bytes() failed: %d\n", ret); return BPF_DROP; } return BPF_OK; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf249100.00%1100.00%
Total249100.00%1100.00%

/* Test: Verify skb data can be modified */ SEC("test_rewrite")
int do_test_rewrite(struct __sk_buff *skb) { uint32_t old_ip, new_ip = 0x3fea8c0; int ret; ret = bpf_skb_load_bytes(skb, IP_DST_OFF, &old_ip, 4); if (ret < 0) { printk("bpf_skb_load_bytes failed: %d\n", ret); return BPF_DROP; } if (old_ip == 0x2fea8c0) { printk("out: rewriting from %x to %x\n", old_ip, new_ip); return rewrite(skb, old_ip, new_ip, 1); } return BPF_OK; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf84100.00%1100.00%
Total84100.00%1100.00%


static inline int __do_push_ll_and_redirect(struct __sk_buff *skb) { uint64_t smac = SRC_MAC, dmac = DST_MAC; int ret, ifindex = DST_IFINDEX; struct ethhdr ehdr; ret = bpf_skb_change_head(skb, 14, 0); if (ret < 0) { printk("skb_change_head() failed: %d\n", ret); } ehdr.h_proto = __constant_htons(ETH_P_IP); memcpy(&ehdr.h_source, &smac, 6); memcpy(&ehdr.h_dest, &dmac, 6); ret = bpf_skb_store_bytes(skb, 0, &ehdr, sizeof(ehdr), 0); if (ret < 0) { printk("skb_store_bytes() failed: %d\n", ret); return BPF_DROP; } return bpf_redirect(ifindex, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf138100.00%1100.00%
Total138100.00%1100.00%

SEC("push_ll_and_redirect_silent")
int do_push_ll_and_redirect_silent(struct __sk_buff *skb) { return __do_push_ll_and_redirect(skb); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf16100.00%1100.00%
Total16100.00%1100.00%

SEC("push_ll_and_redirect")
int do_push_ll_and_redirect(struct __sk_buff *skb) { int ret, ifindex = DST_IFINDEX; ret = __do_push_ll_and_redirect(skb); if (ret >= 0) printk("redirected to %d\n", ifindex); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf40100.00%1100.00%
Total40100.00%1100.00%


static inline void __fill_garbage(struct __sk_buff *skb) { uint64_t f = 0xFFFFFFFFFFFFFFFF; bpf_skb_store_bytes(skb, 0, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 8, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 16, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 24, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 32, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 40, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 48, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 56, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 64, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 72, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 80, &f, sizeof(f), 0); bpf_skb_store_bytes(skb, 88, &f, sizeof(f), 0); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf221100.00%1100.00%
Total221100.00%1100.00%

SEC("fill_garbage")
int do_fill_garbage(struct __sk_buff *skb) { __fill_garbage(skb); printk("Set initial 96 bytes of header to FF\n"); return BPF_OK; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf23100.00%1100.00%
Total23100.00%1100.00%

SEC("fill_garbage_and_redirect")
int do_fill_garbage_and_redirect(struct __sk_buff *skb) { int ifindex = DST_IFINDEX; __fill_garbage(skb); printk("redirected to %d\n", ifindex); return bpf_redirect(ifindex, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf35100.00%1100.00%
Total35100.00%1100.00%

/* Drop all packets */ SEC("drop_all")
int do_drop_all(struct __sk_buff *skb) { printk("dropping with: %d\n", BPF_DROP); return BPF_DROP; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf20100.00%1100.00%
Total20100.00%1100.00%

char _license[] SEC("license") = "GPL";

Overall Contributors

PersonTokensPropCommitsCommitProp
Thomas Graf1176100.00%1100.00%
Total1176100.00%1100.00%
Directory: samples/bpf
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.