Skip to content
Snippets Groups Projects
Commit 229e032c authored by NGUYEN Do Duc Anh's avatar NGUYEN Do Duc Anh
Browse files

update ebpf c for inter

parent 517bbb88
No related branches found
No related tags found
No related merge requests found
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>
#define MY_OPTION_TYPE 31 // Custom option type
#define MAX_CHECKING 4
static inline __u16 iph_csum(struct iphdr *iph, void *data_end)
{
__u32 sum = 0;
__u16 *buf = (__u16 *)iph;
__u16 ihl = iph->ihl << 2; // Convert IHL to bytes
// Reset checksum field
iph->check = 0;
// Sum all 16-bit words in the header - 60 bytes is maximum size of IP header
for (__u8 i = 0; i < ihl && i < 60; i += 2)
{
if ((void *)(buf + 1) > data_end)
{
break;
}
sum += *buf++;
}
// Add overflow (carry folding)
for (__u8 i = 0; sum >> 16 && i < MAX_CHECKING; i += 1)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
// Take one's complement
return ~sum;
}
// CustomIPOption structure
struct CustomIPEntry
{
__u16 id_val;
__u8 inter_val;
__u8 cmd_val;
} __attribute__((packed)); // Ensure packed struct to prevent padding issues
int inter_op_ebpf(struct xdp_md *ctx)
{
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
// Check if the Ethernet header is within bounds
if ((void *)eth + sizeof(*eth) > data_end)
return XDP_PASS;
struct iphdr *ip = data + sizeof(*eth);
// Check if the IP header is within bounds
if ((void *)ip + sizeof(*ip) > data_end)
return XDP_PASS;
if (ip->version != 4)
{
return XDP_PASS;
}
// Check if the packet has IP options
int options_len = (ip->ihl * 4) - sizeof(struct iphdr);
__u8 *options = (__u8 *)(ip + 1);
bpf_trace_printk("Packet received on interface %d and and ihl %d option length %d\n", ctx->ingress_ifindex, ip->ihl, options_len);
__u8 is_register = 1;
__u8 is_exist_custom_option = 0;
if (options_len > 0 && (void *)(options + 4) < data_end)
{ // Ensure you're within the bounds (type + length + count = 4 bytes)
__u8 option_type = options[0];
if (option_type == MY_OPTION_TYPE)
{
is_exist_custom_option = 1;
__u8 option_length = options[1];
__u8 *data_bytes = (__u8 *)data;
int shift_data_length = sizeof(*eth) + sizeof(struct iphdr);
if (option_length == 8){
for (int i = shift_data_length - 1; i >= 0; i--) {
if ((void *)(data_bytes + i + option_length + 1) > data_end)
return XDP_PASS;
data_bytes[i + option_length] = data_bytes[i];
}
}
else if (option_length == 12){
for (int i = shift_data_length - 1; i >= 0; i--) {
if ((void *)(data_bytes + i + option_length + 1) > data_end)
return XDP_PASS;
data_bytes[i + option_length] = data_bytes[i];
}
}
else if (option_length == 16){
for (int i = shift_data_length - 1; i >= 0; i--) {
if ((void *)(data_bytes + i + option_length + 1) > data_end)
return XDP_PASS;
data_bytes[i + option_length] = data_bytes[i];
}
}
else if (option_length == 20){
for (int i = shift_data_length - 1; i >= 0; i--) {
if ((void *)(data_bytes + i + option_length + 1) > data_end)
return XDP_PASS;
data_bytes[i + option_length] = data_bytes[i];
}
}
else if (option_length == 24){
for (int i = shift_data_length - 1; i >= 0; i--) {
if ((void *)(data_bytes + i + option_length + 1) > data_end)
return XDP_PASS;
data_bytes[i + option_length] = data_bytes[i];
}
}
else if (option_length == 28){
for (int i = shift_data_length - 1; i >= 0; i--) {
if ((void *)(data_bytes + i + option_length + 1) > data_end)
return XDP_PASS;
data_bytes[i + option_length] = data_bytes[i];
}
}
else if (option_length == 32){
for (int i = shift_data_length - 1; i >= 0; i--) {
if ((void *)(data_bytes + i + option_length + 1) > data_end)
return XDP_PASS;
data_bytes[i + option_length] = data_bytes[i];
}
}
int ret = bpf_xdp_adjust_head(ctx, option_length); // Cut option length bytes at the head
if (ret < 0)
{
return XDP_PASS; // If adjustment fails, pass the packet
}
data = (void *)(long)ctx->data;
data_end = (void *)(long)ctx->data_end;
eth = data;
// Check if the Ethernet header is within bounds
if ((void *)eth + sizeof(*eth) > data_end)
return XDP_DROP;
ip = data + sizeof(*eth);
// Check if the IP header is within bounds
if ((void *)ip + sizeof(*ip) > data_end)
return XDP_DROP;
if (ip->version != 4)
{
return XDP_DROP;
}
int new_header_size = sizeof(struct iphdr); // 20 + 8 = 28 bytes
ip->ihl = new_header_size / 4;
ip->tot_len = htons(ntohs(ip->tot_len) - option_length);
// bpf_trace_printk("Packet received on interface %d and option length %d\n", ctx->ingress_ifindex, options_len);
// ip->check = iph_csum(ip, data_end);
}
}
ip->check = iph_csum(ip, data_end);
return XDP_PASS;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment