Linux内核构造和发送vlan&udp数据报文
2014-02-08 10:51
127 查看
原文地址:http://wenx05124561.blog.163.com/blog/static/124000805201242023941402/
Linux内核中构造ip数据包,通过网卡驱动直接发送是一种有效的发送数据包方式。本文通过构造数据包和发送数据包来实现该方式。
构造数据包:构造vlant头的ip和udp数据包
#define IP_HEAD_LENTH 20
#define UDP_HEAD_LENTH 8
#define VLAN_ETH_HLENTH 18
#define VLAN_UDP_LENTH (VLAN_ETH_HLENTH + IP_HEAD_LENTH + UDP_HEAD_LENTH )
#define MTU_SIZE 1500
struct vlan_packet
{
unsigned char data[MTU_SIZE];
unsigned short length;
};
struct payload_info
{
unsigned char data[MTU_SIZE - VLAN_UDP_LENTH];
unsigned short length;
unsigned int daddr;
};
struct sk_buff *send_skb ;
int create_new_packet(struct vlan_packet *packet, struct payload_info * payload_info)
{
struct vlan_ethhdr *vethhdr;
struct iphdr *iph;
struct udphdr *uh;
struct gtp_u_hdr *gh;
unsigned char *payload;
//unsigned short udp_check;
struct net_device *dev;
struct sk_buff *skb = NULL;
if(payload_info->length + VLAN_UDP_LENTH > MTU_SIZE)
return -EINVAL;
//填充vlan_ethhdr头结构,即MAC数据
memset(packet->data, 0, MTU_SIZE);
vethhdr = (struct vlan_ethhdr*)packet->data;
memcpy (vethhdr->h_dest, dmac, ETH_ALEN);
memcpy (vethhdr->h_source, smac, ETH_ALEN);
vethhdr->h_vlan_proto = htons(ETH_P_8021Q); //vlan mac 头
vethhdr->h_vlan_TCI = htons(0x0);
vethhdr->h_vlan_encapsulated_proto = htons(0x0800);//下一层协议IP
packet->length = VLAN_ETH_HLEN;
//填充ip头数据
iph =(struct iphdr *)(packet->data + VLAN_ETH_HLEN);
iph->version = 4;
iph->ihl = 5;
iph->tos = 0;
iph->tot_len = htons(VLAN_UDP_LENTH - VLAN_ETH_HLEN + payload_info->length);
iph->id = 0;
iph->frag_off = htons(0x4000);
iph->ttl = 64;
iph->protocol = IPPROTO_UDP;//下一层udp数据包
dev = dev_get_by_name(&init_net, "eth0");
iph->daddr = payload_info->daddr;
iph->saddr = dev->ip_ptr->ifa_list->ifa_address;//获取网口eth0 IP address
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);//ip 头校验和
packet->length += IP_HEAD_LENTH;
//填充udp头数据
uh = (struct udphdr *)(packet->data + VLAN_ETH_HLEN + IP_HEAD_LENTH);
uh->source = htons(0x1234);
uh->dest = htons(U_PORT);
uh->len = htons(UDP_HEAD_LENTH + payload_info->length);
packet->length += UDP_HEAD_LENTH;
//填充payload数据
payload = (packet->data + VLAN_ETH_HLEN + IP_HEAD_LENTH + UDP_HEAD_LENTH);
memcpy(payload, payload_info->data, payload_info->length);
packet->length += payload_info->length;
//分配skb数据结构
skb = dev_alloc_skb(packet->length + 200);
if (NULL == skb)
{
wx_debug("tmp skb alloc failed\n");
return -1;
}
skb_reserve(skb, 2);
skb_put(skb, packet->length);
skb->len = packet->length;
skb->protocol = htons(ETH_P_8021Q);
memcpy((unsigned char *)skb->data, packet->data, packet->length);
skb_pull(skb, VLAN_ETH_HLEN);
iph = (struct iphdr *)(skb->data);
skb_pull(skb, IP_HEAD_LENTH);
uh = (struct udphdr *)(skb->data);
//进行udp检验和计算
uh->check = 0;
skb->csum = csum_partial(skb->data, skb->len, 0);
uh->check = csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len, iph->protocol, skb->csum);
skb_push(skb, IP_HEAD_LENTH + VLAN_ETH_HLEN);
skb->ip_summed = CHECKSUM_COMPLETE;
skb->dev=dev_get_by_name(&init_net, "eth0");
send_skb = skb; //将skb存储于变量send _skb
return 0;
}
发送数据包:通过复制存储send_skb, 利用发送函数进行发送。
int alloc_skb_send()
{
int ret = 0;
//复制数据包
struct sk_buff *skb = skb_clone(skb_send, GFP_KERNEL);
//发送数据包
ret = dev_queue_xmit(skb);
if(ret > 0 && skb != NULL)
{
kfree_skb(skb);
printk("dev_queue_xmit failed\n");
return -1;
}
return 0;
}
Linux内核中构造ip数据包,通过网卡驱动直接发送是一种有效的发送数据包方式。本文通过构造数据包和发送数据包来实现该方式。
构造数据包:构造vlant头的ip和udp数据包
#define IP_HEAD_LENTH 20
#define UDP_HEAD_LENTH 8
#define VLAN_ETH_HLENTH 18
#define VLAN_UDP_LENTH (VLAN_ETH_HLENTH + IP_HEAD_LENTH + UDP_HEAD_LENTH )
#define MTU_SIZE 1500
struct vlan_packet
{
unsigned char data[MTU_SIZE];
unsigned short length;
};
struct payload_info
{
unsigned char data[MTU_SIZE - VLAN_UDP_LENTH];
unsigned short length;
unsigned int daddr;
};
struct sk_buff *send_skb ;
int create_new_packet(struct vlan_packet *packet, struct payload_info * payload_info)
{
struct vlan_ethhdr *vethhdr;
struct iphdr *iph;
struct udphdr *uh;
struct gtp_u_hdr *gh;
unsigned char *payload;
//unsigned short udp_check;
struct net_device *dev;
struct sk_buff *skb = NULL;
if(payload_info->length + VLAN_UDP_LENTH > MTU_SIZE)
return -EINVAL;
//填充vlan_ethhdr头结构,即MAC数据
memset(packet->data, 0, MTU_SIZE);
vethhdr = (struct vlan_ethhdr*)packet->data;
memcpy (vethhdr->h_dest, dmac, ETH_ALEN);
memcpy (vethhdr->h_source, smac, ETH_ALEN);
vethhdr->h_vlan_proto = htons(ETH_P_8021Q); //vlan mac 头
vethhdr->h_vlan_TCI = htons(0x0);
vethhdr->h_vlan_encapsulated_proto = htons(0x0800);//下一层协议IP
packet->length = VLAN_ETH_HLEN;
//填充ip头数据
iph =(struct iphdr *)(packet->data + VLAN_ETH_HLEN);
iph->version = 4;
iph->ihl = 5;
iph->tos = 0;
iph->tot_len = htons(VLAN_UDP_LENTH - VLAN_ETH_HLEN + payload_info->length);
iph->id = 0;
iph->frag_off = htons(0x4000);
iph->ttl = 64;
iph->protocol = IPPROTO_UDP;//下一层udp数据包
dev = dev_get_by_name(&init_net, "eth0");
iph->daddr = payload_info->daddr;
iph->saddr = dev->ip_ptr->ifa_list->ifa_address;//获取网口eth0 IP address
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);//ip 头校验和
packet->length += IP_HEAD_LENTH;
//填充udp头数据
uh = (struct udphdr *)(packet->data + VLAN_ETH_HLEN + IP_HEAD_LENTH);
uh->source = htons(0x1234);
uh->dest = htons(U_PORT);
uh->len = htons(UDP_HEAD_LENTH + payload_info->length);
packet->length += UDP_HEAD_LENTH;
//填充payload数据
payload = (packet->data + VLAN_ETH_HLEN + IP_HEAD_LENTH + UDP_HEAD_LENTH);
memcpy(payload, payload_info->data, payload_info->length);
packet->length += payload_info->length;
//分配skb数据结构
skb = dev_alloc_skb(packet->length + 200);
if (NULL == skb)
{
wx_debug("tmp skb alloc failed\n");
return -1;
}
skb_reserve(skb, 2);
skb_put(skb, packet->length);
skb->len = packet->length;
skb->protocol = htons(ETH_P_8021Q);
memcpy((unsigned char *)skb->data, packet->data, packet->length);
skb_pull(skb, VLAN_ETH_HLEN);
iph = (struct iphdr *)(skb->data);
skb_pull(skb, IP_HEAD_LENTH);
uh = (struct udphdr *)(skb->data);
//进行udp检验和计算
uh->check = 0;
skb->csum = csum_partial(skb->data, skb->len, 0);
uh->check = csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len, iph->protocol, skb->csum);
skb_push(skb, IP_HEAD_LENTH + VLAN_ETH_HLEN);
skb->ip_summed = CHECKSUM_COMPLETE;
skb->dev=dev_get_by_name(&init_net, "eth0");
send_skb = skb; //将skb存储于变量send _skb
return 0;
}
发送数据包:通过复制存储send_skb, 利用发送函数进行发送。
int alloc_skb_send()
{
int ret = 0;
//复制数据包
struct sk_buff *skb = skb_clone(skb_send, GFP_KERNEL);
//发送数据包
ret = dev_queue_xmit(skb);
if(ret > 0 && skb != NULL)
{
kfree_skb(skb);
printk("dev_queue_xmit failed\n");
return -1;
}
return 0;
}
相关文章推荐
- QXDM抓包模板:NB-IOT模组UDP周期发送数据,过一段时间模组和基站无空口报文交互
- python3.5 模拟UDP客户端发送数据报文,报错:TypeError: a bytes-like object is required, not 'str'
- C# UDP接收不同端口的数据报文
- 用UDP进行广播后绑定发送Json数据进行通讯
- Java构造方法&数据类型(5.21)
- 使用UDP协议编写一个网络程序,设置接收端程序的监听端口是8001,发送端发送的数据是“Hello, world”。
- Android Wear 进阶 - 4 发送和同步数据 <Sending and Syncing Data>
- JAVA编码转换的详细过程理解—>浏览器和服务器的接收和发送数据的编码
- 用asp.net 发送udp数据
- 网络编程_UDP协议发送和接收数据代码优化
- Java中通过UDP协议发送和接受数据
- [ActionScript 3.0] AS向php发送二进制数据方法之——在URLRequest中构造HTTP协议发送数据
- 循环发送递增数据的方法 && BCD码和ASCII码的转换 && fgets的一个说明
- UIP协议栈UDP数据发送的问题
- udp 发送和接收结构体数据
- 在内核中构造一个UDP 数据
- C语言中的随机数 && 商余函数ldiv && 长数据分段发送的方法
- Java 使用udp协议发送数据
- 十.TCP与UDP发送和接收数据的简单实现
- Winsock:获取UDP数据发送端的IP地址和端口号