Looking for Information on NF_STOLEN.
After Stealing Packet from NET-FILTER ; am adding IP Header by expanding SKUBUFFER. After that; want to send the Packet to the corresponding Interface . What is the function that we should use to do this step ??? OR if we say; NF_ACCEPT., can we ensure that Manipulated Packet will be processed by the Kernel correctly forwarding it to the right interface ??
Looking forward for the reply !!!
-Thanks in Advance, VKS
Yes, if you alter the skbuff structure and compute the appropriate checksums, you just need to return NF_ACCEPT. The kernel will deal with the rest for you.
I've done this in my thesis. Here's some code I've done (it does not extend or trim the skbuff, but it changes a field in the application payload. However, I've also done some code which extends the skbuff and the theory is the same):
unsigned int pre_routing_hook(filter_specs* sp, unsigned int hooknum,
struct sk_buff* skb, const struct net_device* in,
const struct net_device *out,
int(*okfn)(struct sk_buff*)) {
struct iphdr* iph;
struct udphdr* udp;
__tp(pdu)* pdu;
/*Omitted some sanity checks */
iph = ip_hdr(skb);
udp = (struct udphdr*) (((char*) iph) + (iph->ihl << 2));
//I didn't care about udp checksum so I've stored zero in this field.
udp->check = 0;
switch (iph->protocol) {
case IPPROTO_UDP:
pdu = (__tp(pdu)*) (((char*) iph) + (iph->ihl << 2)
+ sizeof(struct udphdr));
swap_pdu_byte_order(pdu);
pdu->timestamp = get_kernel_current_time() -
(pdu->timestamp + pdu->rtt * 1000);
swap_pdu_byte_order(pdu);
break;
default:
printk("\tProtocol not supported.\n");
}
return NF_ACCEPT;
}
EDIT: I've took a look at the code you've posted and here's what I came up with. It works for me:
#include <linux/ip.h>
#include <linux/in.h>
static uint16_t csum(uint16_t* buff, int nwords) {
uint32_t sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buff++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ((uint16_t) ~sum);
}
//I'm assuming this will run in PRE_ROUTING
unsigned int main_hook(unsigned int hooknum,
struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, int(*okfn)(struct sk_buff*)) {
uint16_t lets_keep_the_original_size;
struct in_device* ipa;
iph = ip_hdr(sock_buff);
lets_keep_the_original_size = ntohs(iph->tot_len);
if(iph->protocol == 1) {
if(skb_headroom(skb) < sizeof(struct iphdr)) {
if( 0 != pskb_expand_head(skb, (sizeof(struct iphdr))-
skb_headroom(skb),0,GFP_ATOMIC) ){
kfree_skb(skb);
return NF_STOLEN;
}
}
iph = (struct iphdr*) skb_push(skb, sizeof(struct iphdr));
iph->proto = IPPROTO_IP;
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = htons(lets_keep_the_original_size + sizeof(struct iphdr));
iph->id = 0;
iph->frag_off = 0;
iph->ttl = 60;
//This must be zero to be able to calculate it with csum above.
iph->check = 0;
//in is the interface where the packet arrived, provided by netfilters.
//In PRE_ROUTING there is no out interface yet so you'll need to add
//the ip manually:
ipa = (struct in_device*) in->ip_ptr;
iph->saddr = ipa->ifa_list->ifa_address;
//in_aton already gives you the address in network byte order .
//You can just add an integer, but I've chosen to use in_aton
//so the code is more readable
iph->daddr = in_aton("192.168.1.1");
//Here is the important part.
iph->check = csum((uint16_t*) iph, (iph->ihl << 1));
//Let the kernel deal with the rest for us.
return NF_ACCEPT;
}
return NF_ACCEPT;
}
Let me know if there's anything I can help you with.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With