示例#1
0
static void checksum_ipv6_packet(struct packet *packet)
{
	struct ipv6 *ipv6 = packet->ipv6;

	/* IPv6 has no header checksum. */
	/* For now we do not support IPv6 extension headers. */
	assert(packet->ip_bytes >= sizeof(*ipv6) + ntohs(ipv6->payload_len));

	/* Find the length of layer 4 header, options, and payload. */
	const int l4_bytes = ntohs(ipv6->payload_len);
	assert(l4_bytes > 0);

	/* Fill in IPv6-based layer 4 checksum. */
	if (packet->sctp != NULL) {
		struct sctp_common_header *sctp = packet->sctp;
		sctp->crc32c = 0;
		sctp->crc32c = sctp_crc32c(sctp, l4_bytes);
	} else if (packet->tcp != NULL) {
		struct tcp *tcp = packet->tcp;
		tcp->check = 0;
		tcp->check = tcp_udp_v6_checksum(&ipv6->src_ip,
						 &ipv6->dst_ip,
						 IPPROTO_TCP, tcp, l4_bytes);
	} else if (packet->udp != NULL) {
		struct udp *udp = packet->udp;
		udp->check = 0;
		udp->check = tcp_udp_v6_checksum(&ipv6->src_ip,
						 &ipv6->dst_ip,
						 IPPROTO_UDP, udp, l4_bytes);
	} else if (packet->udplite != NULL) {
		struct udplite *udplite = packet->udplite;
		u16 coverage;

		coverage = ntohs(udplite->cov);
		if ((coverage == 0) || (coverage > l4_bytes))
			coverage = l4_bytes;
		udplite->check = 0;
		udplite->check = udplite_v6_checksum(&ipv6->src_ip,
						     &ipv6->dst_ip,
						     IPPROTO_UDPLITE,
						     udplite,
						     l4_bytes, coverage);
	} else if (packet->icmpv6 != NULL) {
		/* IPv6 ICMP has a pseudo-header checksum, like TCP. */
		struct icmpv6 *icmpv6 = packet->icmpv6;
		icmpv6->checksum = 0;
		icmpv6->checksum =
			tcp_udp_v6_checksum(&ipv6->src_ip,
					    &ipv6->dst_ip,
					    IPPROTO_ICMPV6, icmpv6, l4_bytes);
	} else {
		assert(!"not TCP or UDP or UDPLite or ICMP");
	}
}
static void checksum_ipv6_packet(struct packet *packet)
{
	struct ipv6 *ipv6 = packet->ipv6;

	/* IPv6 has no header checksum. */
	/* For now we do not support IPv6 extension headers. */
	assert(packet->ip_bytes >= sizeof(*ipv6) + ntohs(ipv6->payload_len));

	/* Find the length of layer 4 header, options, and payload. */
	const int l4_bytes = ntohs(ipv6->payload_len);
	assert(l4_bytes > 0);

	/* Fill in IPv6-based layer 4 checksum. */
	if (packet->tcp != NULL) {
		struct tcp *tcp = packet->tcp;
		tcp->check = 0;
		tcp->check = tcp_udp_v6_checksum(&ipv6->src_ip,
						 &ipv6->dst_ip,
						 IPPROTO_TCP, tcp, l4_bytes);
	} else if (packet->udp != NULL) {
		struct udp *udp = packet->udp;
		udp->check = 0;
		udp->check = tcp_udp_v6_checksum(&ipv6->src_ip,
						 &ipv6->dst_ip,
						 IPPROTO_UDP, udp, l4_bytes);
	} else if (packet->icmpv6 != NULL) {
		/* IPv6 ICMP has a pseudo-header checksum, like TCP. */
		struct icmpv6 *icmpv6 = packet->icmpv6;
		icmpv6->checksum = 0;
		icmpv6->checksum =
			tcp_udp_v6_checksum(&ipv6->src_ip,
					    &ipv6->dst_ip,
					    IPPROTO_ICMPV6, icmpv6, l4_bytes);
	} else {
		assert(!"not TCP or ICMP");
	}
}