1*4882a593Smuzhiyun /* Copyright (c) 2016 Facebook
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or
4*4882a593Smuzhiyun * modify it under the terms of version 2 of the GNU General Public
5*4882a593Smuzhiyun * License as published by the Free Software Foundation.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun #define KBUILD_MODNAME "foo"
8*4882a593Smuzhiyun #include <uapi/linux/if_ether.h>
9*4882a593Smuzhiyun #include <uapi/linux/in6.h>
10*4882a593Smuzhiyun #include <uapi/linux/ipv6.h>
11*4882a593Smuzhiyun #include <uapi/linux/pkt_cls.h>
12*4882a593Smuzhiyun #include <uapi/linux/bpf.h>
13*4882a593Smuzhiyun #include <bpf/bpf_helpers.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /* copy of 'struct ethhdr' without __packed */
16*4882a593Smuzhiyun struct eth_hdr {
17*4882a593Smuzhiyun unsigned char h_dest[ETH_ALEN];
18*4882a593Smuzhiyun unsigned char h_source[ETH_ALEN];
19*4882a593Smuzhiyun unsigned short h_proto;
20*4882a593Smuzhiyun };
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define PIN_GLOBAL_NS 2
23*4882a593Smuzhiyun struct bpf_elf_map {
24*4882a593Smuzhiyun __u32 type;
25*4882a593Smuzhiyun __u32 size_key;
26*4882a593Smuzhiyun __u32 size_value;
27*4882a593Smuzhiyun __u32 max_elem;
28*4882a593Smuzhiyun __u32 flags;
29*4882a593Smuzhiyun __u32 id;
30*4882a593Smuzhiyun __u32 pinning;
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun struct bpf_elf_map SEC("maps") test_cgrp2_array_pin = {
34*4882a593Smuzhiyun .type = BPF_MAP_TYPE_CGROUP_ARRAY,
35*4882a593Smuzhiyun .size_key = sizeof(uint32_t),
36*4882a593Smuzhiyun .size_value = sizeof(uint32_t),
37*4882a593Smuzhiyun .pinning = PIN_GLOBAL_NS,
38*4882a593Smuzhiyun .max_elem = 1,
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun SEC("filter")
handle_egress(struct __sk_buff * skb)42*4882a593Smuzhiyun int handle_egress(struct __sk_buff *skb)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun void *data = (void *)(long)skb->data;
45*4882a593Smuzhiyun struct eth_hdr *eth = data;
46*4882a593Smuzhiyun struct ipv6hdr *ip6h = data + sizeof(*eth);
47*4882a593Smuzhiyun void *data_end = (void *)(long)skb->data_end;
48*4882a593Smuzhiyun char dont_care_msg[] = "dont care %04x %d\n";
49*4882a593Smuzhiyun char pass_msg[] = "pass\n";
50*4882a593Smuzhiyun char reject_msg[] = "reject\n";
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /* single length check */
53*4882a593Smuzhiyun if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
54*4882a593Smuzhiyun return TC_ACT_OK;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun if (eth->h_proto != htons(ETH_P_IPV6) ||
57*4882a593Smuzhiyun ip6h->nexthdr != IPPROTO_ICMPV6) {
58*4882a593Smuzhiyun bpf_trace_printk(dont_care_msg, sizeof(dont_care_msg),
59*4882a593Smuzhiyun eth->h_proto, ip6h->nexthdr);
60*4882a593Smuzhiyun return TC_ACT_OK;
61*4882a593Smuzhiyun } else if (bpf_skb_under_cgroup(skb, &test_cgrp2_array_pin, 0) != 1) {
62*4882a593Smuzhiyun bpf_trace_printk(pass_msg, sizeof(pass_msg));
63*4882a593Smuzhiyun return TC_ACT_OK;
64*4882a593Smuzhiyun } else {
65*4882a593Smuzhiyun bpf_trace_printk(reject_msg, sizeof(reject_msg));
66*4882a593Smuzhiyun return TC_ACT_SHOT;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun char _license[] SEC("license") = "GPL";
71