Results 1 to 1 of 1
Hi all,
For my work, I have to modify the routing lookup process at Linux kernel.
The details is below:
A-----B.
We have pcA, pcB (using Linux OS kernel 2.6.26.5) ...
- 12-07-2010 #1Just Joined!
- Join Date
- Dec 2010
- Posts
- 1
Modify kernel linux.
Hi all,
For my work, I have to modify the routing lookup process at Linux kernel.
The details is below:
A-----B.
We have pcA, pcB (using Linux OS kernel 2.6.26.5) connect together. We need to modify the source code of kernel at B in order to if A sends the packets with destination IP address as C, pcB still receives this packet and send to transport layer (that means, it bypass the routing lookup process at kernel).
The solution I used as the following:
In /net/ipv4/ip_input.c write a ip_receive_finish_fake and put skb->dst->input = ip_local_deliver.
Then in ip_rcv function, i check whether the packet whose destination ip address is C or not, if it's C, we call ip_rcv_finish_fake()Code:static int ip_rcv_finish_fake(struct sk_buff *skb) { const struct iphdr *iph = ip_hdr(skb); struct rtable *rt; struct net *net = dev_net(skb->dev); skb->dst->input=ip_local_deliver; #ifdef CONFIG_NET_CLS_ROUTE if (unlikely(skb->dst->tclassid)) { struct ip_rt_acct *st = per_cpu_ptr(ip_rt_acct, smp_processor_id()); u32 idx = skb->dst->tclassid; st[idx&0xFF].o_packets++; st[idx&0xFF].o_bytes+=skb->len; st[(idx>>16)&0xFF].i_packets++; st[(idx>>16)&0xFF].i_bytes+=skb->len; } #endif if (iph->ihl > 5 && ip_rcv_options(skb)) goto drop; rt = skb->rtable; if (rt->rt_type == RTN_MULTICAST) IP_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS); else if (rt->rt_type == RTN_BROADCAST) IP_INC_STATS_BH(IPSTATS_MIB_INBCASTPKTS); return dst_input(skb); drop: kfree_skb(skb); return NET_RX_DROP; }
it's built successfully, but when PCB receives the the packet with destination IP address as C, the kernel panic.Code:int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { struct iphdr *iph; u32 len; /* When the interface is in promisc. mode, drop all the crap * that it receives, do not try to analyse it. */ if (skb->pkt_type == PACKET_OTHERHOST) goto drop; IP_INC_STATS_BH(IPSTATS_MIB_INRECEIVES); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); goto out; } if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto inhdr_error; iph = ip_hdr(skb); /* * RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum. * * Is the datagram acceptable? * * 1. Length at least the size of an ip header * 2. Version of 4 * 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums] * 4. Doesn't have a bogus length */ if (iph->ihl < 5 || iph->version != 4) goto inhdr_error; if (!pskb_may_pull(skb, iph->ihl*4)) goto inhdr_error; iph = ip_hdr(skb); if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) goto inhdr_error; len = ntohs(iph->tot_len); if (skb->len < len) { IP_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } else if (len < (iph->ihl*4)) goto inhdr_error; /* Our transport medium may have padded the buffer out. Now we know it * is IP we can trim to the true length of the frame. * Note this now means skb->len holds ntohs(iph->tot_len). */ if (pskb_trim_rcsum(skb, len)) { IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); goto drop; } /* Remove any debris in the socket control block */ memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); unsigned int dst_add=inet_addr("10.11.21.40"); // IPC if(iph->daddr==dst_add ) return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish_fake); else return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish); inhdr_error: IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); drop: kfree_skb(skb); out: return NET_RX_DROP; }
I don't know why ? Can you help me ?
Regards,


Reply With Quote
