network arplab not finished

This commit is contained in:
2025-11-18 01:58:02 +08:00
parent 8d9c3ed7f6
commit b46bbe7232
33 changed files with 1641 additions and 384 deletions

View File

@@ -2,9 +2,14 @@
#include "xnet_tiny.h"
int main (void) {
printf("=== xnet starting ===\n");
fflush(stdout);
xnet_init();
printf("xnet running\n");
printf("=== xnet initialized, entering main loop ===\n");
fflush(stdout);
while (1) {
xnet_poll();
}

View File

@@ -1,5 +1,6 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "pcap_device.h"
#include "xnet_tiny.h"
@@ -7,17 +8,27 @@ static pcap_t * pcap;
// pcap所用的网卡
const char * ip_str = "10.20.6.8"; // 根据实际电脑上存在的网卡地址进行修改
const char my_mac_addr[] = {0x00, 0x50, 0x56, 0xc0, 0x00, 0x08};
const uint8_t my_mac_addr[] = {0x04, 0x7b, 0xcb, 0xce, 0x0a, 0x56};
/**
* 初始化网络驱动
* @return 0成功其它失败
*/
xnet_err_t xnet_driver_open (uint8_t * mac_addr) {
printf("[DRIVER] Opening pcap device for IP: %s\n", ip_str);
printf("[DRIVER] Using MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
my_mac_addr[0], my_mac_addr[1], my_mac_addr[2],
my_mac_addr[3], my_mac_addr[4], my_mac_addr[5]);
fflush(stdout);
memcpy(mac_addr, my_mac_addr, sizeof(my_mac_addr));
pcap = pcap_device_open(ip_str, mac_addr, 1);
if (pcap == (pcap_t *)0) {
printf("[DRIVER] Failed to open pcap device!\n");
fflush(stdout);
exit(-1);
}
printf("[DRIVER] Pcap device opened successfully\n");
fflush(stdout);
return XNET_ERR_OK;
}

View File

@@ -11,6 +11,7 @@ static const uint8_t net_broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
typedef enum _xarp_state_t {
XARP_ENTRY_STATE_FREE,
XARP_ENTRY_STATE_RESOLVED,
XARP_ENTRY_STATE_PENDING,
} xarp_state_t;
typedef struct _xarp_entry_t {
@@ -19,6 +20,7 @@ typedef struct _xarp_entry_t {
xarp_state_t state;
int tmo;
int retry;
xnet_packet_t *packet;
} xarp_entry_t;
static xarp_entry_t arp_table[XARP_CACHE_SIZE];
@@ -28,6 +30,7 @@ static xarp_entry_t arp_table[XARP_CACHE_SIZE];
void xarp_init(void) {
for (int i = 0; i < XARP_CACHE_SIZE; i++) {
arp_table[i].state = XARP_ENTRY_STATE_FREE;
arp_table[i].packet = (xnet_packet_t *)0;
}
}
@@ -40,11 +43,9 @@ static xarp_entry_t *find_entry(const uint8_t *ip_addr, int force) {
entry = arp_table + i;
break;
}
} else {
if (memcmp(arp_table[i].ip_addr, ip_addr, 4) == 0) {
entry = arp_table + i;
break;
}
} else if (memcmp(arp_table[i].ip_addr, ip_addr, 4) == 0) {
entry = arp_table + i;
break;
}
}
@@ -57,6 +58,11 @@ static void update_entry(const uint8_t *ip_addr, const uint8_t *mac_addr, int fo
memcpy(entry->ip_addr, ip_addr, 4);
memcpy(entry->mac_addr, mac_addr, XNET_MAC_ADDR_SIZE);
entry->state = XARP_ENTRY_STATE_RESOLVED;
if (entry->packet) {
ethernet_out_to(XNET_PROTOCOL_IP, mac_addr, entry->packet);
entry->packet = (xnet_packet_t *)0;
}
}
}
@@ -124,15 +130,34 @@ static void send_arp_request(const uint8_t *ip_addr) {
}
}
const uint8_t *xarp_resolve(const uint8_t *ip_addr) {
const uint8_t *xarp_resolve(xnet_packet_t *packet, const uint8_t *ip_addr) {
xarp_entry_t *entry = find_entry(ip_addr, 0);
if (entry) {
if (entry->state == XARP_ENTRY_STATE_RESOLVED) {
return entry->mac_addr;
} else if (entry->state == XARP_ENTRY_STATE_PENDING) {
if (entry->packet) {
xnet_free_packet(entry->packet);
}
entry->packet = packet;
return (const uint8_t *)0;
}
} else {
send_arp_request(ip_addr);
entry = find_entry(ip_addr, 1);
if (entry) {
entry->state = XARP_ENTRY_STATE_PENDING;
memcpy(entry->ip_addr, ip_addr, 4);
entry->packet = packet;
send_arp_request(ip_addr);
} else {
xnet_free_packet(packet);
}
}
return (const uint8_t *)0;
}
void xarp_update_from_ip(const uint8_t *ip_addr, const uint8_t *mac_addr) {
update_entry(ip_addr, mac_addr, 1);
}

View File

@@ -30,6 +30,7 @@ typedef struct _xarp_packet_t {
void xarp_init(void);
void xarp_in(xnet_packet_t *packet);
const uint8_t *xarp_resolve(const uint8_t *ip_addr);
const uint8_t *xarp_resolve(xnet_packet_t *packet, const uint8_t *ip_addr);
void xarp_update_from_ip(const uint8_t *ip_addr, const uint8_t *mac_addr);
#endif // XARP_H

View File

@@ -1,7 +1,9 @@
#include <string.h>
#include <stdio.h>
#include "xicmp.h"
#include "xnet_tiny.h"
#include "xip.h"
#include "xarp.h"
#define ICMP_TYPE_ECHO_REPLY 0
#define ICMP_TYPE_ECHO_REQUEST 8
@@ -30,6 +32,12 @@ static uint16_t checksum(void *buf, uint16_t len) {
}
void xicmp_in(xnet_packet_t *packet) {
if (packet->size < sizeof(xether_hdr_t) + sizeof(xip_hdr_t)) {
return;
}
// 先保留下以太头后续要使用源MAC更新ARP缓存
xether_hdr_t *ether_hdr = (xether_hdr_t *)packet->data;
remove_header(packet, sizeof(xether_hdr_t));
xip_hdr_t *ip_hdr = (xip_hdr_t *)packet->data;
@@ -37,7 +45,15 @@ void xicmp_in(xnet_packet_t *packet) {
return;
}
uint8_t hlen = (ip_hdr->hlen_ver & 0x0F) * 4;
if (hlen < sizeof(xip_hdr_t)) {
if ((hlen < sizeof(xip_hdr_t)) || (packet->size < hlen + sizeof(xicmp_packet_t))) {
return;
}
// 目前仅支持无IP选项的报文
if (hlen != sizeof(xip_hdr_t)) {
return;
}
// 仅处理ICMP协议
if (ip_hdr->protocol != 1) {
return;
}
if (checksum(ip_hdr, hlen) != 0) {
@@ -46,29 +62,67 @@ void xicmp_in(xnet_packet_t *packet) {
if (memcmp(ip_hdr->dest_ip, my_ip_addr, 4) != 0) {
return;
}
// 更新ARP缓存以便后续通过IP层发送应答而无需额外ARP查询
xarp_update_from_ip(ip_hdr->src_ip, ether_hdr->src);
uint16_t total_len = swap_order16(ip_hdr->total_len);
if (packet->size < total_len) {
return;
}
if (packet->size > total_len) {
packet->size = total_len;
}
xip_hdr_t saved_ip_hdr;
memcpy(&saved_ip_hdr, ip_hdr, sizeof(xip_hdr_t));
remove_header(packet, hlen);
if (packet->size < sizeof(xicmp_packet_t)) {
return;
}
xicmp_packet_t *icmp_packet = (xicmp_packet_t *)packet->data;
if (icmp_packet->type == ICMP_TYPE_ECHO_REQUEST) {
xnet_packet_t *tx_packet = xnet_alloc_for_send(packet->size);
if (tx_packet) {
memcpy(tx_packet->data, packet->data, packet->size);
printf("[ICMP] Received Echo Request from %d.%d.%d.%d\n",
saved_ip_hdr.src_ip[0], saved_ip_hdr.src_ip[1],
saved_ip_hdr.src_ip[2], saved_ip_hdr.src_ip[3]);
xicmp_packet_t *reply_icmp = (xicmp_packet_t *)tx_packet->data;
// 校验收到的ICMP包避免对错误数据做回复
if (checksum(icmp_packet, packet->size) != 0) {
printf("[ICMP] Checksum failed, dropping packet\n");
return;
}
// 分配发送缓冲区:需要包含以太网头 + IP头 + ICMP数据
xnet_packet_t *tx_packet = xnet_alloc_for_send(sizeof(xether_hdr_t) + packet->size + hlen);
if (tx_packet) {
// 跳过以太网头空间从IP头开始填充以太网头由ethernet_out_to填充
tx_packet->data += sizeof(xether_hdr_t);
tx_packet->size -= sizeof(xether_hdr_t);
xip_hdr_t *reply_ip_hdr = (xip_hdr_t *)tx_packet->data;
memcpy(reply_ip_hdr, &saved_ip_hdr, sizeof(xip_hdr_t));
reply_ip_hdr->total_len = swap_order16(packet->size + hlen);
memcpy(reply_ip_hdr->dest_ip, saved_ip_hdr.src_ip, 4);
memcpy(reply_ip_hdr->src_ip, my_ip_addr, 4);
reply_ip_hdr->ttl = 64;
reply_ip_hdr->hdr_checksum = 0;
reply_ip_hdr->hdr_checksum = checksum(reply_ip_hdr, hlen);
xicmp_packet_t *reply_icmp = (xicmp_packet_t *)((uint8_t *)tx_packet->data + hlen);
memcpy(reply_icmp, packet->data, packet->size);
reply_icmp->type = ICMP_TYPE_ECHO_REPLY;
reply_icmp->checksum = 0;
reply_icmp->checksum = checksum(reply_icmp, tx_packet->size);
reply_icmp->checksum = checksum(reply_icmp, packet->size);
xip_hdr_t *reply_ip_hdr = (xip_hdr_t *)(tx_packet->data - sizeof(xip_hdr_t));
memcpy(reply_ip_hdr, ip_hdr, sizeof(xip_hdr_t));
reply_ip_hdr->total_len = swap_order16(tx_packet->size + sizeof(xip_hdr_t));
memcpy(reply_ip_hdr->dest_ip, ip_hdr->src_ip, 4);
memcpy(reply_ip_hdr->src_ip, my_ip_addr, 4);
reply_ip_hdr->hdr_checksum = 0;
reply_ip_hdr->hdr_checksum = checksum(reply_ip_hdr, sizeof(xip_hdr_t));
xip_out(tx_packet, ip_hdr->src_ip, XNET_PROTOCOL_IP);
printf("[ICMP] Sending Echo Reply to %d.%d.%d.%d\n",
saved_ip_hdr.src_ip[0], saved_ip_hdr.src_ip[1],
saved_ip_hdr.src_ip[2], saved_ip_hdr.src_ip[3]);
xip_out(tx_packet, saved_ip_hdr.src_ip, 1);
printf("[ICMP] Echo Reply sent\n");
} else {
printf("[ICMP] Failed to allocate tx_packet\n");
}
} else if (icmp_packet->type == ICMP_TYPE_ECHO_REPLY) {
// 收到ICMP Echo Reply正常接收不做额外处理
// 这是对本机发出的ping请求的回复
}
}

View File

@@ -3,7 +3,7 @@
#include "xnet_tiny.h"
void xip_out(xnet_packet_t *packet, const uint8_t *dest_ip, uint8_t protocol) {
const uint8_t *mac_addr = xarp_resolve(dest_ip);
const uint8_t *mac_addr = xarp_resolve(packet, dest_ip);
if (mac_addr) {
ethernet_out_to(XNET_PROTOCOL_IP, mac_addr, packet);
}

View File

@@ -0,0 +1,33 @@
#ifndef XLOG_H
#define XLOG_H
#include <stdio.h>
#define XLOG_LEVEL_NONE 0
#define XLOG_LEVEL_ERROR 1
#define XLOG_LEVEL_WARNING 2
#define XLOG_LEVEL_INFO 3
#ifndef XLOG_LEVEL
#define XLOG_LEVEL XLOG_LEVEL_INFO
#endif
#if XLOG_LEVEL >= XLOG_LEVEL_INFO
#define xlog_info(fmt, ...) printf("[INFO] (%s:%d) " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#else
#define xlog_info(fmt, ...)
#endif
#if XLOG_LEVEL >= XLOG_LEVEL_WARNING
#define xlog_warn(fmt, ...) printf("[WARN] (%s:%d) " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#else
#define xlog_warn(fmt, ...)
#endif
#if XLOG_LEVEL >= XLOG_LEVEL_ERROR
#define xlog_err(fmt, ...) printf("[ERROR] (%s:%d) " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#else
#define xlog_err(fmt, ...)
#endif
#endif // XLOG_H

View File

@@ -1,9 +1,10 @@
#include <string.h>
#include <stdio.h>
#include "xnet_tiny.h"
#include "xarp.h"
#include "xicmp.h"
const uint8_t my_ip_addr[] = {192, 168, 254, 2};
const uint8_t my_ip_addr[] = {10, 20, 6, 8};
#define min(a, b) ((a) > (b) ? (b) : (a))
@@ -40,6 +41,10 @@ xnet_packet_t * xnet_alloc_for_read(uint16_t data_size) {
return &rx_packet;
}
void xnet_free_packet(xnet_packet_t * packet) {
// 单缓冲区,无需释放
}
/**
* 为发包添加一个头部
* @param packet 待处理的数据包
@@ -108,19 +113,28 @@ xnet_err_t ethernet_out_to(xnet_protocol_t protocol, const uint8_t *mac_addr, xn
static void ethernet_in (xnet_packet_t * packet) {
// 至少要比头部数据大
if (packet->size <= sizeof(xether_hdr_t)) {
printf("[ETH] Packet too small: %d bytes\n", packet->size);
return;
}
// 往上分解到各个协议处理
xether_hdr_t* hdr = (xether_hdr_t*)packet->data;
switch (swap_order16(hdr->protocol)) {
uint16_t protocol = swap_order16(hdr->protocol);
printf("[ETH] Received packet, protocol: 0x%04x, size: %d\n", protocol, packet->size);
switch (protocol) {
case XNET_PROTOCOL_ARP:
printf("[ETH] Processing ARP packet\n");
xarp_in(packet);
break;
case XNET_PROTOCOL_IP: {
printf("[ETH] Processing IP packet\n");
xicmp_in(packet);
break;
}
default:
printf("[ETH] Unknown protocol: 0x%04x\n", protocol);
break;
}
}
@@ -129,8 +143,12 @@ static void ethernet_in (xnet_packet_t * packet) {
*/
static void ethernet_poll (void) {
xnet_packet_t * packet;
static int packet_count = 0;
if (xnet_driver_read(&packet) == XNET_ERR_OK) {
packet_count++;
printf("\n[POLL] Packet #%d received, size: %d bytes\n", packet_count, packet->size);
fflush(stdout);
// 正常情况下,在此打个断点,全速运行
// 然后在对方端ping 192.168.254.2,会停在这里
ethernet_in(packet);

View File

@@ -41,6 +41,7 @@ typedef enum _xnet_protocol_t {
xnet_packet_t * xnet_alloc_for_send(uint16_t data_size);
xnet_packet_t * xnet_alloc_for_read(uint16_t data_size);
void xnet_free_packet(xnet_packet_t * packet);
xnet_err_t xnet_driver_open (uint8_t * mac_addr);
xnet_err_t xnet_driver_send (xnet_packet_t * packet);