hi, i have three PC A ip = 192.168.2.249 vip = 192.168.2.99 B ip = 192.168.2.245 vip = 192.168.2.99 no arp C ip = 192.168.2.19 A send package to 192.168.2.99 , then A get IP package from C and change it's MAC and send to B. I find A can get C's IP package, but it can't send out. I get the idea from ipvs's dr mode. I guess my problem in function my_xmit, but i don't know why. Thanks. ====================== #include <linux/init.h> #include <linux/module.h> #include <linux/netfilter.h> #include <linux/socket.h>/*PF_INET*/ #include <linux/netfilter_ipv4.h>/*NF_IP_PRE_FIRST*/ #include <linux/skbuff.h> #include <linux/netdevice.h> #include <linux/inet.h> /*in_aton()*/ #include <net/ip.h> #include <net/tcp.h> #include <linux/version.h> #include <linux/module.h> #define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" #define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] MODULE_LICENSE("GPL"); MODULE_AUTHOR("bbo"); struct nf_hook_ops nfho; struct nf_hook_ops nfout; static char * vip="192.168.2.99"; static char server_mac[ETH_ALEN] = {0x90,0xFB,0xA6,0x03,0x06,0x61}; static char * client_ip = "192.168.2.16"; static char * rs_ip = "192.168.2.245"; #define MY_XMIT(pf, skb, rt) \ do { \ skb_forward_csum(skb); \ NF_HOOK(pf, NF_INET_LOCAL_OUT , (skb), NULL, \ (rt)->u.dst.dev, dst_output); \ } while (0) void print_mac_buf(char * buf) { printk("DEST:" MAC_FMT "\n", MAC_ARG(buf)); printk("SOURCE:" MAC_FMT "\n", MAC_ARG(buf+6)); } void print_mac(struct ethhdr* eth) { if(eth==NULL) return; if(eth->h_source!=NULL) printk("SOURCE:" MAC_FMT "\n", MAC_ARG(eth->h_source)); if(eth->h_dest!=NULL) printk("DEST:" MAC_FMT "\n", MAC_ARG(eth->h_dest)); } static struct rtable * my_route(int daddr_ip,int rtos) { struct rtable *rt = NULL;/* Route to the other host */ struct flowi fl = { .oif = 0, .nl_u = { .ip4_u = { .daddr = daddr_ip, .saddr = 0, .tos = rtos, } }, }; if(ip_route_output_key(&init_net, &rt, &fl)) return NULL; if(rt) { char * buf; struct hh_cache * hh = rt->u.dst.hh; if(hh) { buf = hh->hh_data; print_mac_buf(buf+2); } } return rt; } int my_xmit(struct sk_buff *skb, int daddr_ip) { struct rtable *rt; /* Route to the other host */ struct iphdr *iph = ip_hdr(skb); int mtu; rt = my_route(daddr_ip, RT_TOS(iph->tos)); if(rt == NULL) return 0; /* * Call ip_send_check because we are not sure it is called * after ip_defrag. Is copy-on-write needed? */ if (unlikely((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)) { ip_rt_put(rt); return 1; } ip_send_check(ip_hdr(skb)); /* drop old route */ skb_dst_drop(skb); skb_dst_set(skb, &rt->u.dst); /* Another hack: avoid icmp_send in ip_fragment */ skb->local_df = 1; MY_XMIT(NFPROTO_IPV4, skb, rt); return 1; } unsigned int checksum(unsigned int hooknum, struct sk_buff *__skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct sk_buff *skb; struct net_device *dev; struct iphdr *iph; struct tcphdr *tcph; int tot_len; int iph_len; int tcph_len; int ret; skb = __skb; if(skb == NULL) return NF_ACCEPT; iph = ip_hdr(skb); if(iph == NULL) return NF_ACCEPT; if((iph->daddr == in_aton(vip)) && (iph->saddr == in_aton(client_ip))) { if(my_xmit(skb,in_aton(rs_ip))) { printk ("route OK\n"); return NF_STOLEN; } else { printk ("route false\n"); } } return NF_ACCEPT; } unsigned int output(unsigned int hooknum, struct sk_buff *__skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct sk_buff *skb; struct net_device *dev; struct iphdr *iph; struct tcphdr *tcph; int tot_len; int iph_len; int tcph_len; int ret; skb = __skb; if(skb == NULL) return NF_ACCEPT; iph = ip_hdr(skb); if(iph == NULL) return NF_ACCEPT; if((iph->daddr == in_aton(vip)) && (iph->saddr == in_aton(client_ip))) { printk ("In output\n"); } return NF_ACCEPT; } static int __init filter_init(void) { int ret; nfho.hook = checksum; nfho.pf = AF_INET; // nfho.hooknum = NF_INET_PRE_ROUTING; nfho.hooknum = NF_INET_LOCAL_IN; // nfho.hooknum = NF_IP_PRE_ROUTING; nfho.priority = NF_IP_PRI_FIRST; nfout.hook = output; nfout.pf = AF_INET; nfout.hooknum = NF_INET_POST_ROUTING; nfho.priority = NF_IP_PRI_FIRST; printk ("Hello,init forward~~~~~~~.\n"); ret = nf_register_hook(&nfho); if(ret < 0) { printk("%s\n", "can't modify skb hook!"); return ret; } return 0; } static void filter_fini(void) { printk ("Hello,remove forward~~~~~~~.\n"); nf_unregister_hook(&nfho); } module_init(filter_init); module_exit(filter_fini); -- Jianzhang Peng -- To unsubscribe from this list: send the line "unsubscribe lvs-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html