/**
 * Assumes that "tuple" represents a IPv4-UDP or ICMP packet, and filters and updates based on it.
 *
 * This is RFC 6146, second halves of both sections 3.5.1 and 3.5.3.
 *
 * @param[in] skb tuple's packet. This is actually only used for error reporting.
 * @param[in] tuple summary of the packet Jool is currently translating.
 * @return VER_CONTINUE if everything went OK, VER_DROP otherwise.
 */
static verdict ipv4_simple(struct packet *pkt, struct tuple *tuple4)
{
	int error;
	struct bib_entry *bib;
	struct session_entry *session;

	error = get_bib_ipv4(pkt, tuple4, &bib);
	if (error == -ESRCH)
		return VERDICT_ACCEPT;
	else if (error)
		return VERDICT_DROP;
	log_bib(bib);

	error = sessiondb_get_or_create_ipv4(tuple4, bib, &session);
	if (error) {
		inc_stats(pkt, IPSTATS_MIB_INDISCARDS);
		bib_return(bib);
		return VERDICT_DROP;
	}
	log_session(session);

	session_return(session);
	bib_return(bib);

	return VERDICT_CONTINUE;
}
/**
 * Assumes that "tuple" represents a IPv6-UDP or ICMP packet, and filters and updates based on it.
 *
 * This is RFC 6146, first halves of both sections 3.5.1 and 3.5.3.
 *
 * @param[in] skb tuple's packet. This is actually only used for error reporting.
 * @param[in] tuple summary of the packet Jool is currently translating.
 * @return VER_CONTINUE if everything went OK, VER_DROP otherwise.
 */
static verdict ipv6_simple(struct packet *pkt, struct tuple *tuple6)
{
	struct bib_entry *bib;
	struct session_entry *session;
	int error;

	error = bibdb_get_or_create_ipv6(pkt, tuple6, &bib);
	if (error) {
		inc_stats(pkt, IPSTATS_MIB_INDISCARDS);
		return VERDICT_DROP;
	}
	log_bib(bib);

	error = sessiondb_get_or_create_ipv6(tuple6, bib, &session);
	if (error) {
		inc_stats(pkt, IPSTATS_MIB_INDISCARDS);
		bib_return(bib);
		return VERDICT_DROP;
	}
	log_session(session);

	session_return(session);
	bib_return(bib);

	return VERDICT_CONTINUE;
}
Exemple #3
0
int delete_static_route(struct request_bib *req)
{
	struct bib_entry *bib;
	int error = 0;

	if (req->remove.addr6_set) {
		error = bibdb_get_by_ipv6(&req->remove.addr6, req->l4_proto, &bib);
	} else if (req->remove.addr4_set) {
		error = bibdb_get_by_ipv4(&req->remove.addr4, req->l4_proto, &bib);
	} else {
		log_err("You need to provide an address so I can find the entry you want to remove.");
		return -EINVAL;
	}

	if (error == -ESRCH) {
		log_err("Could not find the BIB entry requested by the user.");
		return error;
	}
	if (error)
		return error;

	if (req->remove.addr6_set && req->remove.addr4_set) {
		if (!ipv4_transport_addr_equals(&bib->ipv4, &req->remove.addr4)) {
			log_err("There's no BIB entry with BOTH of the addresses you requested.");
			bib_return(bib);
			return -ESRCH;
		}
	}

	/* Remove the fake user. */
	if (bib->is_static) {
		bib_return(bib);
		bib->is_static = false;
	}

	/* Remove bib's sessions and their references. */
	error = sessiondb_delete_by_bib(bib);
	if (error) {
		bib_return(bib);
		return error;
	}

	/* Remove our own reference. If it was the last one, the entry should be no more. */
	if (bib_return(bib) == 0) {
		log_err("Looks like some packet was using the BIB entry, "
				"so it couldn't be deleted immediately. If the entry still exists, "
				"you might want to try again.");
		return -EAGAIN;
	}

	return 0;
}
/**
 * Attempts to find "tuple"'s BIB entry and returns it in "bib".
 * Assumes "tuple" represents a IPv4 packet.
 */
static int get_bib_ipv4(struct packet *pkt, struct tuple *tuple4, struct bib_entry **bib)
{
	int error;

	error = bibdb_get(tuple4, bib);
	if (error) {
		if (error == -ESRCH) {
			log_debug("There is no BIB entry for the incoming IPv4 packet.");
			inc_stats(pkt, IPSTATS_MIB_INNOROUTES);
		} else {
			log_debug("Error code %d while finding a BIB entry for the incoming packet.", error);
			inc_stats(pkt, IPSTATS_MIB_INDISCARDS);
			icmp64_send(pkt, ICMPERR_ADDR_UNREACHABLE, 0);
		}
		return error;
	}

	if (config_get_addr_dependent_filtering() && !sessiondb_allow(tuple4)) {
		log_debug("Packet was blocked by address-dependent filtering.");
		icmp64_send(pkt, ICMPERR_FILTER, 0);
		inc_stats(pkt, IPSTATS_MIB_INDISCARDS);
		bib_return(*bib);
		return -EPERM;
	}

	return 0;
}
/**
 * First half of the filtering and updating done during the CLOSED state of the TCP state machine.
 * Processes IPv6 SYN packets when there's no state.
 * Part of RFC 6146 section 3.5.2.2.
 */
