Ejemplo n.º 1
0
/**
 * Inserts a single entry, validates it, removes it, validates again.
 * Does not touch the session tables.
 */
bool simple_bib(void)
{
	struct bib_entry *bib;
	bool success = true;

	bib = create_bib_entry(0, 0);
	if (!assert_not_null(bib, "Allocation of test BIB entry"))
		return false;

	success &= assert_equals_int(0, bib_add(bib, IPPROTO_TCP), "BIB insertion call");
	success &= assert_bib("BIB insertion state", bib, false, true, false);
	if (!success)
		/*
		 * Rather have a slight memory leak than corrupted memory. Because of the error, the table
		 * might or might not have a reference to the entry, and if it does, it will try to kfree
		 * it during bib_destroy(). Hence, better not free it here.
		 */
		return false;

	success &= assert_true(bib_remove(bib, IPPROTO_TCP), "BIB removal call");
	success &= assert_bib("BIB removal state", bib, false, false, false);
	if (!success)
		return false;

	kfree(bib);
	return success;
}
Ejemplo n.º 2
0
/**
 * Inserts a single entry, validates it, removes it, validates again.
 * Does not touch the session tables.
 */
bool simple_bib(void)
{
	// Init
	struct bib_entry *bib = create_bib_entry(0, 0);
	if (!bib) {
		log_warning("Could not allocate a BIB entry.");
		return false;
	}

	// Add
	if (!bib_add(bib, IPPROTO_TCP)) {
		log_warning("Test 'BIB insertion' failed: Call returned false.");
		return false;
	}
	if (!assert_bib("BIB insertion", bib, false, true, false))
		return false;

	// Remove
	if (!bib_remove(bib, IPPROTO_TCP)) {
		log_warning("Test 'BIB removal' failed: Call returned false.");
		return false;
	}
	if (!assert_bib("BIB removal", bib, false, false, false))
		return false;

	// Quit
	return true;
}
Ejemplo n.º 3
0
bool simple_bib_session(void)
{
	struct bib_entry *bib;
	struct session_entry *session;

	bib = create_bib_entry(0, 0);
	if (!bib) {
		log_warning("Could not allocate a BIB entry.");
		return false;
	}
	session = create_session_entry(1, 0, 1, 0, bib, IPPROTO_TCP, 12345);
	if (!session) {
		log_warning("Could not allocate a Session entry.");
		return false;
	}

	// Insert the BIB entry.
	if (!bib_add(bib, IPPROTO_TCP)) {
		log_warning("Test 'BIB insertion' failed: Call returned false.");
		return false;
	}
	if (!assert_bib("BIB insertion", bib, false, true, false))
		return false;

	// Insert the session entry.
	if (!session_add(session)) {
		log_warning("Test 'Session insertion' failed: Call returned false.");
		return false;
	}
	if (!assert_session("Session insertion", session, false, true, false))
		return false;

	// The BIB entry has a session entry, so it shouldn't be removable.
	if (bib_remove(bib, IPPROTO_TCP)) {
		log_warning("Test 'Bib removal' failed: Removal shouldn't have succeeded.");
		return false;
	}
	if (!assert_bib("Bib removal (bib table)", bib, false, true, false))
		return false;
	if (!assert_session("BIB removal (session table)", session, false, true, false))
		return false;

	// Remove the session entry.
	// Because the BIB entry no longer has sessions, it should be automatically removed as well.
	if (!session_remove(session)) {
		log_warning("Test 'Session removal' failed: Call returned false.");
		return false;
	}
	if (!assert_bib("Session removal (bib table)", bib, false, false, false))
		return false;
	if (!assert_session("Session removal (session table)", session, false, false, false))
		return false;

	// Quit.
	return true;
}
Ejemplo n.º 4
0
int delete_static_route(struct request_bib *req)
{
	struct bib_entry *bib;
	struct session_entry *session;
	int error = 0;

	spin_lock_bh(&bib_session_lock);

	switch (req->remove.l3_proto) {
	case L3PROTO_IPV6:
		error = bib_get_by_ipv6(&req->remove.ipv6, req->l4_proto, &bib);
		if (error)
			goto end;
		break;
	case L3PROTO_IPV4:
		error = bib_get_by_ipv4(&req->remove.ipv4, req->l4_proto, &bib);
		if (error)
			goto end;
		break;
	default:
		log_err(ERR_L3PROTO, "Unsupported network protocol: %u.", req->remove.l3_proto);
		error = -EINVAL;
		goto end;
	}

	if (!bib) {
		log_err(ERR_BIB_NOT_FOUND, "Could not find the BIB entry requested by the user.");
		error = -ENOENT;
		goto end;
	}

	/*
	 * I'm tempted to assert that the entry is static here. Would that serve a purpose?
	 * Nah.
	 */

	while (!list_empty(&bib->sessions)) {
		session = container_of(bib->sessions.next, struct session_entry, bib_list_hook);
		error = session_remove(session);
		if (error) {
			log_err(ERR_UNKNOWN_ERROR,
					"Session [%pI6c#%u, %pI6c#%u, %pI4#%u, %pI4#%u] refused to die.",
					&session->ipv6.remote.address, session->ipv6.remote.l4_id,
					&session->ipv6.local.address, session->ipv6.local.l4_id,
					&session->ipv4.local.address, session->ipv4.local.l4_id,
					&session->ipv4.remote.address, session->ipv4.remote.l4_id);
			goto end;
		}
		list_del(&session->bib_list_hook);
		list_del(&session->expire_list_hook);
		session_kfree(session);
	}

	error = bib_remove(bib, req->l4_proto);
	if (error) {
		log_err(ERR_UNKNOWN_ERROR, "Remove bib entry call ended with error code %d, "
				"despite validations.", error);
		goto end;
	}

	pool4_return(req->l4_proto, &bib->ipv4);
	bib_kfree(bib);
	/* Fall through. */

end:
	spin_unlock_bh(&bib_session_lock);
	return error;
}
Ejemplo n.º 5
0
Archivo: jool.c Proyecto: npowern/NAT64
/*
 * The main function.
 */
