studying_pxy 2024-09-02 21:03 采纳率: 33.3%
浏览 7
已结题

内核构造ns报文出现问题

pc抓包结果

img


相关代码:

// 计算 ICMPv6 报文的校验和

uint16_t calculate_icmp6_checksum(const sys_ipv6_t *src_ip, const sys_ipv6_t *dst_ip,

                              const icmpv6_neighbor_solicitation_t *ns, size_t ns_len)

{

uint32_t sum = 0;

const uint8_t *data = (const uint8_t *)&ns->icmpv6_header;

const uint8_t *end = data + ns_len;

int i = 0;



// 计算 ICMPv6 头部和选项的校验和

while (data + 1 < end)

{

    // 避免直接转换为 uint16_t*,而是手动读取两个字节

    sum += ((uint16_t)data[0] << 8) | data[1];

    data += 2;

}



if (data < end)

{

    sum += (uint16_t)(*data << 8);

}



// 添加伪首部字段

// 计算源 IP 地址的伪首部

for (i = 0; i < 4; i++)

{

    uint32 tmp = ((uint32)src_ip->hex[i * 4] << 24) |

                ((uint32)src_ip->hex[i * 4 + 1] << 16) |

                ((uint32)src_ip->hex[i * 4 + 2] << 8) |

                ((uint32)src_ip->hex[i * 4 + 3]);

    sum += htons(tmp);

}



// 计算目的 IP 地址的伪首部

for (i = 0; i < 4; i++)

{

    uint32 tmp = ((uint32)dst_ip->hex[i * 4] << 24) |

                ((uint32)dst_ip->hex[i * 4 + 1] << 16) |

                ((uint32)dst_ip->hex[i * 4 + 2] << 8) |

                ((uint32)dst_ip->hex[i * 4 + 3]);

    sum += htons(tmp);

}



// 添加长度和协议号

sum += htons(ns_len) + IPPROTO_ICMPV6;



// 折叠 32 位的和到 16 位

while (sum >> 16)

{

    sum = (sum & 0xFFFF) + (sum >> 16);

}



// 取反

return ~sum;

}

static int32 send_ns_for_nd_snooping(int32 idx)

{

sys_ipv6_t target_address;

sys_ipv6_t source_address;

sys_mac_t target_mac_address;

int32 i;

sys_err_code_t ret = SYS_ERR_OK;

sys_logic_portmask_t blkpm;

ndsp_ipv6hdr_t ip_hdr;

icmpv6_neighbor_solicitation_t ns;

target_addr_option option;

uint16_t checksum;

//sys_logic_portmask_t port_mask;

sys_nic_pkt_t *pPkt;

uint32 packetLen = sizeof(icmpv6_neighbor_solicitation_t) + sizeof(ndsp_ipv6hdr_t) + sizeof(ethernet_header_t);

sys_ipv6_t dst_address;

uint8_t prefix[16] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,  

                        0x00, 0x00, 0x00}; 

ethernet_header_t *eth_hdr;





uint32 unit = SYS_DEV_ID_DEFAULT;



if (RT_ERR_OK != drv_nic_pkt_alloc(unit, packetLen, 0, &pPkt))

{

    osal_printf("[%s]: Alloc packet failed.\n", __FUNCTION__);

    return RT_ERR_FAILED;

}



// Initialize packet pointers

osal_memset(&target_address, 0, sizeof(sys_ipv6_t));

osal_memset(&source_address, 0, sizeof(sys_ipv6_t));

osal_memset(&target_mac_address, 0, sizeof(sys_mac_t));



ND_SNOOPING_LOCK();

// 构造以太网头  

eth_hdr = (ethernet_header_t *) pPkt->data;  

osal_memcpy(&target_mac_address, &nd_snooping_table[idx].mac, sizeof(sys_mac_t));



osal_memcpy(&target_address, &nd_snooping_table[idx].ipv6, sizeof(sys_ipv6_t));

// 将前缀复制到目标地址  

osal_memcpy(&dst_address.hex, prefix, 13); //13字节为前缀  

// 提取source_address的后24位并填充到target_address的后24位  

osal_memcpy(&dst_address.hex[13], &target_address.hex[13], 3); // 复制后3字节 



// 设置MAC地址的前2个字节  

target_mac_address.octet[0] = 0x33;  

target_mac_address.octet[1] = 0x33;  



// 设置MAC地址的后3个字节(IPv6地址的后32位,注意是ff对应的字节)  

target_mac_address.octet[2] = dst_address.hex[12]; // IPv6地址的第13字节 

target_mac_address.octet[3] = dst_address.hex[13]; // IPv6地址的第14字节  

target_mac_address.octet[4] = dst_address.hex[14]; // IPv6地址的第15字节  

target_mac_address.octet[5] = dst_address.hex[15]; // IPv6地址的第16字节

osal_memcpy(eth_hdr->dest_mac, &target_mac_address, sizeof(sys_mac_t)); // 设置目的MAC  

osal_memcpy(eth_hdr->src_mac, &g_ndsp_sysMac, sizeof(sys_mac_t)); // 设置源MAC  

eth_hdr->ethertype = htons(ETHERTYPE_IPV6); // 设置以太网类型为IPv6

BOOTMSG_PRINTF("pxy-test--Constructed MAC Address: %02x:%02x:%02x:%02x:%02x:%02x--%s-----%d\n",target_mac_address.octet[0], target_mac_address.octet[1], target_mac_address.octet[2],   

       target_mac_address.octet[3], target_mac_address.octet[4], target_mac_address.octet[5],__FUNCTION__, __LINE__);

