wpj428/xdp/xdp_udp.c

79 lines
2.4 KiB
C
Raw Normal View History

2021-04-24 23:05:40 +00:00
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/in.h>
//Partie offset header en commentaire pour économiser les bytes sur la mémoire réservée pour le Kernel
/*
const unsigned short macLen = 6; //2bytes
const unsigned short macSrc = macLen; //2bytes
const unsigned short macDest = macLen; //2bytes
const unsigned short pktType =2; //2bytes
const unsigned short ethHead = macSrc+macDest+pktType; //=14
//Partie offet IP
const unsigned short iPVersionAndHeaderLen = 1;
const unsigned short DSF = 1;
const unsigned short totalLen = 2;
const unsigned short id = 2;
const unsigned short offsetIP = iPVersionAndHeaderLen + DSF + totalLen + id; //=6
const unsigned short DF_offset = offsetIP + ethHead; //=20
*/
2021-04-25 14:27:43 +00:00
#define bpf_printk(fmt, ...) \
({ \
char ____fmt[] = fmt; \
bpf_trace_printk(____fmt, sizeof(____fmt), \
##__VA_ARGS__); \
})
2021-04-25 14:56:35 +00:00
static __always_inline int checksum_ipv4(__u16* ipbuf) {
// https://tools.ietf.org/html/rfc1071
__u32 sum = 0;
for (int i = 0; i < sizeof(struct iphdr)/2; i++) {
sum += ipbuf[i];
}
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
2021-04-25 14:27:43 +00:00
2021-04-25 14:56:35 +00:00
return ~sum;
2021-04-25 14:27:43 +00:00
}
2021-04-25 14:56:35 +00:00
// @TODO: Implement https://tools.ietf.org/html/rfc1624 instead
2021-04-25 14:27:43 +00:00
2021-04-24 23:05:40 +00:00
SEC("xdp_udp")
int xdp_udp_func(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data; //structure ethernet from if_ether.h
2021-04-25 14:27:43 +00:00
struct iphdr *ip = (struct iphdr*)(eth + 1);
2021-04-24 23:05:40 +00:00
// Check that our packet ethernet headers is big enough, ie. at least the size of Ethernet's fixed headers
2021-04-25 14:27:43 +00:00
if((void*)ip > data_end) {
return XDP_PASS;
}
2021-04-24 23:05:40 +00:00
// Check that the ethernet header declares an IPv4 packet
if(eth->h_proto == bpf_htons(ETH_P_IP)) {
// Check that the IP packet is big enough, ie. at least the size of IP's fixed headers
2021-04-25 14:27:43 +00:00
if ((void*)(ip + 1) > data_end) {
return XDP_PASS;
2021-04-24 23:05:40 +00:00
}
2021-04-24 23:05:40 +00:00
if(ip->protocol == IPPROTO_UDP) {
2021-04-25 14:27:43 +00:00
ip->frag_off |= bpf_htons(0x4000); //Set the DF flag to 1 -> 0b 0100 0000 0000 0000
2021-04-25 14:56:35 +00:00
ip->check = 0;
ip->check = checksum_ipv4((__u16*)ip);
2021-04-24 23:05:40 +00:00
}
}
return XDP_PASS;
}
2021-04-25 14:27:43 +00:00
char _license[] SEC("license") = "GPL";