static int main_wrapped(int argc, char **argv)
{
	struct arguments args;
	int error;

	error = parse_args(argc, argv, &args);
	if (error)
		return error;

	switch (args.mode) {
	case MODE_POOL6:
		switch (args.op) {
		case OP_DISPLAY:
			return pool6_display();
		case OP_COUNT:
			return pool6_count();
		case OP_ADD:
			if (!args.db.pool6.prefix_set) {
				log_err("Please enter the prefix to be added (--prefix).");
				return -EINVAL;
			}
			return pool6_add(&args.db.pool6.prefix);
		case OP_REMOVE:
			if (!args.db.pool6.prefix_set) {
				log_err("Please enter the prefix to be removed (--prefix).");
				return -EINVAL;
			}
			return pool6_remove(&args.db.pool6.prefix, args.db.quick);
		case OP_FLUSH:
			return pool6_flush(args.db.quick);
		default:
			log_err("Unknown operation for IPv6 pool mode: %u.", args.op);
			return -EINVAL;
		}
		break;

	case MODE_POOL4:
		switch (args.op) {
		case OP_DISPLAY:
			return pool4_display();
		case OP_COUNT:
			return pool4_count();
		case OP_ADD:
			if (!args.db.pool4.addr_set) {
				log_err("Please enter the address to be added (--address).");
				return -EINVAL;
			}
			return pool4_add(&args.db.pool4.addr);
		case OP_REMOVE:
			if (!args.db.pool4.addr_set) {
				log_err("Please enter the address to be removed (--address).");
				return -EINVAL;
			}
			return pool4_remove(&args.db.pool4.addr, args.db.quick);
		case OP_FLUSH:
			return pool4_flush(args.db.quick);
		default:
			log_err("Unknown operation for IPv4 pool mode: %u.", args.op);
			return -EINVAL;
		}
		break;

	case MODE_BIB:
		switch (args.op) {
		case OP_DISPLAY:
			return bib_display(args.db.tables.tcp, args.db.tables.udp, args.db.tables.icmp,
					args.db.tables.numeric_hostname, args.db.tables.csv_format);
		case OP_COUNT:
			return bib_count(args.db.tables.tcp, args.db.tables.udp, args.db.tables.icmp);

		case OP_ADD:
			error = 0;
			if (!args.db.tables.bib.addr6_set) {
				log_err("Missing IPv6 address#port (--bib6).");
				error = -EINVAL;
			}
			if (!args.db.tables.bib.addr4_set) {
				log_err("Missing IPv4 address#port (--bib4).");
				error = -EINVAL;
			}
			if (error)
				return error;

			return bib_add(args.db.tables.tcp, args.db.tables.udp, args.db.tables.icmp,
					&args.db.tables.bib.addr6, &args.db.tables.bib.addr4);

		case OP_REMOVE:
			if (!args.db.tables.bib.addr6_set && !args.db.tables.bib.addr4_set) {
				log_err("I need the IPv4 transport address and/or the IPv6 transport address of "
						"the entry you want to remove.");
				return -EINVAL;
			}
			return bib_remove(args.db.tables.tcp, args.db.tables.udp, args.db.tables.icmp,
					args.db.tables.bib.addr6_set, &args.db.tables.bib.addr6,
					args.db.tables.bib.addr4_set, &args.db.tables.bib.addr4);

		default:
			log_err("Unknown operation for session mode: %u.", args.op);
			return -EINVAL;
		}
		break;

	case MODE_SESSION:
		switch (args.op) {
		case OP_DISPLAY:
			return session_display(args.db.tables.tcp, args.db.tables.udp, args.db.tables.icmp,
					args.db.tables.numeric_hostname, args.db.tables.csv_format);
		case OP_COUNT:
			return session_count(args.db.tables.tcp, args.db.tables.udp, args.db.tables.icmp);
		default:
			log_err("Unknown operation for session mode: %u.", args.op);
			return -EINVAL;
		}
		break;
#ifdef BENCHMARK
	case MODE_LOGTIME:
		switch (args.op) {
		case OP_DISPLAY:
			return logtime_display();
			break;
		default:
			log_err("Unknown operation for log time mode: %u.", args.op);
			break;
		}
		break;
#endif

	case MODE_GENERAL:
		switch (args.op) {
		case OP_DISPLAY:
			return general_display();
		case OP_UPDATE:
			error = general_update(args.general.module, args.general.type, args.general.size,
					args.general.data);
			free(args.general.data);
			return error;
		default:
			log_err("Unknown operation for general mode: %u.", args.op);
			return -EINVAL;
		}
	}

	log_err("Unknown configuration mode: %u", args.mode);
	return -EINVAL;
}