linux网络协议栈源码分析-链路层arp地址解析协议(代码片段)

arm7star arm7star     2022-12-03     682

关键词:

1、ARP报文格式

 

1.1、ARP报文格式

ARP报文的格式如下:

(具体各字段的含义参考《TCP/IP详解卷 1:协议》第4章 ARP:地址解析协议)

1.2、内核定义

op定义如下:

#define	ARPOP_REQUEST	1		/* ARP request			*/
#define	ARPOP_REPLY	2		/* ARP reply			*/

协议类型定义如下:

#define ETH_P_IP	0x0800		/* Internet Protocol packet	*/
#define ETH_P_ARP	0x0806		/* Address Resolution packet	*/


 

2、ARP报文的创建(arp_create)

2.1、ARP首部结构体

struct arphdr 
	__be16		ar_hrd;		/* format of hardware address	*/
	__be16		ar_pro;		/* format of protocol address	*/
	unsigned char	ar_hln;		/* length of hardware address	*/
	unsigned char	ar_pln;		/* length of protocol address	*/
	__be16		ar_op;		/* ARP opcode (command)		*/
;

2.2、ARP报文创建(arp_create)

        ARP报文的创建主要就是为ARP报文分配内存并设置以太网首部、28字节ARP请求/应答的各个字段。arp_create函数代码如下:

struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, // type:  op(ARPOP_REQUEST/ARPOP_REPLY), ptype: 帧类型(ETH_P_IP/ETH_P_ARP), dest_ip: 目的IP地址
			   struct net_device *dev, __be32 src_ip, // dev: 输出网卡设备, src_ip: 发送端IP地址
			   const unsigned char *dest_hw, // dest_hw: 以太网目的地址(以太网首部)
			   const unsigned char *src_hw, // 发送端以太网地址
			   const unsigned char *target_hw) // target_hw: 目的以太网地址(ARP应答报文设置, ARP请求为空)

	struct sk_buff *skb;
	struct arphdr *arp;
	unsigned char *arp_ptr;
	int hlen = LL_RESERVED_SPACE(dev);
	int tlen = dev->needed_tailroom;

	/*
	 *	Allocate a buffer
	 */

	skb = alloc_skb(arp_hdr_len(dev) + hlen + tlen, GFP_ATOMIC); // 分配ARP报文内存(以太网首部+28字节ARP请求/应答)
	if (!skb)
		return NULL;

	skb_reserve(skb, hlen); // 预留hlen长度的内存(以太网首部)
	skb_reset_network_header(skb);
	arp = (struct arphdr *) skb_put(skb, arp_hdr_len(dev)); // 预留ARP首部的内存空间(获取skb内存地址,skb内存地址后移ARP首部大小)
	skb->dev = dev;
	skb->protocol = htons(ETH_P_ARP); // 帧类型(ETH_P_ARP, ARP请求或应答)
	if (!src_hw)
		src_hw = dev->dev_addr;
	if (!dest_hw) // 目的以太网地址(ARP请求没有目的以太网地址,设置为广播地址FF:FF:FF:FF:FF:FF)
		dest_hw = dev->broadcast; // 广播地址FF:FF:FF:FF:FF:FF

	/*
	 *	Fill the device header for the ARP frame
	 */
	if (dev_hard_header(skb, dev, ptype, dest_hw, src_hw, skb->len) < 0) // 调用eth_header填充以太网首部(ptype: 帧类型, dest_hw: 以太网目的地址, src_hw: 以太网源地址)
		goto out;

	/*
	 * Fill out the arp protocol part.
	 *
	 * The arp hardware type should match the device type, except for FDDI,
	 * which (according to RFC 1390) should always equal 1 (Ethernet).
	 */
	/*
	 *	Exceptions everywhere. AX.25 uses the AX.25 PID value not the
	 *	DIX code for the protocol. Make these device structure fields.
	 */
	switch (dev->type) 
	default:
		arp->ar_hrd = htons(dev->type); // 设置ARP首部硬件类型(ARPHRD_ETHER)
		arp->ar_pro = htons(ETH_P_IP); // 设置ARP首部协议类型(ETH_P_IP)
		break;

#if IS_ENABLED(CONFIG_AX25)
	case ARPHRD_AX25:
		arp->ar_hrd = htons(ARPHRD_AX25);
		arp->ar_pro = htons(AX25_P_IP);
		break;

#if IS_ENABLED(CONFIG_NETROM)
	case ARPHRD_NETROM:
		arp->ar_hrd = htons(ARPHRD_NETROM);
		arp->ar_pro = htons(AX25_P_IP);
		break;
#endif
#endif

#if IS_ENABLED(CONFIG_FDDI)
	case ARPHRD_FDDI:
		arp->ar_hrd = htons(ARPHRD_ETHER);
		arp->ar_pro = htons(ETH_P_IP);
		break;
