예제 #1
0
static verdict ipv4_icmp_err(struct sk_buff *skb, struct tuple *tuple4)
{
	struct iphdr *inner_ipv4 = (struct iphdr *) (icmp_hdr(skb) + 1);
	struct udphdr *inner_udp;
	struct tcphdr *inner_tcp;
	struct icmphdr *inner_icmp;

	tuple4->src.addr4.l3.s_addr = inner_ipv4->daddr;
	tuple4->dst.addr4.l3.s_addr = inner_ipv4->saddr;

	switch (inner_ipv4->protocol) {
	case IPPROTO_UDP:
		inner_udp = ipv4_extract_l4_hdr(inner_ipv4);
		tuple4->src.addr4.l4 = be16_to_cpu(inner_udp->dest);
		tuple4->dst.addr4.l4 = be16_to_cpu(inner_udp->source);
		tuple4->l4_proto = L4PROTO_UDP;
		break;

	case IPPROTO_TCP:
		inner_tcp = ipv4_extract_l4_hdr(inner_ipv4);
		tuple4->src.addr4.l4 = be16_to_cpu(inner_tcp->dest);
		tuple4->dst.addr4.l4 = be16_to_cpu(inner_tcp->source);
		tuple4->l4_proto = L4PROTO_TCP;
		break;

	case IPPROTO_ICMP:
		inner_icmp = ipv4_extract_l4_hdr(inner_ipv4);

		if (is_icmp4_error(inner_icmp->type)) {
			log_debug("Packet is a ICMP error containing a ICMP error.");
			inc_stats(skb, IPSTATS_MIB_INHDRERRORS);
			return VER_DROP;
		}

		tuple4->src.addr4.l4 = be16_to_cpu(inner_icmp->un.echo.id);
		tuple4->dst.addr4.l4 = tuple4->src.addr4.l4;
		tuple4->l4_proto = L4PROTO_ICMP;
		break;

	default:
		log_debug("Packet's inner packet is not UDP, TCP or ICMP (%d)", inner_ipv4->protocol);
		inc_stats(skb, IPSTATS_MIB_INUNKNOWNPROTOS);
		return VER_DROP;
	}

	tuple4->l3_proto = L3PROTO_IPV4;

	return VER_CONTINUE;
}
예제 #2
0
static bool ipv4_icmp_err(struct iphdr *hdr_ipv4, struct icmphdr *hdr_icmp, struct tuple *tuple)
{
	struct iphdr *inner_ipv4 = (struct iphdr *) (hdr_icmp + 1);
	struct udphdr *inner_udp;
	struct tcphdr *inner_tcp;
	/* struct icmphdr *inner_icmp; */

	tuple->src.addr.ipv4.s_addr = inner_ipv4->daddr;
	tuple->dst.addr.ipv4.s_addr = inner_ipv4->saddr;

	switch (inner_ipv4->protocol) {
	case IPPROTO_UDP:
		inner_udp = ipv4_extract_l4_hdr(inner_ipv4);
		tuple->src.l4_id = be16_to_cpu(inner_udp->dest);
		tuple->dst.l4_id = be16_to_cpu(inner_udp->source);
		break;

	case IPPROTO_TCP:
		inner_tcp = ipv4_extract_l4_hdr(inner_ipv4);
		tuple->src.l4_id = be16_to_cpu(inner_tcp->dest);
		tuple->dst.l4_id = be16_to_cpu(inner_tcp->source);
		break;

	case IPPROTO_ICMP:
		/* We're not supporting ICMP inside ICMP yet. */
		return false;

		/*
		inner_icmp = ipv4_extract_l4_hdr(inner_ipv4);

		if (is_icmp4_error(inner_icmp->type))
			return false;

		tuple->src.l4_id = be16_to_cpu(inner_icmp->un.echo.id);
		tuple->dst.l4_id = tuple->src.l4_id;
		break;
		*/

	default:
		log_warning("Packet's inner packet is not UDP, TCP or ICMP (%d)", inner_ipv4->protocol);
		return false;
	}

	tuple->l3_proto = PF_INET;
	tuple->l4_proto = inner_ipv4->protocol;

	return true;
}
예제 #3
0
static verdict ipv4_icmp_err(struct iphdr *hdr_ipv4, struct icmphdr *hdr_icmp, struct tuple *tuple)
{
	struct iphdr *inner_ipv4 = (struct iphdr *) (hdr_icmp + 1);
	struct udphdr *inner_udp;
	struct tcphdr *inner_tcp;
	struct icmphdr *inner_icmp;

	tuple->src.addr.ipv4.s_addr = inner_ipv4->daddr;
	tuple->dst.addr.ipv4.s_addr = inner_ipv4->saddr;

	switch (inner_ipv4->protocol) {
	case IPPROTO_UDP:
		inner_udp = ipv4_extract_l4_hdr(inner_ipv4);
		tuple->src.l4_id = be16_to_cpu(inner_udp->dest);
		tuple->dst.l4_id = be16_to_cpu(inner_udp->source);
		tuple->l4_proto = L4PROTO_UDP;
		break;

	case IPPROTO_TCP:
		inner_tcp = ipv4_extract_l4_hdr(inner_ipv4);
		tuple->src.l4_id = be16_to_cpu(inner_tcp->dest);
		tuple->dst.l4_id = be16_to_cpu(inner_tcp->source);
		tuple->l4_proto = L4PROTO_TCP;
		break;

	case IPPROTO_ICMP:
		inner_icmp = ipv4_extract_l4_hdr(inner_ipv4);

		if (is_icmp4_error(inner_icmp->type)) {
			log_debug("Packet is a ICMP error containing a ICMP error.");
			return VER_DROP;
		}

		tuple->src.l4_id = be16_to_cpu(inner_icmp->un.echo.id);
		tuple->dst.l4_id = tuple->src.l4_id;
		tuple->l4_proto = L4PROTO_ICMP;
		break;

	default:
		log_warning("Packet's inner packet is not UDP, TCP or ICMP (%d)", inner_ipv4->protocol);
		return VER_DROP;
	}

	tuple->l3_proto = L3PROTO_IPV4;

	return VER_CONTINUE;
}
예제 #4
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;
}