Advertisement
teknoraver

ebpf

Feb 13th, 2018
258
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.86 KB | None | 0 0
  1. #include <stdint.h>
  2. #include <arpa/inet.h>
  3. #include <linux/bpf.h>
  4. #include <linux/if_ether.h>
  5. #include <linux/ip.h>
  6. #include <linux/icmp.h>
  7.  
  8. /*
  9.  * Sample XDP program, drop even ping replies and randomly change the TTL of the odd one.
  10.  * compile it with:
  11.  *  clang -O3 -target bpf -c ebpf.c -o ebpf.o
  12.  * attach it to a device with:
  13.  *  ip link set dev lo xdp object ebpf.o verbose
  14.  * when attached to a device, eg. loopback, the ping output is like:
  15.  * $ ping -c 10 127.0.0.1
  16.  * PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
  17.  * 64 bytes from 127.0.0.1: icmp_seq=1 ttl=21 time=0.031 ms
  18.  * 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.066 ms
  19.  * 64 bytes from 127.0.0.1: icmp_seq=5 ttl=32 time=0.066 ms
  20.  * 64 bytes from 127.0.0.1: icmp_seq=7 ttl=9 time=0.057 ms
  21.  * 64 bytes from 127.0.0.1: icmp_seq=9 ttl=32 time=0.065 ms
  22.  *
  23.  * --- 127.0.0.1 ping statistics ---
  24.  * 10 packets transmitted, 5 received, 50% packet loss, time 9223ms
  25.  * rtt min/avg/max/mdev = 0.031/0.057/0.066/0.013 ms
  26.  */
  27.  
  28. /*
  29.  * ntohs() triggers the following LLVM error:
  30.  * couldn't allocate output register for constraint 'r' at line 2147805127
  31.  */
  32. #ifdef ntohs
  33. #undef ntohs
  34. #endif
  35. #define ntohs(x) __constant_ntohs(x)
  36.  
  37. /* from bpf_helpers.h */
  38. #define SEC(NAME) __attribute__((section(NAME), used))
  39. static unsigned long long (*bpf_ktime_get_ns)(void) =
  40.     (void *) BPF_FUNC_ktime_get_ns;
  41.  
  42. /* incremental checksum update */
  43. static inline void csum_replace2(uint16_t *sum, uint16_t old, uint16_t new)
  44. {
  45.     uint16_t csum = ~*sum;
  46.  
  47.     csum += ~old;
  48.     csum += csum < (uint16_t)~old;
  49.  
  50.     csum += new;
  51.     csum += csum < (uint16_t)new;
  52.  
  53.     *sum = ~csum;
  54. }
  55.  
  56. SEC("prog")
  57. int xdp_main(struct xdp_md *ctx)
  58. {
  59.     void *data_end = (void *)(long)ctx->data_end;
  60.     void *data = (void *)(long)ctx->data;
  61.  
  62.     struct ethhdr *eth = data;
  63.     struct iphdr *iph = (struct iphdr *)(eth + 1);
  64.     struct icmphdr *icmph = (struct icmphdr *)(iph + 1);
  65.  
  66.     /* sanity check needed by the eBPF verifier */
  67.     if (eth + 1 > data_end)
  68.         return XDP_DROP;
  69.  
  70.     if (eth->h_proto != ntohs(ETH_P_IP))
  71.         return XDP_PASS;
  72.  
  73.     /* sanity check needed by the eBPF verifier */
  74.     if (iph + 1 > data_end)
  75.         return XDP_DROP;
  76.  
  77.     if (iph->protocol != IPPROTO_ICMP)
  78.         return XDP_PASS;
  79.  
  80.     /* sanity check needed by the eBPF verifier */
  81.     if (icmph + 1 > data_end)
  82.         return XDP_DROP;
  83.  
  84.     if (icmph->type == ICMP_ECHOREPLY) {
  85.         if (icmph->un.echo.sequence & ntohs(1)) {
  86.             /* odd reply, mangle the TTL */
  87.             uint16_t *ttlproto = (uint16_t *)&iph->ttl;
  88.             uint16_t old_ttlproto = *ttlproto;
  89.  
  90.             /* use the timestamp as fast pseudorandom source */
  91.             iph->ttl /= bpf_ktime_get_ns() % 10 + 1;
  92.  
  93.             /* recalculate the checksum */
  94.             csum_replace2(&iph->check, old_ttlproto, *ttlproto);
  95.         } else /* even packet, drop */
  96.             return XDP_DROP;
  97.     }
  98.  
  99.     return XDP_PASS;
  100. }
  101.  
  102. /* needed to call GPL functions and helpers */
  103. char _license[] SEC("license") = "GPL";
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement