0001
0002
0003
0004
0005
0006
0007 #define KBUILD_MODNAME "foo"
0008 #include <linux/if_ether.h>
0009 #include <linux/if_vlan.h>
0010 #include <linux/ip.h>
0011 #include <linux/ipv6.h>
0012 #include <linux/in.h>
0013 #include <linux/tcp.h>
0014 #include <linux/udp.h>
0015 #include <uapi/linux/bpf.h>
0016 #include <net/ip.h>
0017 #include <bpf/bpf_helpers.h>
0018
0019 #define DEFAULT_PKTGEN_UDP_PORT 9
0020 #define DEBUG 0
0021
0022 static int tcp(void *data, uint64_t tp_off, void *data_end)
0023 {
0024 struct tcphdr *tcp = data + tp_off;
0025
0026 if (tcp + 1 > data_end)
0027 return 0;
0028 if (tcp->dest == htons(80) || tcp->source == htons(80))
0029 return TC_ACT_SHOT;
0030 return 0;
0031 }
0032
0033 static int udp(void *data, uint64_t tp_off, void *data_end)
0034 {
0035 struct udphdr *udp = data + tp_off;
0036
0037 if (udp + 1 > data_end)
0038 return 0;
0039 if (udp->dest == htons(DEFAULT_PKTGEN_UDP_PORT) ||
0040 udp->source == htons(DEFAULT_PKTGEN_UDP_PORT)) {
0041 if (DEBUG) {
0042 char fmt[] = "udp port 9 indeed\n";
0043
0044 bpf_trace_printk(fmt, sizeof(fmt));
0045 }
0046 return TC_ACT_SHOT;
0047 }
0048 return 0;
0049 }
0050
0051 static int parse_ipv4(void *data, uint64_t nh_off, void *data_end)
0052 {
0053 struct iphdr *iph;
0054 uint64_t ihl_len;
0055
0056 iph = data + nh_off;
0057 if (iph + 1 > data_end)
0058 return 0;
0059
0060 if (ip_is_fragment(iph))
0061 return 0;
0062 ihl_len = iph->ihl * 4;
0063
0064 if (iph->protocol == IPPROTO_IPIP) {
0065 iph = data + nh_off + ihl_len;
0066 if (iph + 1 > data_end)
0067 return 0;
0068 ihl_len += iph->ihl * 4;
0069 }
0070
0071 if (iph->protocol == IPPROTO_TCP)
0072 return tcp(data, nh_off + ihl_len, data_end);
0073 else if (iph->protocol == IPPROTO_UDP)
0074 return udp(data, nh_off + ihl_len, data_end);
0075 return 0;
0076 }
0077
0078 static int parse_ipv6(void *data, uint64_t nh_off, void *data_end)
0079 {
0080 struct ipv6hdr *ip6h;
0081 struct iphdr *iph;
0082 uint64_t ihl_len = sizeof(struct ipv6hdr);
0083 uint64_t nexthdr;
0084
0085 ip6h = data + nh_off;
0086 if (ip6h + 1 > data_end)
0087 return 0;
0088
0089 nexthdr = ip6h->nexthdr;
0090
0091 if (nexthdr == IPPROTO_IPIP) {
0092 iph = data + nh_off + ihl_len;
0093 if (iph + 1 > data_end)
0094 return 0;
0095 ihl_len += iph->ihl * 4;
0096 nexthdr = iph->protocol;
0097 } else if (nexthdr == IPPROTO_IPV6) {
0098 ip6h = data + nh_off + ihl_len;
0099 if (ip6h + 1 > data_end)
0100 return 0;
0101 ihl_len += sizeof(struct ipv6hdr);
0102 nexthdr = ip6h->nexthdr;
0103 }
0104
0105 if (nexthdr == IPPROTO_TCP)
0106 return tcp(data, nh_off + ihl_len, data_end);
0107 else if (nexthdr == IPPROTO_UDP)
0108 return udp(data, nh_off + ihl_len, data_end);
0109 return 0;
0110 }
0111
0112 SEC("varlen")
0113 int handle_ingress(struct __sk_buff *skb)
0114 {
0115 void *data = (void *)(long)skb->data;
0116 struct ethhdr *eth = data;
0117 void *data_end = (void *)(long)skb->data_end;
0118 uint64_t h_proto, nh_off;
0119
0120 nh_off = sizeof(*eth);
0121 if (data + nh_off > data_end)
0122 return 0;
0123
0124 h_proto = eth->h_proto;
0125
0126 if (h_proto == ETH_P_8021Q || h_proto == ETH_P_8021AD) {
0127 struct vlan_hdr *vhdr;
0128
0129 vhdr = data + nh_off;
0130 nh_off += sizeof(struct vlan_hdr);
0131 if (data + nh_off > data_end)
0132 return 0;
0133 h_proto = vhdr->h_vlan_encapsulated_proto;
0134 }
0135 if (h_proto == ETH_P_8021Q || h_proto == ETH_P_8021AD) {
0136 struct vlan_hdr *vhdr;
0137
0138 vhdr = data + nh_off;
0139 nh_off += sizeof(struct vlan_hdr);
0140 if (data + nh_off > data_end)
0141 return 0;
0142 h_proto = vhdr->h_vlan_encapsulated_proto;
0143 }
0144 if (h_proto == htons(ETH_P_IP))
0145 return parse_ipv4(data, nh_off, data_end);
0146 else if (h_proto == htons(ETH_P_IPV6))
0147 return parse_ipv6(data, nh_off, data_end);
0148 return 0;
0149 }
0150 char _license[] SEC("license") = "GPL";