本文主要是介绍ICMPV6遇到的坑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
关于icmpv6的介绍在其他文章中,这里就不再赘述。RFC4443中文
RFC4861中文
1、发送ICMPV6 NEIGHBOR SOLICIATION数据包
struct test_rte_flow_item_icmp6_nd_ns {uint8_t type; /**< ICMPv6 type, normally 135. */uint8_t code; /**< ICMPv6 code, normally 0. */rte_be16_t checksum; /**< ICMPv6 checksum. */rte_be32_t reserved; /**< Reserved, normally 0. */uint8_t target_addr[16]; /**< Target address. */uint8_t op_type; /**< ND option type, normally 1. */uint8_t length; /**< ND option length, normally 1. */struct rte_ether_addr sla; /**< Source Ethernet LLA. */
};
void create_neighbor_solicition(struct rte_mbuf *pkt, uint8_t *dst_ipv6_addr)
{struct rte_ether_hdr *eth_hdr;struct rte_ipv6_hdr *ipv6_hdr;struct test_rte_flow_item_icmp6_nd_ns *icmp_hdr;eth_hdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);_generate_requested_multicast_mac(dst_ipv6_addr, eth_hdr);rte_memcpy(ð_hdr->s_addr, &responser.src_mac_addr, sizeof(struct rte_ether_addr)); eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);ipv6_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv6_hdr *, sizeof(struct rte_ether_hdr));_generate_requested_multicast_ipv6(dst_ipv6_addr, ipv6_hdr);rte_memcpy(&ipv6_hdr->src_addr, &responser.src_ipv6_addr, IPV6_ADDR_LEN);ipv6_hdr->vtc_flow = htonl(0x60000000);ipv6_hdr->payload_len = htons(sizeof(struct test_rte_flow_item_icmp6_nd_ns)); ipv6_hdr->proto = IPPROTO_ICMPV6; ipv6_hdr->hop_limits = 0xff; icmp_hdr = (struct test_rte_flow_item_icmp6_nd_ns *)(ipv6_hdr + 1);icmp_hdr->type = ICMPV6_NEIGHBOR_SOLICIATION;icmp_hdr->code = 0;icmp_hdr->checksum = 0;icmp_hdr->reserved = 0;rte_memcpy(&icmp_hdr->target_addr, dst_ipv6_addr, sizeof(icmp_hdr->target_addr));icmp_hdr->op_type = ICMPV6_ND_OPT_SOURCE_LINKADDR;icmp_hdr->length = 1; //1 == 8 bytesrte_memcpy(&icmp_hdr->sla, &responser.src_mac_addr, sizeof(struct rte_ether_addr));icmp_hdr->checksum =htons(calculate_icmpv6_checksum(icmp_hdr, ipv6_hdr->src_addr, ipv6_hdr->dst_addr, sizeof(struct test_rte_flow_item_icmp6_nd_ns)));pkt->pkt_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr) + sizeof(struct test_rte_flow_item_icmp6_nd_ns);pkt->data_len = pkt->pkt_len;
}
这里需要注意,ICMPV6 NEIGHBOR SOLICIATION
类似于IPV4中的ARP REQUEST,这时候并不知道对端mac,所以需要封装组播mac,不同于V4,这里的目的ip也需要封装为组播ip(按理说不需要封装也行,但是我的环境中不封装无法收到NA报文)
1.1 封装 NEIGHBOR SOLICIATION 组播mac
static void _generate_requested_multicast_mac(const uint8_t *dst_ipv6_addr, struct rte_ether_hdr *eth_hdr)
{if (!dst_ipv6_addr || !eth_hdr) {RESPONSE_ERROR("_generate_requested_multicast_mac fail. \n");return;}const uint8_t fixed_mac_prefix[] = {0x33, 0x33, 0xff};uint32_t last_32_bits = (dst_ipv6_addr[12] << 24) | (dst_ipv6_addr[13] << 16) | (dst_ipv6_addr[14] << 8) | dst_ipv6_addr[15];uint8_t last_24_bits[3];last_24_bits[0] = (last_32_bits >> 16) & 0xFF;last_24_bits[1] = (last_32_bits >> 8) & 0xFF;last_24_bits[2] = last_32_bits & 0xFF;rte_memcpy(eth_hdr->d_addr.addr_bytes, fixed_mac_prefix, 3);rte_memcpy(eth_hdr->d_addr.addr_bytes + 3, last_24_bits, 3);
}
1.2 封装 NEIGHBOR SOLICIATION 组播ip
static void _generate_requested_multicast_ipv6(const uint8_t *dst_ipv6_addr, struct rte_ipv6_hdr *ipv6_hdr)
{if (!dst_ipv6_addr | !ipv6_hdr) {RESPONSE_ERROR("_generate_requested_multicast_ipv6 fail. \n");return;}ipv6_hdr->dst_addr[0] = 0xFF;ipv6_hdr->dst_addr[1] = 0x02;ipv6_hdr->dst_addr[2] = 0x00;ipv6_hdr->dst_addr[3] = 0x00;ipv6_hdr->dst_addr[4] = 0x00;ipv6_hdr->dst_addr[5] = 0x00;ipv6_hdr->dst_addr[6] = 0x00;ipv6_hdr->dst_addr[7] = 0x00;ipv6_hdr->dst_addr[8] = 0x00;ipv6_hdr->dst_addr[9] = 0x00;ipv6_hdr->dst_addr[10] = 0x00;ipv6_hdr->dst_addr[11] = 0x01;ipv6_hdr->dst_addr[12] = 0xFF;ipv6_hdr->dst_addr[13] = dst_ipv6_addr[13]; ipv6_hdr->dst_addr[14] = dst_ipv6_addr[14]; ipv6_hdr->dst_addr[15] = dst_ipv6_addr[15]; }
2 发送ICMPV6 NEIGHBOR ADVERTISEMENT数据包
struct rte_flow_item_icmp6_nd_na {uint8_t type; /**< ICMPv6 type, normally 136. */uint8_t code; /**< ICMPv6 code, normally 0. */rte_be16_t checksum; /**< ICMPv6 checksum. *//*** Route flag (1b), solicited flag (1b), override flag (1b),* reserved (29b).*/rte_be32_t rso_reserved;uint8_t target_addr[16]; /**< Target address. */
};static void _response_icmpv6_NS(struct rte_mbuf *new_pkt, struct rte_mbuf *old_pkt)
{struct rte_ether_hdr *eth_hdr_old = rte_pktmbuf_mtod(old_pkt, struct rte_ether_hdr *);struct rte_ipv6_hdr *ipv6_hdr_old = rte_pktmbuf_mtod_offset(old_pkt, struct rte_ipv6_hdr *, sizeof(struct rte_ether_hdr));struct rte_flow_item_icmp6_nd_ns *icmpv6_ns = (struct rte_flow_item_icmp6_nd_ns *)(ipv6_hdr_old + 1);struct rte_ether_hdr *eth_hdr_new = rte_pktmbuf_mtod(new_pkt, struct rte_ether_hdr *);rte_memcpy(ð_hdr_new->d_addr, ð_hdr_old->s_addr, sizeof(struct rte_ether_addr));rte_memcpy(ð_hdr_new->s_addr, &responser.src_mac_addr, sizeof(struct rte_ether_addr)); eth_hdr_new->ether_type = htons(0x86DD);struct rte_ipv6_hdr *ipv6_hdr_new = rte_pktmbuf_mtod_offset(new_pkt, struct rte_ipv6_hdr *, sizeof(struct rte_ether_hdr));rte_memcpy(&ipv6_hdr_new->dst_addr, &responser.dst_ipv6_addr, sizeof(struct in6_addr));rte_memcpy(&ipv6_hdr_new->src_addr, &responser.src_ipv6_addr, sizeof(struct in6_addr));ipv6_hdr_new->vtc_flow = htonl(0x60000000);ipv6_hdr_new->payload_len = htons(sizeof(struct rte_flow_item_icmp6_nd_na)); ipv6_hdr_new->proto = ipv6_hdr_old->proto; ipv6_hdr_new->hop_limits = 0xff; struct rte_flow_item_icmp6_nd_na *icmp_hdr_new = (struct rte_flow_item_icmp6_nd_na *)(ipv6_hdr_new + 1);icmp_hdr_new->type = ICMPV6_NEIGHBOR_ADVERTISEMENT; icmp_hdr_new->code = 0; icmp_hdr_new->checksum = 0; icmp_hdr_new->rso_reserved = rte_cpu_to_be_32(0x60000000);rte_memcpy(&icmp_hdr_new->target_addr, &ipv6_hdr_old->src_addr, sizeof(struct in6_addr));icmp_hdr_new->checksum =htons(calculate_icmpv6_checksum((uint8_t *)icmp_hdr_new,ipv6_hdr_new->src_addr,ipv6_hdr_new->dst_addr,sizeof(struct rte_flow_item_icmp6_nd_na)));new_pkt->pkt_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr) + sizeof(struct rte_flow_item_icmp6_nd_na);new_pkt->data_len = new_pkt->pkt_len;RESPONSE_DEBUG("encapsulation ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT success \n");
}
3 发送ICMPV6_ECHO_REQUEST数据包
struct test_rte_icmp_hdr {uint8_t icmp_type; /* ICMP packet type. */uint8_t icmp_code; /* ICMP packet code. */rte_be16_t icmp_cksum; /* ICMP packet checksum. */rte_be16_t icmp_ident; /* ICMP packet identifier. */rte_be16_t icmp_seq_nb; /* ICMP packet sequence number. */uint8_t data[ICMPV6_REQUEST_DATA_LEN];
} __attribute__((__packed__));static _create_icmpv6_request(struct rte_mbuf *pkt, uint8_t *dst_ipv6_addr, uint16_t identifier)
{static uint16_t seq_num = 0;struct rte_ether_hdr *eth_hdr;struct rte_ipv6_hdr *ipv6_hdr;struct test_rte_icmp_hdr *icmp_hdr;struct ipv6_mac_entry result_entry;eth_hdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);//_generate_requested_multicast_mac(dst_ipv6_addr, eth_hdr);get_mac_by_ipv6(dst_ipv6_addr, &result_entry);rte_memcpy(ð_hdr->d_addr, &result_entry.mac_address, MAC_ADDR_LEN); rte_memcpy(ð_hdr->s_addr, &responser.src_mac_addr, MAC_ADDR_LEN); eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);ipv6_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv6_hdr *, sizeof(struct rte_ether_hdr));rte_memcpy(&ipv6_hdr->dst_addr, dst_ipv6_addr, IPV6_ADDR_LEN);rte_memcpy(&ipv6_hdr->src_addr, &responser.src_ipv6_addr, IPV6_ADDR_LEN);ipv6_hdr->vtc_flow = htonl(0x60000000);ipv6_hdr->payload_len = htons(sizeof(struct test_rte_icmp_hdr)); ipv6_hdr->proto = IPPROTO_ICMPV6; ipv6_hdr->hop_limits = 0xff;icmp_hdr = (struct test_rte_icmp_hdr *)(ipv6_hdr + 1);icmp_hdr->icmp_type = ICMPV6_ECHO_REQUEST;icmp_hdr->icmp_code = 0;icmp_hdr->icmp_cksum = 0; icmp_hdr->icmp_ident = htons(identifier); icmp_hdr->icmp_seq_nb = htons(((seq_num++) % 4) + 1); memset(&icmp_hdr->data, 1, ICMPV6_REQUEST_DATA_LEN);icmp_hdr->icmp_cksum =htons(calculate_icmpv6_checksum(icmp_hdr, ipv6_hdr->src_addr, ipv6_hdr->dst_addr, sizeof(struct test_rte_icmp_hdr)));pkt->pkt_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr) + sizeof(struct test_rte_icmp_hdr);pkt->data_len = pkt->pkt_len;
}
4 发送ICMPV6_ECHO_REPLY数据包
static void _response_icmpv6_request(struct rte_mbuf *new_pkt, struct rte_mbuf *old_pkt)
{struct rte_ether_hdr *eth_hdr_old = rte_pktmbuf_mtod(old_pkt, struct rte_ether_hdr *);struct rte_ipv6_hdr *ipv6_hdr_old = rte_pktmbuf_mtod_offset(old_pkt, struct rte_ipv6_hdr *, sizeof(struct rte_ether_hdr));struct test_rte_icmp_hdr *icmp_hdr_old = (struct test_rte_icmp_hdr *)(ipv6_hdr_old + 1); struct rte_ether_hdr *eth_hdr_new = rte_pktmbuf_mtod(new_pkt, struct rte_ether_hdr *);rte_memcpy(ð_hdr_new->d_addr, ð_hdr_old->s_addr, sizeof(struct rte_ether_addr)); rte_memcpy(ð_hdr_new->s_addr, ð_hdr_old->d_addr, sizeof(struct rte_ether_addr)); eth_hdr_new->ether_type = htons(0x86DD);struct rte_ipv6_hdr *ipv6_hdr_new = rte_pktmbuf_mtod_offset(new_pkt, struct rte_ipv6_hdr *, sizeof(struct rte_ether_hdr));rte_memcpy(&ipv6_hdr_new->dst_addr, &ipv6_hdr_old->src_addr, sizeof(struct in6_addr)); rte_memcpy(&ipv6_hdr_new->src_addr, &ipv6_hdr_old->dst_addr, sizeof(struct in6_addr)); ipv6_hdr_new->vtc_flow = htonl(0x60000000); ipv6_hdr_new->payload_len = htons(sizeof(struct test_rte_icmp_hdr)); ipv6_hdr_new->proto = ipv6_hdr_old->proto; ipv6_hdr_new->hop_limits = 0xff; struct test_rte_icmp_hdr *icmp_hdr_new = (struct test_rte_icmp_hdr *)(ipv6_hdr_new + 1); icmp_hdr_new->icmp_type = ICMPV6_ECHO_REPLY; icmp_hdr_new->icmp_code = 0; icmp_hdr_new->icmp_ident = htons(icmp_hdr_old->icmp_ident); icmp_hdr_new->icmp_seq_nb = htons(icmp_hdr_old->icmp_seq_nb); icmp_hdr_new->icmp_cksum = 0; rte_memcpy(&icmp_hdr_new->data, &icmp_hdr_old->data, ICMPV6_REQUEST_DATA_LEN); icmp_hdr_new->icmp_cksum = htons(calculate_icmpv6_checksum((uint8_t *)icmp_hdr_new, ipv6_hdr_new->src_addr,ipv6_hdr_new->dst_addr, sizeof(struct test_rte_icmp_hdr)));new_pkt->pkt_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr) + sizeof(struct test_rte_icmp_hdr);new_pkt->data_len = new_pkt->pkt_len;RESPONSE_DEBUG("encapsulation ICMPV6_ECHO_REPLY success \n");
}
这篇关于ICMPV6遇到的坑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!