static int tcp_closed_v6_syn(struct packet *pkt, struct tuple *tuple6)
{
	struct bib_entry *bib;
	struct session_entry *session;
	int error;

	error = bibdb_get_or_create_ipv6(pkt, tuple6, &bib);
	if (error)
		return error;
	log_bib(bib);

	error = create_session_ipv6(tuple6, bib, &session, SESSIONTIMER_TRANS, V6_INIT);
	if (error) {
		bib_return(bib);
		return error;
	}
	log_session(session);

	session_return(session);
	bib_return(bib);

	return 0;
}
Exemple #6
0
/**
 * Assumes that "tuple" represents a IPv4-UDP or ICMP packet, and filters and updates based on it.
 *
 * This is RFC 6146, second halves of both sections 3.5.1 and 3.5.3.
 *
 * @param[in] skb tuple's packet. This is actually only used for error reporting.
 * @param[in] tuple summary of the packet Jool is currently translating.
 * @return VER_CONTINUE if everything went OK, VER_DROP otherwise.
 */
static verdict ipv4_simple(struct sk_buff *skb, struct tuple *tuple4)
{
	int error;
	struct bib_entry *bib;
	struct session_entry *session;

	error = get_bib_ipv4(skb, tuple4, &bib);
	if (error)
		return VER_DROP;
	log_bib(bib);

	error = sessiondb_get_or_create_ipv4(tuple4, bib, &session);
	if (error) {
		inc_stats(skb, IPSTATS_MIB_INDISCARDS);
		bib_return(bib);
		return VER_DROP;
	}
	log_session(session);

	session_return(session);
	bib_return(bib);

	return VER_CONTINUE;
}
/**
 * Filtering and updating done during the CLOSED state of the TCP state machine.
 * Part of RFC 6146 section 3.5.2.2.
 */
static verdict tcp_closed_state_handle(struct packet *pkt, struct tuple *tuple)
{
	struct bib_entry *bib;
	verdict result;
	int error;

	switch (pkt_l3_proto(pkt)) {
	case L3PROTO_IPV6:
		if (pkt_tcp_hdr(pkt)->syn) {
			result = is_error(tcp_closed_v6_syn(pkt, tuple)) ? VERDICT_DROP : VERDICT_CONTINUE;
			goto syn_out;
		}
		break;

	case L3PROTO_IPV4:
		if (pkt_tcp_hdr(pkt)->syn) {
			result = tcp_closed_v4_syn(pkt, tuple);
			goto syn_out;
		}
		break;
	}

	error = bibdb_get(tuple, &bib);
	if (error) {
		log_debug("Closed state: Packet is not SYN and there is no BIB entry, so discarding. "
				"ERRcode %d", error);
		inc_stats(pkt, IPSTATS_MIB_INNOROUTES);
		return VERDICT_DROP;
	}

	bib_return(bib);
	return VERDICT_CONTINUE;

syn_out:
	if (result == VERDICT_DROP)
		inc_stats(pkt, IPSTATS_MIB_INDISCARDS);
	return result;
}
/**
 * Second half of the filtering and updating done during the CLOSED state of the TCP state machine.
 * Processes IPv4 SYN packets when there's no state.
 * Part of RFC 6146 section 3.5.2.2.
 */
static verdict tcp_closed_v4_syn(struct packet *pkt, struct tuple *tuple4)
{
	struct bib_entry *bib;
	struct session_entry *session;
	int error;
	verdict result = VERDICT_DROP;

	if (config_get_drop_external_connections()) {
		log_debug("Applying policy: Dropping externally initiated TCP connections.");
		return VERDICT_DROP;
	}

	error = bibdb_get(tuple4, &bib);
	if (error) {
		if (error != -ESRCH)
			return VERDICT_DROP;
		bib = NULL;
	}
	log_bib(bib);

	error = create_session_ipv4(tuple4, bib, &session);
	if (error)
		goto end_bib;
	log_session(session);

	session->state = V4_INIT;

	if (!bib || config_get_addr_dependent_filtering()) {
		error = pktqueue_add(session, pkt);
		if (error) {
			if (error == -E2BIG) {
				/* Fall back to assume there's no Simultaneous Open. */
				icmp64_send(pkt, ICMPERR_PORT_UNREACHABLE, 0);
			}
			goto end_session;
		}

		/* At this point, skb's original skb completely belongs to pktqueue. */
		result = VERDICT_STOLEN;

		error = sessiondb_add(session, SESSIONTIMER_SYN);
		if (error) {
			log_debug("Error code %d while adding the session to the DB.", error);
			pktqueue_remove(session);
			goto end_session;
		}

	} else {
		error = sessiondb_add(session, SESSIONTIMER_TRANS);
		if (error) {
			log_debug("Error code %d while adding the session to the DB.", error);
			goto end_session;
		}

		result = VERDICT_CONTINUE;
	}

	/* Fall through. */

end_session:
	session_return(session);
	/* Fall through. */

end_bib:
	if (bib)
		bib_return(bib);
	return result;
}