I was working on a kernel module lab where we built our own mini firewall. I started to research what else I can do and had an idea of trying to modify a packet by adding data to it. I came across an example that modified the options. I used that as an example and tried to adapt it to adding more data however what I have just causes the system to crash.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/slab.h>
#include <linux/inet.h>
#include <linux/time.h>
#include <linux/ktime.h>
static struct nf_hook_ops nfho_out;
unsigned int hook_out(void* priv, struct skb_buff* skb, const struct nf_hook_state* state)
{
struct iph* iphdr;
struct tcph* tcphdr;
// Extra data to add
unsigned char extra_data[] = {'A', 'D', 'D', 'T', 'H', 'I', 'S', 0};
int extra_size = sizeof(extra_data);
// Check valid skb
if(!skb)
return NF_ACCEPT;
// Get IP header and check for TCP
iph = ip_hdr(skb);
if(!iph || iph->protocol != IPPROTO_TCP)
return NF_ACCEPT;
// Get TCP header
tcph = tcp_hdr(skb);
if(!tcph)
return NF_ACCEPT;
// Check for specific port
if(ntohs(tcph->dest) != 9999)
return NF_ACCEPT;
// Make a copy of the skb with extra size for the extra data
new_skb = skb_copy_expand(skb, skb_headroom(skb), skb->tail + extra_size, GFP_ATOMIC);
if(!new_skb)
return NF_ACCEPT;
// Recalculate the IP header
iph = ip_hdr(new_skb);
if(!iph){
kfree_skb(new_skb);
return NF_ACCEPT;
}
// Update tot_len to include the extra bytes
iph->tot_len = htons(ntohs(iph->tot_len) + extra_size);
// Recalculate TCP header
tcph = tcp_hdr(new_skb);
if(!tcph){
kfree_skb(new_skb);
return NF_ACCEPT;
}
// Modify data here??
// Calculate checksums here
// From my understanding, this puts the new_skb up for kernel to send
if(ip_local_out(new_skb)){
kfree_skb(new_skb);
return NF_ACCEPT;
}
printk("Modified TCP Packet!");
return NF_DROP;
}
static int __init mod_init()
{
nfho_out.hook = hook_out;
nfho_out.hooknum = NF_INET_LOCAL_OUT;
nfho_out.pf = PF_INET;
nfho_out.priority = NF_IP_PRI_FIRST;
return nf_register_hook(&nfho_out);
}
static void __exit mod_exit()
{
nf_unregister_hook(&nfho_out);
}
MODULE_LICENSE("GPL");
module_init(mod_init);
module_exit(mod_exit);
I am new to this and stuck on how the skb should be expanded and how the extra data should be added. Also I am unsure if the ip_local_out() is the correct function to tell the kernel to process the packet.