BOOTMSG_PRINTF("pxy-test--Constructed MAC Address: %02x:%02x:%02x:%02x:%02x:%02x--%s-----%d\n",g_ndsp_sysMac.octet[0], g_ndsp_sysMac.octet[1], g_ndsp_sysMac.octet[2],   

       g_ndsp_sysMac.octet[3], g_ndsp_sysMac.octet[4], g_ndsp_sysMac.octet[5],__FUNCTION__, __LINE__);    



 

// for (i = 0; i < CAPA_L3_IPV6ADDR_NUM_MAX; i++)

// {

//     if((gl3intfipv6[i].id.type == SYS_L3_INTFTYPE_PORT) && (gl3intfipv6[i].id.id == nd_snooping_table[idx].port))

//     {

//         //本地链路地址为源地址

//         osal_memcpy(&source_address, &gl3intfipv6[i].ip[0].v6.addr, sizeof(sys_ipv6_t));

//         break;

//     }

// }

// 设置版本号 (4 bits), 流量类别 (8 bits), 流标签 (20 bits)

ip_hdr.version_trafficClass_flowLabel = htonl((6 << 28) | (0x00 << 20) | 0x0000); // 版本号 6, 流量类别 0, 流标签 0

// 设置有效载荷长度

ip_hdr.payload_length = htons(sizeof(icmpv6_neighbor_solicitation_t)); // NS 报文的大小

// 设置下一个头部 (Next Header)

ip_hdr.next_header = IPPROTO_ICMPV6; // ICMPv6 协议

// 设置跳数限制

ip_hdr.hop_limit = 255; // 最大跳数

// 设置源地址

osal_memcpy(ip_hdr.src_addr, &source_address, 16);

// 设置目标地址

osal_memcpy(ip_hdr.dst_addr, &dst_address, 16);

NDSPDBG("send_ns_for_nd_snooping--IPv6 source addr: " IPADDRV6_PRINT IPADDRV6_PRINT IPADDRV6_PRINT,IPADDRV6_PRINT_ARG(source_address.hex),IPADDRV6_PRINT_ARG(dst_address.hex),IPADDRV6_PRINT_ARG(target_address.hex));



// 构造 Neighbor Solicitation 报文

// 设置 ICMPv6 头部类型为 Neighbor Solicitation (135)

ns.icmpv6_header.type = 135;

// 设置代码为 0

ns.icmpv6_header.code = 0;

// 设置校验和初始值为 0,稍后会计算并更新

ns.icmpv6_header.checksum = 0;

// 复制目标 IPv6 地址到 NS 报文的目标地址字段

osal_memcpy(ns.target_address, &target_address, 16);

// 初始化选项字段

// 设置选项类型为 2 (Target Address Option)

option.option_type = 2;

// 设置选项数据长度为 1 (不包括类型和长度字段)

option.length = 1;

// 复制目标 MAC 地址到选项中的目标地址字段

osal_memcpy(option.target_addr, &nd_snooping_table[idx].mac, 6);

// 将选项字段添加到 NS 报文中

osal_memcpy(ns.options, &option, sizeof(option));

// 计算校验和

checksum = calculate_icmp6_checksum(&source_address, &dst_address, &ns, sizeof(icmpv6_neighbor_solicitation_t));

// 更新 ICMPv6 头部的校验和

ns.icmpv6_header.checksum = checksum;



pPkt->length = packetLen;

pPkt->tail = pPkt->data + packetLen;

pPkt->txIncludeCRC = TRUE;

// 设置数据

osal_memcpy(pPkt->data + sizeof(ethernet_header_t) + sizeof(ndsp_ipv6hdr_t), &ns, sizeof(icmpv6_neighbor_solicitation_t));



LOGIC_PORTMASK_CLEAR_ALL(blkpm);

LOGIC_PORTMASK_SET_PORT(blkpm, nd_snooping_table[idx].port);

for (i = 0; i < SYS_BITS_TO_LONGS(SYS_LOGICPORT_NUM_MAX); i++)

{

    blkpm.bits[i] = ~blkpm.bits[i];

}



BOOTMSG_PRINTF("pxy-test--Block Ports = "FMT_PORTMASK"--%s-----%d\n",SHOW_PORTMASK(blkpm),__FUNCTION__, __LINE__);

ret = rsd_nic_pktByDmacBlkPM_tx(pPkt, SYS_CPU_PORT_PRIORITY_NDSNOOPING, nd_snooping_table[idx].vid, blkpm);

g_ndsp_portMib[nd_snooping_table[idx].port].ndNsSent++;

NDSPDBG("Sent NS pkt from %s, vlan %u enable", LPSTR(nd_snooping_table[idx].port), nd_snooping_table[idx].vid);

ND_SNOOPING_UNLOCK();

return ret;

}

  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 9月10日
    • 创建了问题 9月2日

    悬赏问题

    • ¥15 在hololens1上运行unity项目只有空窗口
    • ¥25 TABLEAU PREP无法打开
    • ¥15 关于#c语言#的问题:求完整代码条件好说
    • ¥15 (需要远程,AI不回)VB6二进制文件转换成功,但是C#转换总是失败
    • ¥15 关于#matlab#的问题:有没有什么其他办法能够保证不退出进程(相关搜索:matlab调用)
    • ¥15 依据报错在原代吗格式的基础上解决问题
    • ¥15 在虚拟机中安装flash code
    • ¥15 单片机stm32f10x编写光敏电阻调节3.3伏大功率灯亮度(光强越大灯越暗,白天正常光强灯不亮,使用ADC,PWM等模块)望各位找一下错误或者提供一个可实现功能的代码
    • ¥20 verilog状态机方法流水灯
    • ¥15 pandas代码实现不了意图