162306a36Sopenharmony_ci/* Copyright (c) 2016 Facebook
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or
462306a36Sopenharmony_ci * modify it under the terms of version 2 of the GNU General Public
562306a36Sopenharmony_ci * License as published by the Free Software Foundation.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#define KBUILD_MODNAME "foo"
862306a36Sopenharmony_ci#include "vmlinux.h"
962306a36Sopenharmony_ci#include "net_shared.h"
1062306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/* copy of 'struct ethhdr' without __packed */
1362306a36Sopenharmony_cistruct eth_hdr {
1462306a36Sopenharmony_ci	unsigned char   h_dest[ETH_ALEN];
1562306a36Sopenharmony_ci	unsigned char   h_source[ETH_ALEN];
1662306a36Sopenharmony_ci	unsigned short  h_proto;
1762306a36Sopenharmony_ci};
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistruct {
2062306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
2162306a36Sopenharmony_ci	__type(key, u32);
2262306a36Sopenharmony_ci	__type(value, u32);
2362306a36Sopenharmony_ci	__uint(pinning, LIBBPF_PIN_BY_NAME);
2462306a36Sopenharmony_ci	__uint(max_entries, 1);
2562306a36Sopenharmony_ci} test_cgrp2_array_pin SEC(".maps");
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ciSEC("filter")
2862306a36Sopenharmony_ciint handle_egress(struct __sk_buff *skb)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	void *data = (void *)(long)skb->data;
3162306a36Sopenharmony_ci	struct eth_hdr *eth = data;
3262306a36Sopenharmony_ci	struct ipv6hdr *ip6h = data + sizeof(*eth);
3362306a36Sopenharmony_ci	void *data_end = (void *)(long)skb->data_end;
3462306a36Sopenharmony_ci	char dont_care_msg[] = "dont care %04x %d\n";
3562306a36Sopenharmony_ci	char pass_msg[] = "pass\n";
3662306a36Sopenharmony_ci	char reject_msg[] = "reject\n";
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	/* single length check */
3962306a36Sopenharmony_ci	if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
4062306a36Sopenharmony_ci		return TC_ACT_OK;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	if (eth->h_proto != bpf_htons(ETH_P_IPV6) ||
4362306a36Sopenharmony_ci	    ip6h->nexthdr != IPPROTO_ICMPV6) {
4462306a36Sopenharmony_ci		bpf_trace_printk(dont_care_msg, sizeof(dont_care_msg),
4562306a36Sopenharmony_ci				 eth->h_proto, ip6h->nexthdr);
4662306a36Sopenharmony_ci		return TC_ACT_OK;
4762306a36Sopenharmony_ci	} else if (bpf_skb_under_cgroup(skb, &test_cgrp2_array_pin, 0) != 1) {
4862306a36Sopenharmony_ci		bpf_trace_printk(pass_msg, sizeof(pass_msg));
4962306a36Sopenharmony_ci		return TC_ACT_OK;
5062306a36Sopenharmony_ci	} else {
5162306a36Sopenharmony_ci		bpf_trace_printk(reject_msg, sizeof(reject_msg));
5262306a36Sopenharmony_ci		return TC_ACT_SHOT;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cichar _license[] SEC("license") = "GPL";
57