forked from microsoft/ebpf-for-windows
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdroppacket.c
69 lines (61 loc) · 2.59 KB
/
droppacket.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
// clang -O2 -Werror -c droppacket.c -o dropjit.o
//
// For bpf code: clang -target bpf -O2 -Werror -c droppacket.c -o droppacket.o
// this passes the checker
#include "bpf_endian.h"
#include "bpf_helpers.h"
#include "net/if_ether.h"
#include "net/ip.h"
#include "net/udp.h"
SEC("maps")
struct bpf_map_def dropped_packet_map = {
.type = BPF_MAP_TYPE_ARRAY, .key_size = sizeof(uint32_t), .value_size = sizeof(uint64_t), .max_entries = 1};
SEC("maps")
struct bpf_map_def interface_index_map = {
.type = BPF_MAP_TYPE_ARRAY, .key_size = sizeof(uint32_t), .value_size = sizeof(uint32_t), .max_entries = 1};
SEC("xdp")
int
DropPacket(xdp_md_t* ctx)
{
int rc = XDP_PASS;
ETHERNET_HEADER* ethernet_header = NULL;
long key = 0;
// This part of the sample is an example of how one might use the ingress_ifindex
// field of the context. Filtering by ifindex in this way is typically not
// needed since one can attach to one or more specific ifindex values and we
// will only be called if there is a match. Indeed, this example causes a perf
// hit on every packet which is undesirable. However, a real use might use
// the ifindex to log or to look up a more specific policy, or update per-interface
// statistics of some sort.
uint32_t* interface_index = bpf_map_lookup_elem(&interface_index_map, &key);
if (interface_index != NULL) {
if (ctx->ingress_ifindex != *interface_index) {
// Not interested in packets indicated over this interfce.
goto Done;
}
}
if ((char*)ctx->data + sizeof(ETHERNET_HEADER) + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) > (char*)ctx->data_end)
goto Done;
ethernet_header = (ETHERNET_HEADER*)ctx->data;
if (ntohs(ethernet_header->Type) == 0x0800) {
// IPv4.
IPV4_HEADER* ipv4_header = (IPV4_HEADER*)(ethernet_header + 1);
if (ipv4_header->Protocol == IPPROTO_UDP) {
// UDP.
char* next_header = (char*)ipv4_header + sizeof(uint32_t) * ipv4_header->HeaderLength;
if ((char*)next_header + sizeof(UDP_HEADER) > (char*)ctx->data_end)
goto Done;
UDP_HEADER* udp_header = (UDP_HEADER*)((char*)ipv4_header + sizeof(uint32_t) * ipv4_header->HeaderLength);
if (ntohs(udp_header->length) <= sizeof(UDP_HEADER)) {
long* count = bpf_map_lookup_elem(&dropped_packet_map, &key);
if (count)
*count = (*count + 1);
rc = XDP_DROP;
}
}
}
Done:
return rc;
}