staticvoid test_optmem_limit(void)
{
size_t i, keys_limit, current_optmem = test_get_optmem(); struct tcp_ao_add ao; union tcp_addr net = {}; int sk;
if (inet_pton(TEST_FAMILY, TEST_NETWORK, &net) != 1)
test_error("Can't convert ip address %s", TEST_NETWORK);
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
keys_limit = current_optmem / KERNEL_TCP_AO_KEY_SZ_ROUND_UP; for (i = 0;; i++) { union tcp_addr key_peer; int err;
key_peer = gen_tcp_addr(net, i + 1);
tcp_addr_to_sockaddr_in(&ao.addr, &key_peer, 0);
err = setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY,
&ao, sizeof(ao)); if (!err) { /* * TCP_AO_ADD_KEY should be the same order as the real * sizeof(struct tcp_ao_key) in kernel.
*/ if (i <= keys_limit * 10) continue;
test_fail("optmem limit test failed: added %zu key", i); break;
} if (i < keys_limit) {
test_fail("optmem limit test failed: couldn't add %zu key", i); break;
}
test_ok("optmem limit was hit on adding %zu key", i); break;
}
close(sk);
}
staticvoid test_einval_add_key(void)
{ struct tcp_ao_add ao; int sk;
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
ao.keylen = TCP_AO_MAXKEYLEN + 1;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "too big keylen");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
make_listen(sk);
ao.set_current = 1;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "add current key on a listen socket");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
make_listen(sk);
ao.set_rnext = 1;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "add rnext key on a listen socket");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
make_listen(sk);
ao.set_current = 1;
ao.set_rnext = 1;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "add current+rnext key on a listen socket");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
ao.set_current = 1;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "add key and set as current");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
ao.set_rnext = 1;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "add key and set as rnext");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
ao.set_current = 1;
ao.set_rnext = 1;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "add key and set as current+rnext");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
ao.ifindex = 42;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "ifindex without TCP_AO_KEYF_IFNINDEX");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
ao.keyflags |= TCP_AO_KEYF_IFINDEX;
ao.ifindex = 42;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "non-existent VRF"); /* * tcp_md5_do_lookup{,_any_l3index}() are checked in unsigned-md5 * see client_vrf_tests().
*/
test_optmem_limit();
/* tcp_ao_parse_crypto() */
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
ao.maclen = 100;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EMSGSIZE, "maclen bigger than TCP hdr");
sk = prepare_defs(TCP_AO_DEL_KEY, &del);
make_listen(sk); if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))
test_error("add key");
del.set_current = 1;
setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "del and set current key on a listen socket");
sk = prepare_defs(TCP_AO_DEL_KEY, &del);
make_listen(sk); if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))
test_error("add key");
del.set_rnext = 1;
setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "del and set rnext key on a listen socket");
sk = prepare_defs(TCP_AO_DEL_KEY, &del);
make_listen(sk); if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))
test_error("add key");
del.set_current = 1;
del.set_rnext = 1;
setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "del and set current+rnext key on a listen socket");
sk = prepare_defs(TCP_AO_DEL_KEY, &del);
del.set_current = 1;
del.current_key = 100;
setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set as current key to be removed");
sk = prepare_defs(TCP_AO_DEL_KEY, &del);
del.set_rnext = 1;
del.rnext = 100;
setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set as rnext key to be removed");
sk = prepare_defs(TCP_AO_DEL_KEY, &del);
del.set_current = 1;
del.current_key = 100;
del.set_rnext = 1;
del.rnext = 100;
setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set as current+rnext key to be removed");
sk = prepare_defs(TCP_AO_DEL_KEY, &del);
del.del_async = 1;
setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "async on non-listen");
staticvoid test_einval_ao_info(void)
{ struct tcp_ao_info_opt info; int sk;
sk = prepare_defs(TCP_AO_INFO, &info);
make_listen(sk);
info.set_current = 1;
setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "set current key on a listen socket");
sk = prepare_defs(TCP_AO_INFO, &info);
make_listen(sk);
info.set_rnext = 1;
setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "set rnext key on a listen socket");
sk = prepare_defs(TCP_AO_INFO, &info);
make_listen(sk);
info.set_current = 1;
info.set_rnext = 1;
setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "set current+rnext key on a listen socket");
staticvoid duplicate_tests(void)
{ union tcp_addr network_dup; struct tcp_ao_add ao, ao2; int sk;
sk = prepare_defs(TCP_AO_ADD_KEY, &ao); if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))
test_error("setsockopt()");
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: full copy");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao);
ao2 = ao;
memcpy(&ao2.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));
ao2.prefix = 0; if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao2, sizeof(ao)))
test_error("setsockopt()");
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: any addr key on the socket");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao); if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))
test_error("setsockopt()");
memcpy(&ao.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));
ao.prefix = 0;
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: add any addr key");
if (inet_pton(TEST_FAMILY, TEST_NETWORK, &network_dup) != 1)
test_error("Can't convert ip address %s", TEST_NETWORK);
sk = prepare_defs(TCP_AO_ADD_KEY, &ao); if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))
test_error("setsockopt()"); if (test_prepare_def_key(&ao, "password", 0, network_dup,
16, 0, 100, 100))
test_error("prepare default tcp_ao_add");
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: add any addr for the same subnet");
sk = prepare_defs(TCP_AO_ADD_KEY, &ao); if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))
test_error("setsockopt()");
setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: full copy of a key");
f = -1;
sk = prepare_test_keys(original_keys); for (int i = 0; i < original_keys[0].nkeys; i++) { if (original_keys[i].is_current) {
f = i; break;
}
} if (f < 0)
test_error("No current key after adding one");
filter.is_current = 1;
filter_keys_checked(sk, &filter, &original_keys[f], 1, "by is_current");
f = -1;
sk = prepare_test_keys(original_keys); for (int i = 0; i < original_keys[0].nkeys; i++) { if (original_keys[i].is_rnext) {
f = i; break;
}
} if (f < 0)
test_error("No rnext key after adding one");
filter.is_rnext = 1;
filter_keys_checked(sk, &filter, &original_keys[f], 1, "by is_rnext");
f = -1;
nmatches = 0;
sk = prepare_test_keys(original_keys); for (int i = 0; i < original_keys[0].nkeys; i++) { if (original_keys[i].sndid == 100) {
f = i;
memcpy(&expected_keys[nmatches], &original_keys[i], sizeof(struct tcp_ao_getsockopt));
nmatches++;
}
} if (f < 0)
test_error("No key for sndid 100"); if (nmatches != 2)
test_error("Should have 2 keys with sndid 100");
filter.rcvid = original_keys[f].rcvid;
filter.sndid = original_keys[f].sndid;
filter.addr.ss_family = test_family;
filter_keys_checked(sk, &filter, expected_keys, nmatches, "by sndid, rcvid");
sk = prepare_test_keys(original_keys);
filter.get_all = 1;
filter.nkeys = FILTER_TEST_NKEYS / 2;
len = sizeof(struct tcp_ao_getsockopt); if (getsockopt(sk, IPPROTO_TCP, TCP_AO_GET_KEYS, &filter, &len))
test_error("getsockopt"); if (filter.nkeys == FILTER_TEST_NKEYS)
test_ok("filter keys: correct nkeys when in.nkeys < matches"); else
test_fail("filter keys: wrong nkeys, expected %u got %u",
FILTER_TEST_NKEYS, filter.nkeys);
}
staticvoid *client_fn(void *arg)
{ if (inet_pton(TEST_FAMILY, __TEST_CLIENT_IP(2), &tcp_md5_client) != 1)
test_error("Can't convert ip address");
extend_tests();
einval_tests();
filter_tests();
duplicate_tests();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.