18c2ecf20Sopenharmony_ci/* Copyright (c) 2016 Facebook 28c2ecf20Sopenharmony_ci * 38c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or 48c2ecf20Sopenharmony_ci * modify it under the terms of version 2 of the GNU General Public 58c2ecf20Sopenharmony_ci * License as published by the Free Software Foundation. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#define KBUILD_MODNAME "foo" 88c2ecf20Sopenharmony_ci#include <linux/if_ether.h> 98c2ecf20Sopenharmony_ci#include <linux/if_vlan.h> 108c2ecf20Sopenharmony_ci#include <linux/ip.h> 118c2ecf20Sopenharmony_ci#include <linux/ipv6.h> 128c2ecf20Sopenharmony_ci#include <linux/in.h> 138c2ecf20Sopenharmony_ci#include <linux/tcp.h> 148c2ecf20Sopenharmony_ci#include <linux/udp.h> 158c2ecf20Sopenharmony_ci#include <uapi/linux/bpf.h> 168c2ecf20Sopenharmony_ci#include <net/ip.h> 178c2ecf20Sopenharmony_ci#include <bpf/bpf_helpers.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define DEFAULT_PKTGEN_UDP_PORT 9 208c2ecf20Sopenharmony_ci#define DEBUG 0 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic int tcp(void *data, uint64_t tp_off, void *data_end) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci struct tcphdr *tcp = data + tp_off; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci if (tcp + 1 > data_end) 278c2ecf20Sopenharmony_ci return 0; 288c2ecf20Sopenharmony_ci if (tcp->dest == htons(80) || tcp->source == htons(80)) 298c2ecf20Sopenharmony_ci return TC_ACT_SHOT; 308c2ecf20Sopenharmony_ci return 0; 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic int udp(void *data, uint64_t tp_off, void *data_end) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci struct udphdr *udp = data + tp_off; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci if (udp + 1 > data_end) 388c2ecf20Sopenharmony_ci return 0; 398c2ecf20Sopenharmony_ci if (udp->dest == htons(DEFAULT_PKTGEN_UDP_PORT) || 408c2ecf20Sopenharmony_ci udp->source == htons(DEFAULT_PKTGEN_UDP_PORT)) { 418c2ecf20Sopenharmony_ci if (DEBUG) { 428c2ecf20Sopenharmony_ci char fmt[] = "udp port 9 indeed\n"; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci bpf_trace_printk(fmt, sizeof(fmt)); 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci return TC_ACT_SHOT; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci return 0; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic int parse_ipv4(void *data, uint64_t nh_off, void *data_end) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci struct iphdr *iph; 548c2ecf20Sopenharmony_ci uint64_t ihl_len; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci iph = data + nh_off; 578c2ecf20Sopenharmony_ci if (iph + 1 > data_end) 588c2ecf20Sopenharmony_ci return 0; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci if (ip_is_fragment(iph)) 618c2ecf20Sopenharmony_ci return 0; 628c2ecf20Sopenharmony_ci ihl_len = iph->ihl * 4; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if (iph->protocol == IPPROTO_IPIP) { 658c2ecf20Sopenharmony_ci iph = data + nh_off + ihl_len; 668c2ecf20Sopenharmony_ci if (iph + 1 > data_end) 678c2ecf20Sopenharmony_ci return 0; 688c2ecf20Sopenharmony_ci ihl_len += iph->ihl * 4; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci if (iph->protocol == IPPROTO_TCP) 728c2ecf20Sopenharmony_ci return tcp(data, nh_off + ihl_len, data_end); 738c2ecf20Sopenharmony_ci else if (iph->protocol == IPPROTO_UDP) 748c2ecf20Sopenharmony_ci return udp(data, nh_off + ihl_len, data_end); 758c2ecf20Sopenharmony_ci return 0; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic int parse_ipv6(void *data, uint64_t nh_off, void *data_end) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct ipv6hdr *ip6h; 818c2ecf20Sopenharmony_ci struct iphdr *iph; 828c2ecf20Sopenharmony_ci uint64_t ihl_len = sizeof(struct ipv6hdr); 838c2ecf20Sopenharmony_ci uint64_t nexthdr; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci ip6h = data + nh_off; 868c2ecf20Sopenharmony_ci if (ip6h + 1 > data_end) 878c2ecf20Sopenharmony_ci return 0; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci nexthdr = ip6h->nexthdr; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (nexthdr == IPPROTO_IPIP) { 928c2ecf20Sopenharmony_ci iph = data + nh_off + ihl_len; 938c2ecf20Sopenharmony_ci if (iph + 1 > data_end) 948c2ecf20Sopenharmony_ci return 0; 958c2ecf20Sopenharmony_ci ihl_len += iph->ihl * 4; 968c2ecf20Sopenharmony_ci nexthdr = iph->protocol; 978c2ecf20Sopenharmony_ci } else if (nexthdr == IPPROTO_IPV6) { 988c2ecf20Sopenharmony_ci ip6h = data + nh_off + ihl_len; 998c2ecf20Sopenharmony_ci if (ip6h + 1 > data_end) 1008c2ecf20Sopenharmony_ci return 0; 1018c2ecf20Sopenharmony_ci ihl_len += sizeof(struct ipv6hdr); 1028c2ecf20Sopenharmony_ci nexthdr = ip6h->nexthdr; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (nexthdr == IPPROTO_TCP) 1068c2ecf20Sopenharmony_ci return tcp(data, nh_off + ihl_len, data_end); 1078c2ecf20Sopenharmony_ci else if (nexthdr == IPPROTO_UDP) 1088c2ecf20Sopenharmony_ci return udp(data, nh_off + ihl_len, data_end); 1098c2ecf20Sopenharmony_ci return 0; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ciSEC("varlen") 1138c2ecf20Sopenharmony_ciint handle_ingress(struct __sk_buff *skb) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci void *data = (void *)(long)skb->data; 1168c2ecf20Sopenharmony_ci struct ethhdr *eth = data; 1178c2ecf20Sopenharmony_ci void *data_end = (void *)(long)skb->data_end; 1188c2ecf20Sopenharmony_ci uint64_t h_proto, nh_off; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci nh_off = sizeof(*eth); 1218c2ecf20Sopenharmony_ci if (data + nh_off > data_end) 1228c2ecf20Sopenharmony_ci return 0; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci h_proto = eth->h_proto; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci if (h_proto == ETH_P_8021Q || h_proto == ETH_P_8021AD) { 1278c2ecf20Sopenharmony_ci struct vlan_hdr *vhdr; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci vhdr = data + nh_off; 1308c2ecf20Sopenharmony_ci nh_off += sizeof(struct vlan_hdr); 1318c2ecf20Sopenharmony_ci if (data + nh_off > data_end) 1328c2ecf20Sopenharmony_ci return 0; 1338c2ecf20Sopenharmony_ci h_proto = vhdr->h_vlan_encapsulated_proto; 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci if (h_proto == ETH_P_8021Q || h_proto == ETH_P_8021AD) { 1368c2ecf20Sopenharmony_ci struct vlan_hdr *vhdr; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci vhdr = data + nh_off; 1398c2ecf20Sopenharmony_ci nh_off += sizeof(struct vlan_hdr); 1408c2ecf20Sopenharmony_ci if (data + nh_off > data_end) 1418c2ecf20Sopenharmony_ci return 0; 1428c2ecf20Sopenharmony_ci h_proto = vhdr->h_vlan_encapsulated_proto; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci if (h_proto == htons(ETH_P_IP)) 1458c2ecf20Sopenharmony_ci return parse_ipv4(data, nh_off, data_end); 1468c2ecf20Sopenharmony_ci else if (h_proto == htons(ETH_P_IPV6)) 1478c2ecf20Sopenharmony_ci return parse_ipv6(data, nh_off, data_end); 1488c2ecf20Sopenharmony_ci return 0; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_cichar _license[] SEC("license") = "GPL"; 151