#define
ETH "eth0" //接口名称
#define
SIP
"192.168.6.130" //接口的IP地址
#define
DIP "118.6.24.132" //要发送UDP报文的目的IP地址
#define
SPORT 39804 //源端口
#define
DPORT 6980 //目的端口
unsigned char SMAC[ETH_ALEN]
= {0x00,0x0C,0x29,0x33,0x2C,0x3C}; //eth0网卡地址
unsigned char DMAC[ETH_ALEN]
= {0x00,0x50,0x56,0xF4,0x8B,0xB3}; //默认网关的网卡地址
static int build_and_xmit_udp(char * eth,
u_char * smac, u_char * dmac,
u_char * pkt, int pkt_len,u_long sip,
u_long dip,
u_short sport, u_short dport)
{
struct sk_buff * skb = NULL;
struct net_device * dev = NULL;
struct ethhdr * ethdr = NULL;
struct iphdr * iph = NULL;
struct udphdr * udph = NULL;
u_char * pdata = NULL;
if(NULL == smac || NULL == dmac)
goto out;
if(NULL == (dev= dev_get_by_name(eth)))
goto out;
//通过alloc_skb()来为一个新的skb申请内存结构
skb = alloc_skb(pkt_len
+ sizeof(struct iphdr) + sizeof(struct udphdr) + LL_RESERVED_SPACE(dev),
GFP_ATOMIC);
if(NULL == skb)
goto out;
skb_reserve(skb,
LL_RESERVED_SPACE(dev));
skb->dev = dev;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = __constant_htons(ETH_P_IP);
skb->ip_summed = CHECKSUM_NONE;
skb->priority = 0;
skb->nh.iph = (struct iphdr*)skb_put(skb, sizeof(struct iphdr));
skb->h.uh = (struct udphdr*)skb_put(skb, sizeof(struct udphdr));
pdata = skb_put(skb, pkt_len); //预留给上层用于数据填充的接口
{
if(NULL != pkt)
memcpy(pdata, pkt, pkt_len);
}
//“从上往下”填充skb结构,依次是UDP层--IP层--MAC层
udph
= (struct udphdr *)skb->h.uh;
memset(udph,
0, sizeof(struct udphdr));
udph->source
= sport;
udph->dest
= dport;
skb->csum
= 0;
udph->len
= htons(sizeof(struct udphdr)+pkt_len);
udph->check
= 0;
//填充IP层
iph
= (struct iphdr*)skb->nh.iph;
iph->version
= 4;
iph->ihl
= sizeof(struct iphdr)>>2;
iph->frag_off
= 0;
iph->protocol
= IPPROTO_UDP;
iph->tos
= 0;
iph->daddr
= dip;
iph->saddr
= sip;
iph->ttl
= 0x40;
iph->tot_len
= __constant_htons(skb->len);
iph->check
= 0;
iph->check
= ip_fast_csum((unsigned char *)iph,iph->ihl);
skb->csum = skb_checksum(skb, iph->ihl*4, skb->len -
iph->ihl * 4, 0);
udph->check = csum_tcpudp_magic(sip, dip, skb->len - iph->ihl
* 4, IPPROTO_UDP, skb->csum);
//填充MAC层
skb->mac.raw = skb_push(skb, 14);
ethdr
= (struct ethhdr *)skb->mac.raw;
memcpy(ethdr->h_dest,
dmac, ETH_ALEN);
memcpy(ethdr->h_source,
smac, ETH_ALEN);
ethdr->h_proto
= __constant_htons(ETH_P_IP);
//调用dev_queue_xmit()发送报文
if(0 > dev_queue_xmit(skb))
goto out;
out:
if(NULL != skb)
{
dev_put (dev);
kfree_skb (skb);
}
return(NF_ACCEPT);
}