Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1371840
  • 博文数量: 244
  • 博客积分: 10311
  • 博客等级: 上将
  • 技术积分: 3341
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-14 21:50
文章分类

全部博文(244)

文章存档

2013年(6)

2012年(5)

2011年(16)

2010年(11)

2009年(172)

2008年(34)

分类: LINUX

2009-04-27 14:56:37

Linux内核ARP的发送函数分析

void arp_send(int type, int ptype, u32 dest_ip,
struct net_device *dev, u32 src_ip,
unsigned char *dest_hw, unsigned char *src_hw,
unsigned char *target_hw)
当系统的网络驱动程序收到一个arp包的时候,调用这个函数处理。简单来说,arp_rev
发回本机器或者它代理的其他机器的网卡硬件地址(mac address),并且将发送者的网卡硬件地址放在自己的缓存(arp cache)中。
实现过程:

(1) 分配一个sk_buff,用来构造ARP包,除了必要的空间以外,还预留了15字节作备用。
调用skb_reserve空出前面的15字节和网络包头部。
skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
+ dev->hard_header_len + 15, GFP_ATOMIC);
if (skb == NULL)
return;

skb_reserve(skb, (dev->hard_header_len+15)&~15);
skb->nh.raw = skb->data;
arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4));
skb->dev = dev;
skb->protocol = __constant_htons (ETH_P_ARP);

+ 如果从参数传进来的源硬件地址为空的话,则设为设备的硬件地址;
如果从参数传进来的目的硬件地址为空的话,则设为广播地址。
if (src_hw == NULL)
src_hw = dev->dev_addr;
if (dest_hw == NULL)
dest_hw = dev->broadcast;
+ 调用网卡设备本身的MAC头部构造函数,填好这个ARP包的ethernet目的硬件地址和源硬件地址。
ethernet的缺省构造函数为eth_header,请参见net_init.c中的ether_setup函数。
if (dev->hard_header &&
dev->hard_header(skb,dev,ptype,dest_hw,src_hw,skb->len) ar_hrd = htons(dev->type);
arp->ar_pro = __constant_htons(ETH_P_IP);

+ 填写硬件地址长度(一般为6 字节)和协议地址长度(4 字节);
填写arp包的类型,arp请求为1,arp应答为2。
arp->ar_hln = dev->addr_len;
arp->ar_pln = 4;
arp->ar_op = htons(type);

填写arp包的数据,包括源ethernet地址(sha)、源ip地址(sip)、目的ethernet地址(tha) 和目的ip地址(tip)。
arp_ptr=(unsigned char *)(arp+1);

memcpy(arp_ptr, src_hw, dev->addr_len);
arp_ptr+=dev->addr_len;
memcpy(arp_ptr, &src_ip,4);
arp_ptr+=4;
if (target_hw != NULL)
memcpy(arp_ptr, target_hw, dev->addr_len);
else
memset(arp_ptr, 0, dev->addr_len);
arp_ptr+=dev->addr_len;
memcpy(arp_ptr, &dest_ip, 4);

+ 最后,调用dev_queue_xmit将这个ARP包放在发送队列中准备发送。
dev_queue_xmit(skb);


 

阅读(3619) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~