Exemple #1
0
static int whine_if_too_big(struct packet *in, struct packet *out)
{
	unsigned int len;
	unsigned int mtu;

	if (pkt_l3_proto(in) == L3PROTO_IPV4 && !is_dont_fragment_set(pkt_ip4_hdr(in)))
		return 0;

	len = pkt_len(out);
	mtu = get_nexthop_mtu(out);
	if (len > mtu) {
		/*
		 * We don't have to worry about ICMP errors causing this because the translate code already
		 * truncates them.
		 */
		log_debug("Packet is too big (len: %u, mtu: %u).", len, mtu);

		switch (pkt_l3_proto(out)) {
		case L3PROTO_IPV6:
			mtu -= 20;
			break;
		case L3PROTO_IPV4:
			mtu += 20;
			break;
		}
		icmp64_send(out, ICMPERR_FRAG_NEEDED, mtu);

		return -EINVAL;
	}

	return 0;
}
/**
 * Main F&U routine. Called during the processing of every packet.
 *
 * Decides if "skb" should be processed, updating binding and session information.
 *
 * @param[in] skb packet being translated.
 * @param[in] tuple skb's summary.
 * @return indicator of what should happen to skb.
 */
verdict filtering_and_updating(struct packet *pkt, struct tuple *in_tuple)
{
	struct ipv6hdr *hdr_ip6;
	verdict result = VERDICT_CONTINUE;

	log_debug("Step 2: Filtering and Updating");

	switch (pkt_l3_proto(pkt)) {
	case L3PROTO_IPV6:
		/* ICMP errors should not be filtered or affect the tables. */
		if (pkt_is_icmp6_error(pkt)) {
			log_debug("Packet is ICMPv6 error; skipping step...");
			return VERDICT_CONTINUE;
		}
		/* Get rid of hairpinning loops and unwanted packets. */
		hdr_ip6 = pkt_ip6_hdr(pkt);
		if (pool6_contains(&hdr_ip6->saddr)) {
			log_debug("Hairpinning loop. Dropping...");
			inc_stats(pkt, IPSTATS_MIB_INADDRERRORS);
			return VERDICT_DROP;
		}
		if (!pool6_contains(&hdr_ip6->daddr)) {
			log_debug("Packet was rejected by pool6; dropping...");
			inc_stats(pkt, IPSTATS_MIB_INADDRERRORS);
			return VERDICT_DROP;
		}
		break;
	case L3PROTO_IPV4:
		/* ICMP errors should not be filtered or affect the tables. */
		if (pkt_is_icmp4_error(pkt)) {
			log_debug("Packet is ICMPv4 error; skipping step...");
			return VERDICT_CONTINUE;
		}
		/* Get rid of unexpected packets */
		if (!pool4_contains(pkt_ip4_hdr(pkt)->daddr)) {
			log_debug("Packet was rejected by pool4; dropping...");
			inc_stats(pkt, IPSTATS_MIB_INADDRERRORS);
			return VERDICT_DROP;
		}
		break;
	}

	/* Process packet, according to its protocol. */

	switch (pkt_l4_proto(pkt)) {
	case L4PROTO_UDP:
		switch (pkt_l3_proto(pkt)) {
		case L3PROTO_IPV6:
			result = ipv6_simple(pkt, in_tuple);
			break;
		case L3PROTO_IPV4:
			result = ipv4_simple(pkt, in_tuple);
			break;
		}
		break;

	case L4PROTO_TCP:
		result = tcp(pkt, in_tuple);
		break;

	case L4PROTO_ICMP:
		switch (pkt_l3_proto(pkt)) {
		case L3PROTO_IPV6:
			if (config_get_filter_icmpv6_info()) {
				log_debug("Packet is ICMPv6 info (ping); dropping due to policy.");
				inc_stats(pkt, IPSTATS_MIB_INDISCARDS);
				return VERDICT_DROP;
			}

			result = ipv6_simple(pkt, in_tuple);
			break;
		case L3PROTO_IPV4:
			result = ipv4_simple(pkt, in_tuple);
			break;
		}
		break;

	case L4PROTO_OTHER:
		WARN(true, "Unknown layer 4 protocol (%d)...", pkt_l4_proto(pkt));
		break;
	}

	log_debug("Done: Step 2.");
	return result;
}
/**
 * Checks whether "pkt" is a hairpin packet.
 *
 * @param pkt outgoing packet the NAT64 would send if it's not a hairpin.
 * @return whether pkt is a hairpin packet.
 */
bool is_hairpin(struct packet *pkt)
{
	return (pkt_l3_proto(pkt) == L3PROTO_IPV4) ? pool4_contains(pkt_ip4_hdr(pkt)->daddr) : false;
}