1. Ideas
Allocate space---> Populate UDP, IP, Ethernet headers, and send data---> Send construction-completed messages
2, need to understand the interface
ALLOC_SKB Allocating SKB Space
Skb_reserve on SKB head (move data pointer and SKB tail pointer back)
Skb_push move the data head pointer forward (Skb_reserve reserve space for this operation)
Skb_reset_transport_header Reset Transfer Beginning header pointer (there are two ways of offset and no offset)
Skb_set_transport_header resetting and setting the transfer beginning header pointer
Skb_reset_network_header Resetting the IP beginning Text header pointer
Skb_reset_mac_header Reset link Beginning text head pointer
3, UDP send the text interface implementation
#defineICMP 1#defineETH "Eth0"#defineS_port 9988#defineD_port 8899U_long s_ip=0xc0a8034d;//"192.168.3.77"U_long d_ip =0xc0a80305;//"192.168.3.5"UnsignedChars_mac[eth_alen]={0x00,0x0c,0x29,0x41,0x3e,0x66};/*Local MAC address*/unsignedChard_mac[eth_alen]={0x14,0xa5,0x1a,0xba,0xf1,0x04};/*Gateway MAC address*/Static intMy_diyudp_and_send (Char*eth, U_char *smac, U_char *Dmac, U_char*PKT,intpkt_len,u_long sip, u_long dip, U_short Sport, U_short dport) { intRET =-1; unsignedintpktsize; structSk_buff *SKB =NULL; structNet_device *dev =NULL; structETHHDR *ethheader =NULL; structIPHDR *ipheader =NULL; structUDPHDR *udpheader =NULL; U_char*pdata =NULL; /*parameter legality check*/ if(NULL = = SMAC | | NULL = =Dmac)Goto out; /*Get interface Device information by export interface name*/Dev= Dev_get_by_name (&init_net, ETH); if(NULL = =Dev) {PRINTK (Kern_err"unknow Device name:%s\n", ETH); Goto out; } /*Calculate message Length*/pktsize= Pkt_len +sizeof(structIPHDR) +sizeof(structUDPHDR) +ll_reserved_space (Dev); SKB=alloc_skb (pktsize, gfp_atomic); if(NULL = =SKB) {PRINTK (Kern_err"malloc SKB fail\n"); Goto out; } /*reserve the required space in the head*/Skb_reserve (SKB, pktsize); SKB->dev =Dev; SKB->pkt_type =Packet_otherhost; SKB->protocol =__constant_htons (ETH_P_IP); SKB->ip_summed = Checksum_none;//UDP Checksum initializationSkb->priority =0; Pdata=Skb_push (SKB, Pkt_len); if(NULL! =pkt) memcpy (pdata, PKT, Pkt_len); /*populating the UDP header*/Udpheader= (structudphdr*) Skb_push (SKB,sizeof(structudphdr)); memset (Udpheader,0,sizeof(structudphdr)); Udpheader->source =htons (sport); Udpheader->dest =htons (Dport); SKB->csum =0; Udpheader->len = htons (sizeof(structUDPHDR) +Pkt_len); Udpheader->check =0; Skb_reset_transport_header (SKB); /*Populating IP Headers*/Ipheader= (structiphdr*) Skb_push (SKB,sizeof(structiphdr)); Ipheader->version =4; Ipheader->IHL =sizeof(structIPHDR) >>2;//IP head LengthIpheader->frag_off =0; Ipheader->protocol =ipproto_udp; Ipheader->tos =0; Ipheader->SADDR =htonl (SIP); Ipheader->DADDR =htonl (DIP); Ipheader->ttl =0x40; Ipheader->tot_len = htons (Pkt_len +sizeof(structIPHDR) +sizeof(structudphdr)); Ipheader->check =0; Ipheader->check = Ip_fast_csum ((unsignedChar*) Ipheader, ipheader->IHL); Skb_reset_network_header (SKB); SKB->csum = Skb_checksum (SKB, ipheader->ihl*4, skb->len-ipheader->ihl*4,0); Udpheader->check = csum_tcpudp_magic (SIP, dip, skb->len-ipheader->ihl*4, IPPROTO_UDP, skb->csum); /*Populate Mac*/Ethheader= (structethhdr*) Skb_push (SKB, -); memcpy (Ethheader-h_dest, Dmac, Eth_alen); memcpy (Ethheader-H_source, SMAC, Eth_alen); Ethheader->h_proto =__constant_htons (ETH_P_IP); Skb_reset_mac_header (SKB); /*send PKT Dev_queue_xmit will release the appropriate space after it is sent. So be careful not to do a repeat release*/ if(0>Dev_queue_xmit (SKB)) {PRINTK (Kern_err"Send PKT Error"); Goto out; } ret=0; PRINTK (Kern_info"Send success\n"); out: if(Ret! =0&& NULL! =SKB) {dev_put (dev); KFREE_SKB (SKB); } returnnf_accept;}
4, need to pay attention to
1) The conversion of the host sequence to the network sequence is required for the 2-byte and 4-byte fields in the packet header.
2) Call the location where the message function is constructed (at the very beginning of the practice, because all packages are discarded and then UDP is sent, SSH cannot be logged in)
5. Function call
StaticUnsignedintMy_hook_test (unsignedintHooknum,structSk_buff *SKB,Const structNet_device *inch,Const structNet_device * out,int(*OKFN) (structSk_buff *)){ Const structIPHDR *iph =Ip_hdr (SKB); //Filter ICMP if(Iph->protocol = =ICMP) {PRINTK (Kern_info"recv pkt (%u):p rotocol:%u, src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n", pktcnt, Iph->protocol, Nipquad (IPH->SADDR), Nipquad (iph->daddr)); My_diyudp_and_send (ETH, S_mac, D_mac,"Hello from Slackware", strlen ("Hello from Slackware"), S_ip, D_ip, S_port, D_port); returnNf_drop; } returnnf_accept;}//Mount the hook, hang it in the exit processing positionStatic structNf_hook_ops Nfhello ={. Hook=my_hook_test,. Owner=this_module,. PF=pf_inet,. Hooknum= Nf_inet_local_out,//node that is mounted on the egress processing message. Priority = Nf_ip_pri_first,//Highest priority level};Static intMy_netfilter_init (void) {PRINTK (Kern_info"init my nodule\n"); /*Register Hooks*/Nf_register_hook (&Nfhello); return 0;}Static voidMy_netfilter_exit (void) {PRINTK (Kern_info"Goodbye my module\n"); /*Uninstalling Hooks*/Nf_unregister_hook (&Nfhello);} Module_init (My_netfilter_init); Module_exit (My_netfilter_exit); Module_license ("GPL"); Module_author ("Zhaojie"); Module_description ("Hello NetFilter");
6. Operation Result
Linux NetFilter Mount Hooks send a simple UDP message