1 /* Copyright (c) 2017 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 #include <stddef.h> 8 #include <string.h> 9 #include <linux/bpf.h> 10 #include <linux/if_ether.h> 11 #include <linux/if_packet.h> 12 #include <linux/ip.h> 13 #include <linux/ipv6.h> 14 #include <linux/in.h> 15 #include <linux/tcp.h> 16 #include <linux/pkt_cls.h> 17 #include "bpf_helpers.h" 18 #include "bpf_endian.h" 19 20 #define barrier() __asm__ __volatile__("": : :"memory") 21 int _version SEC("version") = 1; 22 23 SEC("test1") 24 int process(struct __sk_buff *skb) 25 { 26 void *data_end = (void *)(long)skb->data_end; 27 void *data = (void *)(long)skb->data; 28 struct ethhdr *eth = (struct ethhdr *)(data); 29 struct tcphdr *tcp = NULL; 30 __u8 proto = 255; 31 __u64 ihl_len; 32 33 if (eth + 1 > data_end) 34 return TC_ACT_SHOT; 35 36 if (eth->h_proto == bpf_htons(ETH_P_IP)) { 37 struct iphdr *iph = (struct iphdr *)(eth + 1); 38 39 if (iph + 1 > data_end) 40 return TC_ACT_SHOT; 41 ihl_len = iph->ihl * 4; 42 proto = iph->protocol; 43 tcp = (struct tcphdr *)((void *)(iph) + ihl_len); 44 } else if (eth->h_proto == bpf_htons(ETH_P_IPV6)) { 45 struct ipv6hdr *ip6h = (struct ipv6hdr *)(eth + 1); 46 47 if (ip6h + 1 > data_end) 48 return TC_ACT_SHOT; 49 ihl_len = sizeof(*ip6h); 50 proto = ip6h->nexthdr; 51 tcp = (struct tcphdr *)((void *)(ip6h) + ihl_len); 52 } 53 54 if (tcp) { 55 if (((void *)(tcp) + 20) > data_end || proto != 6) 56 return TC_ACT_SHOT; 57 barrier(); /* to force ordering of checks */ 58 if (((void *)(tcp) + 18) > data_end) 59 return TC_ACT_SHOT; 60 if (tcp->urg_ptr == 123) 61 return TC_ACT_OK; 62 } 63 64 return TC_ACT_UNSPEC; 65 } 66