手写TCP/IP协议——IP层输出处理

在无人问津的渡口,总是开满鲜花。

本节课主要实现将IP数据包添加头部并通过以太网发包的全过程

xnet_tinny.h

声明函数xip_out:

cpp 复制代码
#define XNET_VERSION_IPV4	4

xnet_err_t xip_out(xnet_protocol_t protocol, xipaddr_t* dest_ip, xnet_packet_t * packet);

xnet_tinny.c

cpp 复制代码
xnet_err_t xip_out(xnet_protocol_t protocol, xipaddr_t* dest_ip, xnet_packet_t* packet)
{
	static uint32_t ip_packet_id = 0;
	xip_hdr_t* iphdr;

	add_header(packet, sizeof(xip_hdr_t));
	iphdr = (xip_hdr_t*)packet->data;
	iphdr->version = XNET_VERSION_IPV4;
	iphdr->hdr_len = sizeof(xip_hdr_t) / 4;
	iphdr->tos = 0;
	iphdr->total_len = swap_order16(packet->size);
	iphdr->id = swap_order16(ip_packet_id);
	iphdr->flags_fragment = 0;
	iphdr->ttl = XNET_IP_DEFAULT_TTL;
	iphdr->protocol = protocol;
	memcpy(iphdr->dst_ip, dest_ip->array, XNET_IPV4_ADDR_SIZE);
	memcpy(iphdr->src_ip, netif_ipaddr.array, XNET_IPV4_ADDR_SIZE);
	iphdr->hdr_checksum = 0;
	iphdr->hdr_checksum = checksum16((uint16_t*)iphdr, sizeof(xip_hdr_t), 0, 1);

	ip_packet_id++;

	return ethernet_out(dest_ip, packet);
}

由于以太网层面无法直接识别IP地址,还需要实现一下IP地址到MAC地址的转换函数ethernet_out

将IP地址转为MAC地址之后,再调用以太网底层发送函数ethernet_out_to来完成发包

cpp 复制代码
static xnet_err_t ethernet_out(xipaddr_t* dest_ip, xnet_packet_t* packet)
{
	xnet_err_t err;
	uint8_t* mac_addr;

	if ((err = xarp_resolve(dest_ip, &mac_addr)) == XNET_ERR_OK)
		return ethernet_out_to(XNET_PROTOCOL_IP, mac_addr, packet);
	
	return err;
}

最后实现arp解析函数:xarp_resolve

首先添加错误码XNET_ERR_NONE表示缺少ARP表项

cpp 复制代码
typedef enum _xnet_err_t
{
	XNET_ERR_OK = 0,
	XNET_ERR_IO = -1,
	XNET_ERR_NONE = -2,
}xnet_err_t;

添加判断两个IP地址整数相同的宏函数

cpp 复制代码
#define xipaddr_is_equal(addr1, addr2)  ((addr1)->addr == (addr2)->addr)

xarp_resolve具体实现:

由于需要返回mac_addr的值,而在ethernet_out中mac_addr是uint8*所以这里mac_addr需要使用二级指针,才能返回解析后的值

cpp 复制代码
xnet_err_t xarp_resolve(const xipaddr_t* ipaddr, uint8_t** mac_addr)
{
	if ((arp_entry.state == XARP_ENTRY_OK) && xipaddr_is_equal(ipaddr, &arp_entry.ipaddr))
	{
		*mac_addr = arp_entry.macaddr;
		return XNET_ERR_OK;
	}
	xarp_make_request(ipaddr);

	return XNET_ERR_NONE;
}

最后重新生成解决方案,编译没问题即可

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

相关推荐
王老师青少年编程22 分钟前
csp信奥赛C++高频考点专项训练之字符串 --【子串查找】:[NOIP 2009 提高组] 潜伏者
c++·字符串·csp·高频考点·信奥赛·子串查找·潜伏者
初願致夕霞31 分钟前
基于系统调用的Linux网络编程——UDP与TCP
linux·网络·c++·tcp/ip·udp
小小de风呀2 小时前
de风——【从零开始学C++】(五):内存管理
开发语言·c++
数智化精益手记局2 小时前
什么是设备维护管理?设备维护管理包含哪些内容?
大数据·网络·人工智能·安全·信息可视化
CHANG_THE_WORLD3 小时前
C语言中的 %*s 和 %.*s 和C++的字符串格式化输出
c语言·c++·c#
消失的旧时光-19434 小时前
C语言对象模型系列(四)《Linux 内核里的 container_of 到底是什么黑魔法?》—— 一篇讲透 Linux 内核的“对象模型”核心技巧
linux·c语言·算法
螺丝钉的扭矩一瞬间产生高能蛋白4 小时前
QT的C++接口基础用法
c++·qt·嵌入式软件·嵌入式linux·linux应用
2501_931803755 小时前
Go:一门为解决C语言痛点而生的现代语言
c语言·开发语言·golang
salipopl5 小时前
FPGA中AXI-FIFO主机接口的自定义实现与versal读写工程分析
网络·fpga开发
智者知已应修善业5 小时前
【51单片机模拟生日蜡烛】2023-10-10
c++·经验分享·笔记·算法·51单片机