brintos

brintos / linux-shallow public Read only

0
0
Text · 3.4 KiB · d862384 Raw
151 lines · c
1/* Copyright (c) 2016 Facebook2 *3 * This program is free software; you can redistribute it and/or4 * modify it under the terms of version 2 of the GNU General Public5 * License as published by the Free Software Foundation.6 */7#define KBUILD_MODNAME "foo"8#include <linux/if_ether.h>9#include <linux/if_vlan.h>10#include <linux/ip.h>11#include <linux/ipv6.h>12#include <linux/in.h>13#include <linux/tcp.h>14#include <linux/udp.h>15#include <uapi/linux/bpf.h>16#include <net/ip.h>17#include <bpf/bpf_helpers.h>18 19#define DEFAULT_PKTGEN_UDP_PORT 920#define DEBUG 021 22static int tcp(void *data, uint64_t tp_off, void *data_end)23{24	struct tcphdr *tcp = data + tp_off;25 26	if (tcp + 1 > data_end)27		return 0;28	if (tcp->dest == htons(80) || tcp->source == htons(80))29		return TC_ACT_SHOT;30	return 0;31}32 33static int udp(void *data, uint64_t tp_off, void *data_end)34{35	struct udphdr *udp = data + tp_off;36 37	if (udp + 1 > data_end)38		return 0;39	if (udp->dest == htons(DEFAULT_PKTGEN_UDP_PORT) ||40	    udp->source == htons(DEFAULT_PKTGEN_UDP_PORT)) {41		if (DEBUG) {42			char fmt[] = "udp port 9 indeed\n";43 44			bpf_trace_printk(fmt, sizeof(fmt));45		}46		return TC_ACT_SHOT;47	}48	return 0;49}50 51static int parse_ipv4(void *data, uint64_t nh_off, void *data_end)52{53	struct iphdr *iph;54	uint64_t ihl_len;55 56	iph = data + nh_off;57	if (iph + 1 > data_end)58		return 0;59 60	if (ip_is_fragment(iph))61		return 0;62	ihl_len = iph->ihl * 4;63 64	if (iph->protocol == IPPROTO_IPIP) {65		iph = data + nh_off + ihl_len;66		if (iph + 1 > data_end)67			return 0;68		ihl_len += iph->ihl * 4;69	}70 71	if (iph->protocol == IPPROTO_TCP)72		return tcp(data, nh_off + ihl_len, data_end);73	else if (iph->protocol == IPPROTO_UDP)74		return udp(data, nh_off + ihl_len, data_end);75	return 0;76}77 78static int parse_ipv6(void *data, uint64_t nh_off, void *data_end)79{80	struct ipv6hdr *ip6h;81	struct iphdr *iph;82	uint64_t ihl_len = sizeof(struct ipv6hdr);83	uint64_t nexthdr;84 85	ip6h = data + nh_off;86	if (ip6h + 1 > data_end)87		return 0;88 89	nexthdr = ip6h->nexthdr;90 91	if (nexthdr == IPPROTO_IPIP) {92		iph = data + nh_off + ihl_len;93		if (iph + 1 > data_end)94			return 0;95		ihl_len += iph->ihl * 4;96		nexthdr = iph->protocol;97	} else if (nexthdr == IPPROTO_IPV6) {98		ip6h = data + nh_off + ihl_len;99		if (ip6h + 1 > data_end)100			return 0;101		ihl_len += sizeof(struct ipv6hdr);102		nexthdr = ip6h->nexthdr;103	}104 105	if (nexthdr == IPPROTO_TCP)106		return tcp(data, nh_off + ihl_len, data_end);107	else if (nexthdr == IPPROTO_UDP)108		return udp(data, nh_off + ihl_len, data_end);109	return 0;110}111 112SEC("varlen")113int handle_ingress(struct __sk_buff *skb)114{115	void *data = (void *)(long)skb->data;116	struct ethhdr *eth = data;117	void *data_end = (void *)(long)skb->data_end;118	uint64_t h_proto, nh_off;119 120	nh_off = sizeof(*eth);121	if (data + nh_off > data_end)122		return 0;123 124	h_proto = eth->h_proto;125 126	if (h_proto == ETH_P_8021Q || h_proto == ETH_P_8021AD) {127		struct vlan_hdr *vhdr;128 129		vhdr = data + nh_off;130		nh_off += sizeof(struct vlan_hdr);131		if (data + nh_off > data_end)132			return 0;133		h_proto = vhdr->h_vlan_encapsulated_proto;134	}135	if (h_proto == ETH_P_8021Q || h_proto == ETH_P_8021AD) {136		struct vlan_hdr *vhdr;137 138		vhdr = data + nh_off;139		nh_off += sizeof(struct vlan_hdr);140		if (data + nh_off > data_end)141			return 0;142		h_proto = vhdr->h_vlan_encapsulated_proto;143	}144	if (h_proto == htons(ETH_P_IP))145		return parse_ipv4(data, nh_off, data_end);146	else if (h_proto == htons(ETH_P_IPV6))147		return parse_ipv6(data, nh_off, data_end);148	return 0;149}150char _license[] SEC("license") = "GPL";151