#endif
	

	arp->ar_hln = dev->addr_len; // 设置ARP首部硬件地址长度(6, 物理地址长度)
	arp->ar_pln = 4; // 设置ARP首部协议地址长度(4, IP地址长度)
	arp->ar_op = htons(type); // op(ARPOP_REQUEST/ARPOP_REPLY)

	arp_ptr = (unsigned char *)(arp + 1); // arp_ptr指针指向发送端以太网地址

	memcpy(arp_ptr, src_hw, dev->addr_len); // 拷贝发送端以太网地址到ARP报文发送端以太网地址里面
	arp_ptr += dev->addr_len; // 发送端以太网地址指针+地址长度(6),arp_ptr指针指向发送端IP地址
	memcpy(arp_ptr, &src_ip, 4); // 拷贝发送端IP地址到ARP报文发送端地址里面
	arp_ptr += 4; // 发送端IP地址指针+4,arp_ptr指针指向目的以太网地址

	switch (dev->type) 
#if IS_ENABLED(CONFIG_FIREWIRE_NET)
	case ARPHRD_IEEE1394:
		break;
#endif
	default:
		if (target_hw) // 目的以太网地址不为空(ARP应答报文)
			memcpy(arp_ptr, target_hw, dev->addr_len); // 拷贝目的以太网地址到ARP的目的以太网地址里面
		else // 目的以太网地址为空(ARP请求报文)
			memset(arp_ptr, 0, dev->addr_len); // ARP请求报文,设置目的以太网地址为00:00:00:00:00:00
		arp_ptr += dev->addr_len; // 目的以太网地址指针+地址长度(6),arp_ptr指针指向目的IP地址
	
	memcpy(arp_ptr, &dest_ip, 4); // 拷贝目的IP地址到ARP报文的目的IP地址里面

	return skb;

out:
	kfree_skb(skb);
	return NULL;

3、ARP报文的发送

3.1、ARP请求报文的发送

        arp_send_dst调用arp_create创建ARP报文后,调用arp_xmit发送ARP报文,最后调用__dev_queue_xmit将报文发送到网卡的发送队列里面。

         ARP报文最后通过调用网卡设备驱动函数smsc911x_hard_start_xmit发送到网卡里面,smsc911x_hard_start_xmit调用栈如下:

       

 3.2、ARP应答报文的发送

        首先网卡收到报文触发硬件中断,调用网卡的中断处理函数smsc911x_irqhandler(smsc911x_drv_probe注册的中断处理函数),smsc911x_irqhandler最终调用____napi_schedule触发NET_RX_SOFTIRQ软件中断,在硬件中断返回时,调用软件中断处理函数。

        __do_softirq软件中断调用栈如下:

        smsc911x_poll从网卡读取报文并设置帧类型skb->protocol,__netif_receive_skb_core调用deliver_ptype_list_skb找到对应协议的packet_type,packet_type报文对应协议的输入函数,对于ARP协议的packet_type就是arp_packet_type,处理函数就是arp_rcv,arp_rcv最终调用arp_process处理ARP报文,对于ARP请求,调用arp_send_dst发送ARP应答报文,调用代码如下:

         ARP请求输入到ARP应答再到发送到网卡的调用栈如下:

网络层--地址解析协议arp

...解决这个问题的。ARP协议通过前面几篇文章,我们知道,网络层使用的是IP地址,但在实际网络的链路上传送数据帧,最终还是必须使用该网络的硬件地址。IP地址和硬件地址由于格式不同,所以不存在简单的映射关系(IP地址32... 查看详情

lwip协议栈:arp协议(代码片段)

...ARP(AddressResolutionProtocol),地址解析协议。ARP协议处于网络层,其主要功能就是通过目标设备的IP地址,查询目标设备的MAC地址,从而进行网络通信。网络层中,源主机和目标主机依赖于IP地址进行通信。而链路层又有自己的寻... 查看详情

地址解析协议(arp)

...么主机需要有各自的ipv4地址和mac地址才能通信呢?ip属于网络层,mac地址属于数据链路层。通过沿ip传输的路径是逻辑路径,由路由设备根据路由表进行转发,而一条逻辑路径包括多个数据链路。沿独立的数据链路传播的时候,... 查看详情

网络协议笔记-网络层-arp协议

...地址。【2.2-为什么要使用ARP】  在数据传输过程中,网络层使用的IP地址,但是在实际传输的时候,数据是从网络的数据链路上传送数据帧的(就是数据链路层所做的工作,七层网络结构中,数据从上往下移动),所以最终还... 查看详情

计算机网络-----arp协议

... 由于是IP协议使用了ARP协议,因此通常就把ARP协议划归网络层。但是ARP协议的用途是为了从网络层使用的IP地址解析出在数据链路层使用的硬件地址,因此,把ARP协议划归在数据 查看详情

arp(addressresolutionprotocol)地址解析协议初识

...中第二层——数据链路层。使用ARP地址解析协议,可根据网络层IP数据包包头中的IP地址信息解析出目标硬件地址(MAC地址)信息,以保证通信的顺利进行。可能会受到恶意攻击——ARP欺骗与IPV6的NDP协议相比,ARP使用广播的效率... 查看详情

linux从青铜到王者第二十一篇:linux网络基础第三篇之数据链路层

系列文章目录文章目录系列文章目录前言一、数据链路层的以太网协议二、认识MAC地址三、对比理解MAC地址和IP地址四、ARP协议的作用五、ARP数据报格式五、ARP协议工作流程六、ARP缓存表七、DNS(DomainNameSystem)八、NAT协议九、NAPT协... 查看详情

linux网络编程----网络接口层(数据链路层+物理层)

...争用问题解决局域网的争用问题--交换机以太网帧格式跨网络传输认识MAC地址对比理解IP与MAC地址ARP协议ARP协议格式ARP协议作用ARP请求与ARP应答ARP请求ARP应答查看ARP和MAC地址对应的映射关系DNS(域名解析)ICMP--工作在网络层的协议pin... 查看详情

第二章arp——地址解析协议

...寻址机制(常常为48bit地址),这是使用数据链路的任何网络层都必须遵从的。一个网络如以太网可以同时被不同的网络层使用。例如,一组使用TCP/IP协议的主机和另一组使用某种PC网络软件的主机可以共享相同的电缆。当一台... 查看详情

linux网络协议栈源码分析-传输层(tcp连接的建立)(代码片段)

1、bind系统调用1.1、地址端口及状态检查(inet_bind)    通过路由表查找绑定地址的路由类型,对于非本地IP检查是否允许绑定非本地IP地址;检查公认端口绑定权限,是否允许绑定0~1024端口;检查socket是否已经绑定... 查看详情

linux网络协议栈源码分析-传输层(tcp连接的建立)(代码片段)

1、bind系统调用1.1、地址端口及状态检查(inet_bind)    通过路由表查找绑定地址的路由类型,对于非本地IP检查是否允许绑定非本地IP地址;检查公认端口绑定权限,是否允许绑定0~1024端口;检查socket是否已经绑定... 查看详情

arp(地址解析协议)

...通信,必须要知道目标主机的MAC地址。而在TCP/IP协议中,网络层和传输层只关心目标主机的IP地址。这就导致在以太网中使用IP协议时,数据链路层的以太网协议接到上层IP协议提供的数据中,只包含目的主机的IP地址。于是需要... 查看详情

linux网络基础--网络层与数据链路层(代码片段)

网络基础--网络层与数据链路层详解🌴网络层🌿网络层概念🌵网络层主要功能🌿网络层协议🌵IP协议🍁基本概念🍁协议头格式🍁网段划分🌱特殊的IP地址🌱IP地址的数量限制🌱私有I... 查看详情

linux网络协议栈源码分析-网络层ip网际协议(代码片段)

1、IP报文1.1、IP报文格式         更详细的介绍参考《TCP/IP详解卷1:协议》第3章IP:网际协议。1.2、IP首部结构体structiphdr#ifdefined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, version:4;#elifdefined(__BIG_ENDIAN_BITFIELD) __u8 vers 查看详情

arp欺骗分析

...址才能上网,那arp用来干嘛的呢?如果我们学习过计算机网络,就应该知道,上网需要网络协议-》TCP/IP协议(抽象上)有四层,上三层传输数据需要IP地址传输,最底一层数据传输则需要ARP解析成MAC地址进行传输。 查看详情

网络协议面试题

...模型的区别是什么?答:OSI参考模型和TCP/IP协议模型都是网络协议栈的标准模型,但OSI参考模型包括七层协议,分别是物理层,数据链路层,网络层,传输层,会话层,表示层和应用层;TCP/IP协议模型只包括四层协议,分别是网... 查看详情

arp协议

《ARP协议介绍》<以太网通讯格式>在计算机网络中,数据的发送就是将数据按照网络分层中的各层协议封装的过程,在这个过程中,最终要使用的协议是以太网协议(数据链路成协议) 分析:目的MAC地址:接受者的物理... 查看详情

链路层:eth协议,arp协议,mtu

...,其中传输层描述了端口表示哪两个进程处理,网络层描述了IP地址,也就是通信两端主机,但是数据无法直接从一段到达另一端,实际传输是通过了很多相邻节点设备之间的传输完成的eth-以太网协议:mac... 查看详情