Ejemplo n.º 1
0
/**
 * 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;
}
Ejemplo n.º 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;
}
Ejemplo n.º 3
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;
}