コード例 #1
0
ファイル: packet.c プロジェクト: NICMx/Jool
static verdict handle_icmp6(struct xlation *state, struct pkt_metadata const *meta)
{
	union {
		struct icmp6hdr icmp;
		struct frag_hdr frag;
	} buffer;
	union {
		struct icmp6hdr *icmp;
		struct frag_hdr *frag;
	} ptr;
	verdict result;

	ptr.icmp = skb_hdr_ptr(state->in.skb, meta->l4_offset, buffer.icmp);
	if (!ptr.icmp)
		return truncated(state, "ICMPv6 header");

	if (has_inner_pkt6(ptr.icmp->icmp6_type)) {
		result = validate_inner6(state, meta);
		if (result != VERDICT_CONTINUE)
			return result;
	}

	if (xlat_is_siit() && meta->has_frag_hdr && is_icmp6_info(ptr.icmp->icmp6_type)) {
		ptr.frag = skb_hdr_ptr(state->in.skb, meta->frag_offset, buffer.frag);
		if (!ptr.frag)
			return truncated(state, "fragment header");
		if (is_fragmented_ipv6(ptr.frag)) {
			log_debug("Packet is a fragmented ping; its checksum cannot be translated.");
			return drop(state, JSTAT_FRAGMENTED_PING);
		}
	}

	return VERDICT_CONTINUE;
}
コード例 #2
0
bool determine_in_tuple(struct sk_buff *skb, struct tuple *tuple)
{
	struct iphdr *hdr4;
	struct ipv6hdr *hdr6;
	struct icmphdr *icmp4;
	struct icmp6hdr *icmp6;
	struct hdr_iterator iterator;

	log_debug("Step 1: Determining the Incoming Tuple");

	switch (be16_to_cpu(skb->protocol)) {
	case ETH_P_IP:
		hdr4 = ip_hdr(skb);
		switch (hdr4->protocol) {
		case IPPROTO_UDP:
			if (!ipv4_udp(hdr4, ipv4_extract_l4_hdr(hdr4), tuple))
				return false;
			break;
		case IPPROTO_TCP:
			if (!ipv4_tcp(hdr4, ipv4_extract_l4_hdr(hdr4), tuple))
				return false;
			break;
		case IPPROTO_ICMP:
			icmp4 = ipv4_extract_l4_hdr(hdr4);
			if (is_icmp4_info(icmp4->type)) {
				if (!ipv4_icmp_info(hdr4, icmp4, tuple))
					return false;
			} else {
				if (!ipv4_icmp_err(hdr4, icmp4, tuple))
					return false;
			}
			break;
		default:
			log_info("Unsupported transport protocol for IPv4: %d.", hdr4->protocol);
			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
			return false;
		}
		break;

	case ETH_P_IPV6:
		hdr6 = ipv6_hdr(skb);
		hdr_iterator_init(&iterator, hdr6);
		hdr_iterator_last(&iterator);
		switch (iterator.hdr_type) {
		case IPPROTO_UDP:
			if (!ipv6_udp(hdr6, iterator.data, tuple))
				return false;
			break;
		case IPPROTO_TCP:
			if (!ipv6_tcp(hdr6, iterator.data, tuple))
				return false;
			break;
		case IPPROTO_ICMPV6:
			icmp6 = iterator.data;
			if (is_icmp6_info(icmp6->icmp6_type)) {
				if (!ipv6_icmp_info(hdr6, icmp6, tuple))
					return false;
			} else {
				if (!ipv6_icmp_err(hdr6, icmp6, tuple))
					return false;
			}
			break;
		default:
			log_info("Unsupported transport protocol for IPv6: %d.", iterator.hdr_type);
			icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
			return false;
		}
		break;

	default:
		log_info("Packet's protocol (%d) is not IPv4 or IPv6.", be16_to_cpu(skb->protocol));
		return false;
	}

	log_tuple(tuple);
	log_debug("Done step 1.");
	return true;
}
コード例 #3
0
ファイル: determine_incoming_tuple.c プロジェクト: magg/NAT64
/**
 * Extracts relevant data from "skb" and stores it in the "tuple" tuple.
 *
 * @param skb packet the data will be extracted from.
 * @param tuple this function will populate this value using "skb"'s contents.
 * @return whether packet processing should continue.
 */
verdict determine_in_tuple(struct sk_buff *skb, struct tuple *in_tuple)
{
	struct icmphdr *icmp4;
	struct icmp6hdr *icmp6;
	verdict result = VER_CONTINUE;

	log_debug("Step 1: Determining the Incoming Tuple");

	switch (skb_l3_proto(skb)) {
	case L3PROTO_IPV4:
		switch (skb_l4_proto(skb)) {
		case L4PROTO_UDP:
			result = ipv4_udp(skb, in_tuple);
			break;
		case L4PROTO_TCP:
			result = ipv4_tcp(skb, in_tuple);
			break;
		case L4PROTO_ICMP:
			icmp4 = icmp_hdr(skb);
			if (is_icmp4_info(icmp4->type)) {
				result = ipv4_icmp_info(skb, in_tuple);
			} else if (is_icmp4_error(icmp4->type)) {
				result = ipv4_icmp_err(skb, in_tuple);
			} else {
				log_debug("Unknown ICMPv4 type: %u. Dropping packet...", icmp4->type);
				inc_stats(skb, IPSTATS_MIB_INHDRERRORS);
				result = VER_DROP;
			}
			break;
		}
		break;

	case L3PROTO_IPV6:
		switch (skb_l4_proto(skb)) {
		case L4PROTO_UDP:
			result = ipv6_udp(skb, in_tuple);
			break;
		case L4PROTO_TCP:
			result = ipv6_tcp(skb, in_tuple);
			break;
		case L4PROTO_ICMP:
			icmp6 = icmp6_hdr(skb);
			if (is_icmp6_info(icmp6->icmp6_type)) {
				result = ipv6_icmp_info(skb, in_tuple);
			} else if (is_icmp6_error(icmp6->icmp6_type)) {
				result = ipv6_icmp_err(skb, in_tuple);
			} else {
				log_debug("Unknown ICMPv6 type: %u. Dropping packet...", icmp6->icmp6_type);
				inc_stats(skb, IPSTATS_MIB_INHDRERRORS);
				result = VER_DROP;
			}
			break;
		}
		break;
	}

	/*
	 * We moved the transport-protocol-not-recognized ICMP errors to packet.c because they're
	 * covered in validations.
	 */

	log_tuple(in_tuple);
	log_debug("Done step 1.");
	return result;
}
コード例 #4
0
/**
 * Extracts relevant data from "frag" and stores it in the "tuple" tuple.
 *
 * @param frag fragment the data will be extracted from. Whether the packet is fragmented or not,
 *		this has to be the chunk whose fragment offset is zero.
 * @param tuple this function will populate this value using "frag"'s contents.
 * @return whether packet processing should continue.
 */
verdict determine_in_tuple(struct fragment *frag, struct tuple *tuple)
{
	struct iphdr *hdr4;
	struct ipv6hdr *hdr6;
	struct icmphdr *icmp4;
	struct icmp6hdr *icmp6;
	verdict result = VER_CONTINUE;

	log_debug("Step 1: Determining the Incoming Tuple");

	switch (frag->l3_hdr.proto) {
	case L3PROTO_IPV4:
		hdr4 = frag_get_ipv4_hdr(frag);
		switch (frag->l4_hdr.proto) {
		case L4PROTO_UDP:
			result = ipv4_udp(hdr4, frag_get_udp_hdr(frag), tuple);
			break;
		case L4PROTO_TCP:
			result = ipv4_tcp(hdr4, frag_get_tcp_hdr(frag), tuple);
			break;
		case L4PROTO_ICMP:
			icmp4 = frag_get_icmp4_hdr(frag);
			if (is_icmp4_info(icmp4->type)) {
				result = ipv4_icmp_info(hdr4, icmp4, tuple);
			} else if (is_icmp4_error(icmp4->type)) {
				result = ipv4_icmp_err(hdr4, icmp4, tuple);
			} else {
				log_warning("Unknown ICMPv4 type: %u. Dropping packet...", icmp4->type);
				result = VER_DROP;
			}
			break;
		case L4PROTO_NONE:
			log_crit(ERR_ILLEGAL_NONE, "IPv4 - First fragment has no transport header.");
			result = VER_DROP;
		}
		break;

	case L3PROTO_IPV6:
		hdr6 = frag_get_ipv6_hdr(frag);
		switch (frag->l4_hdr.proto) {
		case L4PROTO_UDP:
			result = ipv6_udp(hdr6, frag_get_udp_hdr(frag), tuple);
			break;
		case L4PROTO_TCP:
			result = ipv6_tcp(hdr6, frag_get_tcp_hdr(frag), tuple);
			break;
		case L4PROTO_ICMP:
			icmp6 = frag_get_icmp6_hdr(frag);
			if (is_icmp6_info(icmp6->icmp6_type)) {
				result = ipv6_icmp_info(hdr6, icmp6, tuple);
			} else if (is_icmp6_error(icmp6->icmp6_type)) {
				result = ipv6_icmp_err(hdr6, icmp6, tuple);
			} else {
				log_warning("Unknown ICMPv6 type: %u. Dropping packet...", icmp6->icmp6_type);
				result = VER_DROP;
			}
			break;
		case L4PROTO_NONE:
			log_crit(ERR_ILLEGAL_NONE, "IPv6 - First fragment has no transport header.");
			result = VER_DROP;
		}
		break;
	}

	/*
	 * We moved the transport-protocol-not-recognized ICMP errors to fragment_db because they're
	 * covered in validations.
	 */

	log_tuple(tuple);
	log_debug("Done step 1.");
	return result;
}