Back to home page

OSCL-LXR

 
 

    


0001 /* Copyright (c) 2016 Facebook
0002  *
0003  * This program is free software; you can redistribute it and/or
0004  * modify it under the terms of version 2 of the GNU General Public
0005  * License as published by the Free Software Foundation.
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";