Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdint.h>
- #include <arpa/inet.h>
- #include <linux/bpf.h>
- #include <linux/if_ether.h>
- #include <linux/ip.h>
- #include <linux/icmp.h>
- /*
- * Sample XDP program, drop even ping replies and randomly change the TTL of the odd one.
- * compile it with:
- * clang -O3 -target bpf -c ebpf.c -o ebpf.o
- * attach it to a device with:
- * ip link set dev lo xdp object ebpf.o verbose
- * when attached to a device, eg. loopback, the ping output is like:
- * $ ping -c 10 127.0.0.1
- * PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
- * 64 bytes from 127.0.0.1: icmp_seq=1 ttl=21 time=0.031 ms
- * 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.066 ms
- * 64 bytes from 127.0.0.1: icmp_seq=5 ttl=32 time=0.066 ms
- * 64 bytes from 127.0.0.1: icmp_seq=7 ttl=9 time=0.057 ms
- * 64 bytes from 127.0.0.1: icmp_seq=9 ttl=32 time=0.065 ms
- *
- * --- 127.0.0.1 ping statistics ---
- * 10 packets transmitted, 5 received, 50% packet loss, time 9223ms
- * rtt min/avg/max/mdev = 0.031/0.057/0.066/0.013 ms
- */
- /*
- * ntohs() triggers the following LLVM error:
- * couldn't allocate output register for constraint 'r' at line 2147805127
- */
- #ifdef ntohs
- #undef ntohs
- #endif
- #define ntohs(x) __constant_ntohs(x)
- /* from bpf_helpers.h */
- #define SEC(NAME) __attribute__((section(NAME), used))
- static unsigned long long (*bpf_ktime_get_ns)(void) =
- (void *) BPF_FUNC_ktime_get_ns;
- /* incremental checksum update */
- static inline void csum_replace2(uint16_t *sum, uint16_t old, uint16_t new)
- {
- uint16_t csum = ~*sum;
- csum += ~old;
- csum += csum < (uint16_t)~old;
- csum += new;
- csum += csum < (uint16_t)new;
- *sum = ~csum;
- }
- SEC("prog")
- int xdp_main(struct xdp_md *ctx)
- {
- void *data_end = (void *)(long)ctx->data_end;
- void *data = (void *)(long)ctx->data;
- struct ethhdr *eth = data;
- struct iphdr *iph = (struct iphdr *)(eth + 1);
- struct icmphdr *icmph = (struct icmphdr *)(iph + 1);
- /* sanity check needed by the eBPF verifier */
- if (eth + 1 > data_end)
- return XDP_DROP;
- if (eth->h_proto != ntohs(ETH_P_IP))
- return XDP_PASS;
- /* sanity check needed by the eBPF verifier */
- if (iph + 1 > data_end)
- return XDP_DROP;
- if (iph->protocol != IPPROTO_ICMP)
- return XDP_PASS;
- /* sanity check needed by the eBPF verifier */
- if (icmph + 1 > data_end)
- return XDP_DROP;
- if (icmph->type == ICMP_ECHOREPLY) {
- if (icmph->un.echo.sequence & ntohs(1)) {
- /* odd reply, mangle the TTL */
- uint16_t *ttlproto = (uint16_t *)&iph->ttl;
- uint16_t old_ttlproto = *ttlproto;
- /* use the timestamp as fast pseudorandom source */
- iph->ttl /= bpf_ktime_get_ns() % 10 + 1;
- /* recalculate the checksum */
- csum_replace2(&iph->check, old_ttlproto, *ttlproto);
- } else /* even packet, drop */
- return XDP_DROP;
- }
- return XDP_PASS;
- }
- /* needed to call GPL functions and helpers */
- char _license[] SEC("license") = "GPL";
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement