手写TCP/IP协议栈——ARP输入处理

理论部分

对方ARP包过来之后,我们需要先检查包的合法性,然后在switch...case里面处理ARP包

在虚拟机里面ping一下192.168.254.1

如果arp表中没有改IP,会先发送arp广播包

收到回复之后,再发送ICMP请求包,对方ICMP响应回来(往返四次请求-响应)

代码实现部分

在ethernet_in以太网输入部分,添加对XNET_PROTOCOL_ARP的处理

cpp 复制代码
switch (swap_order16(hdr->protocol))
	{
	case XNET_PROTOCOL_ARP:
		remove_header(packet, sizeof(xether_hdr_t));
		xarp_in(packet);
		break;
	case XNET_PROTOCOL_IP:
		break;
	}

arp包输入处理部分:

ARP输入主要处理两种情况:①别人的ARP请求处理 ②别人的ARP回复处理

cpp 复制代码
#define xipaddr_is_equal_buf(addr,buf) (memcmp((addr->array),(buf),XNET_IPV4_ADDR_SIZE)==0)

void xarp_in(xnet_packet_t* packet)
{
	if (packet->size >= sizeof(xarp_packet_t))
	{
		xarp_packet_t* arp_packet = (xarp_packet_t*)packet->data;
		uint16_t opcode = swap_order16(arp_packet->opcode);

		if ((swap_order16(arp_packet->hw_type) != XARP_HW_ETHER) ||
			(arp_packet->hw_len != XNET_MAC_ADDR_SIZE) ||
			(swap_order16(arp_packet->pro_type) != XNET_PROTOCOL_IP) ||
			(arp_packet->pro_len != XNET_IPV4_ADDR_SIZE) ||
			((opcode != XARP_REQUEST) && (opcode != XARP_REPLY)))
			return;

		if (!xipaddr_is_equal_buf(&netif_ipaddr, arp_packet->target_ip))
			return;

		switch (swap_order16(arp_packet->opcode))
		{
		case XARP_REQUEST:
			xarp_make_response(arp_packet);
			update_arp_entry(arp_packet->sender_ip, arp_packet->sender_mac);
			break;
		case XARP_REPLY:
			update_arp_entry(arp_packet->sender_ip, arp_packet->sender_mac);
			break;
		}
	}
}

arp响应数据包传送

更新本地arp缓存表

cpp 复制代码
xnet_tinny.h

#define XARP_ENTRY_FREE  0
#define XARP_ENTRY_OK    1

xnet_tinny.c

xnet_err_t xarp_make_response(xarp_packet_t* arp_packet)
{
	xarp_packet_t* response_packet;
	xnet_packet_t* packet = xnet_alloc_for_send(sizeof(xarp_packet_t));

	response_packet = (xarp_packet_t*)packet->data;
	response_packet->hw_type = swap_order16(XARP_HW_ETHER);
	response_packet->pro_type = swap_order16(XNET_PROTOCOL_IP);
	response_packet->hw_len = XNET_MAC_ADDR_SIZE;
	response_packet->pro_len = XNET_IPV4_ADDR_SIZE;
	response_packet->opcode = swap_order16(XARP_REPLY);
	memcpy(response_packet->target_mac, arp_packet->sender_mac, XNET_MAC_ADDR_SIZE);
	memcpy(response_packet->target_ip, arp_packet->sender_ip, XNET_IPV4_ADDR_SIZE);
	memcpy(response_packet->sender_mac, netif_mac, XNET_MAC_ADDR_SIZE);
	memcpy(response_packet->sender_ip, netif_ipaddr.array, XNET_IPV4_ADDR_SIZE);
	
	return ethernet_out_to(XNET_PROTOCOL_ARP, response_packet->target_mac, packet);
}

static void update_arp_entry(uint8_t* src_ip, uint8_t* mac_addr)
{
	memcpy(arp_entry.ipaddr.array, src_ip, XNET_IPV4_ADDR_SIZE);
	memcpy(arp_entry.macaddr, mac_addr, XNET_MAC_ADDR_SIZE);
	arp_entry.state = XARP_ENTRY_OK;
}

在虚拟机当中ping一下我们的协议栈,发现可以进入arp请求处理

arp -a:查看本机arp缓存表

arp -d:清除本机arp缓存表(需要管理员权限)

最初arp -a能看到192.168.254.2说明无回报的arp数据包工作正常

我们把arp的表项删除掉

然后再ping一下192.168.254.2

此时我们通过arp_make_response已经可以给对方回复并更新arp缓存表了

ok,今天的你就到此为止吧,明天还要接着🐺啊!

相关推荐
草原上唱山歌4 分钟前
如何理解C语言中的指针?
c语言·开发语言·数据结构
无敌昊哥战神9 小时前
【LeetCode 257】二叉树的所有路径(回溯法/深度优先遍历)- Python/C/C++详细题解
c语言·c++·python·leetcode·深度优先
m0_4886333211 小时前
C语言中枚举类型变量的定义、赋值及使用方法全解析
c语言·枚举类型·实例分析·变量定义·赋值使用
老鱼说AI11 小时前
大规模并发处理器程序设计(PMPP)讲解(CUDA架构):第四期:计算架构与调度
c语言·深度学习·算法·架构·cuda
钛态12 小时前
Flutter 三方库 http_mock_adapter — 赋能鸿蒙应用开发的高效率网络接口 Mock 与自动化测试注入引擎(适配鸿蒙 HarmonyOS Next ohos)
android·网络协议·flutter·http·华为·中间件·harmonyos
IT小白315 小时前
windows的VMware虚拟机上的Linux系统(CentOS)配置永久ip(关机重启ip不变)
网络·网络协议·tcp/ip
小白橘颂16 小时前
【C语言】基础概念梳理(一)
c语言·开发语言·stm32·单片机·mcu·物联网·51单片机
co_wait16 小时前
【c 语言】linux下gcc编译工具的使用
linux·c语言·开发语言
always_TT16 小时前
结构体数组与初始化
c语言
蛊明16 小时前
批量检测 IP 是否在线:CPing vs QuickPing
网络·网络协议·tcp/ip