103 lines
3.8 KiB
C
103 lines
3.8 KiB
C
|
#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>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
char pkt[]={0x04, 0xf0, 0x21, 0x65, 0x18, 0x12, 0x50, 0x9a, 0x4c,
|
||
|
0x24, 0x1a, 0x72, 0x08, 0x00, 0x45, 0x00, 0x00, 0x20,
|
||
|
0x37, 0xb5, 0x40, 0x00, 0x40, 0x11, 0x70, 0x86, 0xc0,
|
||
|
0xa8, 0x00, 0xad, 0xd4, 0x2f, 0xfd, 0x0c, 0x9e, 0x1e,
|
||
|
0x09, 0x44, 0x00, 0x0c, 0xfd, 0x72, 0x64, 0x64, 0x64,
|
||
|
0x0a};
|
||
|
|
||
|
char pkt2[] = { 0x04,0xf0,0x21,0x65,0x18,0x12,0x50,0x9a,0x4c,0x24,0x1a,0x72,0x08,0x00,0x45,0x00,0x00,0x4e,0xf7,0xb9,0x00,0x00,0x40,0x11,0xb1,0x80,0xc0,0xa8,0x00,0xad,0x08,0x08,0x08,0x08,0x95,0xa2,0x00,0x35,0x00,0x3a,0xd1,0xb0,0x4a,0x8d,0x01,0x20,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x02,0x66,0x72,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x29,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x0a,0x00,0x08,0x32,0x1b,0xf3,0x55,0xed,0xd5,0xd5,0x6b };
|
||
|
|
||
|
char pkt3[] = { 0x50,0x9a,0x4c,0x24,0x1a,0x72,0x04,0xf0,0x21,0x65,0x18,0x12,0x08,0x00,0x45,0x00,0x00,0x64,0x7e,0x9c,0x40,0x00,0x40,0x11,0xfb,0xfe,0xc0,0xa8,0x00,0xfe,0xc0,0xa8,0x00,0xad,0x00,0x35,0xe6,0x4c,0x00,0x50,0x88,0x50,0xd1,0x70,0x81,0x80,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x0c,0x73,0x61,0x66,0x65,0x62,0x72,0x6f,0x77,0x73,0x69,0x6e,0x67,0x0a,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x61,0x70,0x69,0x73,0x03,0x63,0x6f,0x6d,0x00,0x00,0x01,0x00,0x01,0xc0,0x0c,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x0d,0x00,0x04,0x8e,0xfa,0xba,0x8a,0x00,0x00,0x29,0x04,0xd0,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||
|
|
||
|
char csDesired[] = { 0x38, 0xf1 };
|
||
|
|
||
|
// Checksum utilities
|
||
|
__attribute__((__always_inline__))
|
||
|
static inline __u16 csum_fold_helper(__u64 csum) {
|
||
|
int i;
|
||
|
#pragma unroll
|
||
|
for (i = 0; i < 4; i ++) {
|
||
|
if (csum >> 16)
|
||
|
csum = (csum & 0xffff) + (csum >> 16);
|
||
|
}
|
||
|
return ~csum;
|
||
|
}
|
||
|
|
||
|
// Update checksum following RFC 1624 (Eqn. 3): https://tools.ietf.org/html/rfc1624
|
||
|
// HC' = ~(~HC + ~m + m')
|
||
|
// Where :
|
||
|
// HC - old checksum in header
|
||
|
// HC' - new checksum in header
|
||
|
// m - old value
|
||
|
// m' - new value
|
||
|
__attribute__((__always_inline__))
|
||
|
static inline void update_csum(__u64 *csum, __be32 old_flag,__be32 new_flag ) {
|
||
|
// ~HC
|
||
|
*csum = ~*csum;
|
||
|
*csum = *csum & 0xffff;
|
||
|
// + ~m
|
||
|
__u32 tmp;
|
||
|
tmp = ~old_addr;
|
||
|
*csum += tmp;
|
||
|
// + m
|
||
|
*csum += new_addr;
|
||
|
// then fold and complement result !
|
||
|
*csum = csum_fold_helper(*csum);
|
||
|
}
|
||
|
|
||
|
|
||
|
int main(void) {
|
||
|
void *data = pkt3;
|
||
|
void *data_end = pkt3+114;
|
||
|
|
||
|
struct ethhdr *eth = data; //structure ethernet from if_ether.h
|
||
|
struct iphdr *ip = (struct iphdr*)(eth + 1);
|
||
|
printf("%#06x\n", bpf_ntohs(ip->check));
|
||
|
__u64 cs = iph->check;
|
||
|
update_csum(&cs, old_addr, new_addr);
|
||
|
iph->check = cs;
|
||
|
printf("new cs: %x\n", ip->check);
|
||
|
}
|
||
|
|
||
|
int main2(void) {
|
||
|
void *data = pkt2; //pkt;
|
||
|
void *data_end = pkt2+92;//pkt+46;
|
||
|
|
||
|
struct ethhdr *eth = data; //structure ethernet from if_ether.h
|
||
|
struct iphdr *ip = (struct iphdr*)(eth + 1);
|
||
|
|
||
|
// Check that our packet ethernet headers is big enough, ie. at least the size of Ethernet's fixed headers
|
||
|
if((void*)ip > data_end) {
|
||
|
printf("eth headers too short\n");
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
|
||
|
// Check that the ethernet header declares an IPv4 packet
|
||
|
if(eth->h_proto == bpf_htons(ETH_P_IP)) {
|
||
|
printf("this is an IPv4 packet according to ethernet headers\n");
|
||
|
// Check that the IP packet is big enough, ie. at least the size of IP's fixed headers
|
||
|
if((void*)(ip + 1) > data_end) {
|
||
|
printf("IPv4 headers are too short \n");
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
|
||
|
if(ip->protocol == IPPROTO_UDP) {
|
||
|
printf("Protocol is UDP, flags are %#06x\n", ip->frag_off);
|
||
|
printf("Total offset: %x\n", (void*)&(ip->frag_off) - data);
|
||
|
ip->frag_off |= bpf_htons(0x4000); //Set the DF flag to 1 -> 0b 0100 0000 0000 0000
|
||
|
printf("Protocol is UDP, flags are now %#06x\n", ip->frag_off);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|