#include #include #include #include #include #include #include T_GLOBAL_META( T_META_NAMESPACE("xnu.pfkey"), T_META_ASROOT(true), T_META_RADAR_COMPONENT_NAME("xnu"), T_META_RADAR_COMPONENT_VERSION("NetworkExtension"), T_META_CHECK_LEAKS(false)); #define MAX_SPD_CHECK 100 #define TEST_SRC_ADDRESS_IPv4 "192.168.2.2" #define TEST_DST_ADDRESS_IPv4 "192.168.2.3" #define TEST_SRC_ADDRESS_IPv6 "fd04:5c6b:8df7:7092:0000:0000:0000:0002" #define TEST_DST_ADDRESS_IPv6 "fd04:5c6b:8df7:7092:0000:0000:0000:0003" #define TEST_MIGRATE_SRC_ADDRESS_IPv4 "192.168.2.10" #define TEST_MIGRATE_DST_ADDRESS_IPv4 "192.168.2.11" #define TEST_MIGRATE_SRC_ADDRESS_IPv6 "fd04:5c6b:8df7:7092:0000:0000:0002:0000" #define TEST_MIGRATE_DST_ADDRESS_IPv6 "fd04:5c6b:8df7:7092:0000:0000:0003:0000" typedef enum { TEST_INVALID = 0, TEST_SADB_X_GET_OVERFLOW_60822136 = 1, TEST_SADB_X_SPDENABLE_OVERFLOW_60822924 = 2, TEST_SADB_X_SPDDISABLE_OVERFLOW_60822956 = 3, TEST_SADB_UPDATE_USE_AFTER_FREE_60679513 = 4, TEST_SADB_DUMP_HEAP_OVERFLOW_60768729 = 5, TEST_SADB_POLICY_DUMP_HEAP_OVERFLOW_60769680 = 6, TEST_SADB_GETSASTAT_OOB_READ_60822823 = 7, TEST_SADB_GETSASTAT_OOB_READ_SUCCESS = 8, TEST_SADB_EXT_MIGRATE_ADDRESS_IPv4 = 9, TEST_SADB_EXT_MIGRATE_ADDRESS_IPv6 = 10, TEST_SADB_EXT_MIGRATE_BAD_ADDRESS = 11, TEST_TCP_INPUT_IPSEC_COPY_POLICY = 12, TEST_SADB_X_SPDADD_MEMORY_LEAK_78944570 = 13, TEST_SADB_EXT_MIGRATE_AFTER_EXPIRY_134671927 = 14, } test_identifier; static test_identifier test_id = TEST_INVALID; static dispatch_source_t pfkey_source = NULL; static unsigned long oldmax; static void pfkey_cleanup(void); static void pfkey_process_message_test_60822136(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_60822924(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_60822956(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_60679513(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_60768729(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_60769680(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_60822823(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_60822823_1(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_60687183(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_60687183_1(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_60687183_2(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_78944570(uint8_t **mhp, int pfkey_socket); static void pfkey_process_message_test_134671927(uint8_t **mhp, int pfkey_socket); static void(*const process_pfkey_message_tests[])(uint8_t * *mhp, int pfkey_socket) = { NULL, pfkey_process_message_test_60822136, // TEST_SADB_X_GET_OVERFLOW_60822136 pfkey_process_message_test_60822924, // TEST_SADB_X_SPDENABLE_OVERFLOW_60822924 pfkey_process_message_test_60822956, // TEST_SADB_X_SPDDISABLE_OVERFLOW_60822956 pfkey_process_message_test_60679513, // TEST_SADB_UPDATE_USE_AFTER_FREE_60679513 pfkey_process_message_test_60768729, // TEST_SADB_DUMP_HEAP_OVERFLOW_60768729 pfkey_process_message_test_60769680, // TEST_SADB_POLICY_DUMP_HEAP_OVERFLOW_60769680 pfkey_process_message_test_60822823, // TEST_SADB_GETSASTAT_OOB_READ_60822823 pfkey_process_message_test_60822823_1, // TEST_SADB_GETSASTAT_OOB_READ_SUCCESS pfkey_process_message_test_60687183, // TEST_SADB_EXT_MIGRATE_ADDRESS_IPv4 pfkey_process_message_test_60687183_1, // TEST_SADB_EXT_MIGRATE_ADDRESS_IPv6 pfkey_process_message_test_60687183_2, // TEST_SADB_EXT_MIGRATE_BAD_ADDRESS NULL, // TEST_TCP_INPUT_IPSEC_COPY_POLICY pfkey_process_message_test_78944570, // TEST_SADB_X_SPDADD_MEMORY_LEAK_78944570 pfkey_process_message_test_134671927, // TEST_SADB_EXT_MIGRATE_AFTER_EXPIRY_134671927 }; static void pfkey_align(struct sadb_msg *msg, uint8_t **mhp) { struct sadb_ext *ext; int i; uint8_t *p; uint8_t *ep; /* XXX should be passed from upper layer */ /* validity check */ T_QUIET; T_ASSERT_NOTNULL(msg, "pfkey align msg"); T_QUIET; T_ASSERT_NOTNULL(mhp, "pfkey align mhp"); /* initialize */ for (i = 0; i < SADB_EXT_MAX + 1; i++) { mhp[i] = NULL; } mhp[0] = (void *)msg; /* initialize */ p = (void *) msg; ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len); /* skip base header */ p += sizeof(struct sadb_msg); while (p < ep) { ext = (void *)p; T_QUIET; T_ASSERT_GE_PTR((void *)ep, (void *)(p + sizeof(*ext)), "pfkey extension header beyond end of buffer"); T_QUIET; T_ASSERT_GE_ULONG((unsigned long)PFKEY_EXTLEN(ext), sizeof(*ext), "pfkey extension shorter than extension header"); T_QUIET; T_ASSERT_GE_PTR((void *)ep, (void *)(p + PFKEY_EXTLEN(ext)), "pfkey extension length beyond end of buffer"); T_QUIET; T_EXPECT_NULL(mhp[ext->sadb_ext_type], "duplicate extension type %u payload", ext->sadb_ext_type); /* set pointer */ switch (ext->sadb_ext_type) { case SADB_EXT_SA: case SADB_EXT_LIFETIME_CURRENT: case SADB_EXT_LIFETIME_HARD: case SADB_EXT_LIFETIME_SOFT: case SADB_EXT_ADDRESS_SRC: case SADB_EXT_ADDRESS_DST: case SADB_EXT_ADDRESS_PROXY: case SADB_EXT_KEY_AUTH: /* XXX should to be check weak keys. */ case SADB_EXT_KEY_ENCRYPT: /* XXX should to be check weak keys. */ case SADB_EXT_IDENTITY_SRC: case SADB_EXT_IDENTITY_DST: case SADB_EXT_SENSITIVITY: case SADB_EXT_PROPOSAL: case SADB_EXT_SUPPORTED_AUTH: case SADB_EXT_SUPPORTED_ENCRYPT: case SADB_EXT_SPIRANGE: case SADB_X_EXT_POLICY: case SADB_X_EXT_SA2: case SADB_EXT_SESSION_ID: case SADB_EXT_SASTAT: #ifdef SADB_X_EXT_NAT_T_TYPE case SADB_X_EXT_NAT_T_TYPE: case SADB_X_EXT_NAT_T_SPORT: case SADB_X_EXT_NAT_T_DPORT: case SADB_X_EXT_NAT_T_OA: #endif #ifdef SADB_X_EXT_TAG case SADB_X_EXT_TAG: #endif #ifdef SADB_X_EXT_PACKET case SADB_X_EXT_PACKET: #endif case SADB_X_EXT_IPSECIF: case SADB_X_EXT_ADDR_RANGE_SRC_START: case SADB_X_EXT_ADDR_RANGE_SRC_END: case SADB_X_EXT_ADDR_RANGE_DST_START: case SADB_X_EXT_ADDR_RANGE_DST_END: #ifdef SADB_MIGRATE case SADB_EXT_MIGRATE_ADDRESS_SRC: case SADB_EXT_MIGRATE_ADDRESS_DST: case SADB_X_EXT_MIGRATE_IPSECIF: #endif mhp[ext->sadb_ext_type] = (void *)ext; break; default: T_FAIL("bad extension type %u", ext->sadb_ext_type); T_END; } p += PFKEY_EXTLEN(ext); } T_QUIET; T_EXPECT_EQ_PTR((void *)ep, (void *)p, "invalid pfkey message length"); return; } static void recv_pfkey_message(int pfkey_socket) { uint8_t buffer[8192] __attribute__((aligned(4))); struct iovec iovecs[1] = { { buffer, sizeof(buffer) }, }; struct msghdr msg = { NULL, 0, iovecs, sizeof(iovecs) / sizeof(iovecs[0]), NULL, 0, 0, }; do { ssize_t result = -1; memset(buffer, 0, sizeof(buffer)); T_QUIET; T_ASSERT_POSIX_SUCCESS(result = recvmsg(pfkey_socket, &msg, 0), NULL); if (result > 0) { T_QUIET; T_ASSERT_GE_ULONG((size_t)result, sizeof(struct sadb_msg), "Invalid PFKey message size: %zu", result); struct sadb_msg *hdr = (struct sadb_msg *)buffer; uint8_t *mhp[SADB_EXT_MAX + 1]; pfkey_align(hdr, mhp); (*process_pfkey_message_tests[test_id])(mhp, pfkey_socket); } else if (result == 0) { T_LOG("PFKey socket received EOF"); break; } } while (1); } static void send_pfkey_spd_add_message(int pfkey_socket, uint8_t proto) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_X_SPDADD; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (u_int32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen); src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff; src_address_payload->sadb_address_proto = proto & 0xff; src_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3); src_address_payload->sadb_address_reserved = 0; tlen += sizeof(*src_address_payload); struct sockaddr_in *src = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_SRC_ADDRESS_IPv4, &src->sin_addr), 1, "src address fail"); src->sin_family = AF_INET; src->sin_len = sizeof(*src); uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src->sin_len); src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(src->sin_len); struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen); dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff; dst_address_payload->sadb_address_proto = proto & 0xff; dst_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3); dst_address_payload->sadb_address_reserved = 0; tlen += sizeof(*dst_address_payload); struct sockaddr_in *dst = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_DST_ADDRESS_IPv4, &dst->sin_addr), 1, "dst address fail"); dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst->sin_len); dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(dst->sin_len); struct sadb_lifetime *lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen); lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*lifetime_payload)); lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; tlen += sizeof(*lifetime_payload); struct sadb_x_policy *policy_payload = (struct sadb_x_policy *)(void *)(payload + tlen); policy_payload->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*policy_payload)); policy_payload->sadb_x_policy_exttype = SADB_X_EXT_POLICY; policy_payload->sadb_x_policy_type = IPSEC_POLICY_DISCARD; if (test_id == TEST_SADB_X_SPDADD_MEMORY_LEAK_78944570) { policy_payload->sadb_x_policy_dir = IPSEC_DIR_INVALID; } else { policy_payload->sadb_x_policy_dir = IPSEC_DIR_OUTBOUND; } tlen += sizeof(*policy_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd add"); } static void send_pfkey_spd_get_message(int pfkey_socket, uint32_t policy_id) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)(void *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_X_SPDGET; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (uint32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_x_policy *policy_payload = (struct sadb_x_policy *)(void *)(payload + tlen); policy_payload->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*policy_payload)); policy_payload->sadb_x_policy_exttype = SADB_X_EXT_POLICY; policy_payload->sadb_x_policy_id = policy_id; tlen += sizeof(*policy_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd get failed"); } static void send_pfkey_spd_enable_message(int pfkey_socket, uint32_t policy_id) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)(void *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_X_SPDENABLE; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (uint32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_x_policy *policy_payload = (struct sadb_x_policy *)(void *)(payload + tlen); policy_payload->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*policy_payload)); policy_payload->sadb_x_policy_exttype = SADB_X_EXT_POLICY; policy_payload->sadb_x_policy_id = policy_id; tlen += sizeof(*policy_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd enable failed"); } static void send_pfkey_spd_disable_message(int pfkey_socket, uint32_t policy_id) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)(void *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_X_SPDDISABLE; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (uint32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_x_policy *policy_payload = (struct sadb_x_policy *)(void *)(payload + tlen); policy_payload->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*policy_payload)); policy_payload->sadb_x_policy_exttype = SADB_X_EXT_POLICY; policy_payload->sadb_x_policy_id = policy_id; tlen += sizeof(*policy_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd disable failed"); } static void send_pfkey_spd_delete_message(int pfkey_socket, uint32_t policy_id) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_X_SPDDELETE2; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (uint32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_x_policy *policy_payload = (struct sadb_x_policy *)(void *)(payload + tlen); policy_payload->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*policy_payload)); policy_payload->sadb_x_policy_exttype = SADB_X_EXT_POLICY; policy_payload->sadb_x_policy_id = policy_id; tlen += sizeof(*policy_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd delete failed"); } static void send_pfkey_spd_dump_message(int pfkey_socket) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)(void *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_X_SPDDUMP; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (uint32_t)getpid(); tlen += sizeof(*msg_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd dump failed"); } static void send_pfkey_flush_sp(int pfkey_socket) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_X_SPDFLUSH; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (u_int32_t)getpid(); tlen += sizeof(*msg_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey flush security policies"); } static void send_pfkey_register(int pfkey_socket) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_REGISTER; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_ESP; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (u_int32_t)getpid(); tlen += sizeof(*msg_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey flush security policies"); } static void send_pkey_get_spi(int pfkey_socket) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_GETSPI; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_ESP; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (u_int32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_x_sa2 *sa2_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen); sa2_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_payload)); sa2_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2; sa2_payload->sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT; sa2_payload->sadb_x_sa2_reqid = 0; tlen += sizeof(*sa2_payload); struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen); src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff; src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; src_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3); src_address_payload->sadb_address_reserved = 0; tlen += sizeof(*src_address_payload); struct sockaddr_in *src = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_SRC_ADDRESS_IPv4, &src->sin_addr), 1, "src address fail"); src->sin_family = AF_INET; src->sin_len = sizeof(*src); uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src->sin_len); src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(src->sin_len); struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen); dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff; dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; dst_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3); dst_address_payload->sadb_address_reserved = 0; tlen += sizeof(*dst_address_payload); struct sockaddr_in *dst = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_DST_ADDRESS_IPv4, &dst->sin_addr), 1, "dst address fail"); dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst->sin_len); dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(dst->sin_len); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send get spi"); } static void send_pkey_add_sa(int pfkey_socket, uint32_t spi, const char *src, const char *dst, int family) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_ADD; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_ESP; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (u_int32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen); sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload)); sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA; sa2_payload->sa.sadb_sa_spi = htonl(spi); sa2_payload->sa.sadb_sa_replay = 4; sa2_payload->sa.sadb_sa_state = SADB_SASTATE_LARVAL; sa2_payload->sa.sadb_sa_auth = SADB_X_AALG_SHA2_256; sa2_payload->sa.sadb_sa_encrypt = SADB_X_EALG_AESCBC; sa2_payload->sa.sadb_sa_flags |= (SADB_X_EXT_NATT | SADB_X_EXT_NATT_KEEPALIVE); sa2_payload->sadb_sa_natt_src_port = htons(4500); sa2_payload->sadb_sa_natt_port = 4500; sa2_payload->sadb_sa_natt_interval = 20; sa2_payload->sadb_sa_natt_offload_interval = 0; tlen += sizeof(*sa2_payload); struct sadb_x_sa2 *sa2_x_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen); sa2_x_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_x_payload)); sa2_x_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2; sa2_x_payload->sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT; sa2_x_payload->sadb_x_sa2_reqid = 0; if (test_id == TEST_SADB_EXT_MIGRATE_AFTER_EXPIRY_134671927) { sa2_x_payload->sadb_x_sa2_alwaysexpire = 1; } tlen += sizeof(*sa2_x_payload); uint8_t prefixlen = (family == AF_INET) ? (sizeof(struct in_addr) << 3) : (sizeof(struct in6_addr) << 3); struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen); src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff; src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; src_address_payload->sadb_address_prefixlen = prefixlen; src_address_payload->sadb_address_reserved = 0; tlen += sizeof(*src_address_payload); if (family == AF_INET) { struct sockaddr_in *src4 = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, src, &src4->sin_addr), 1, "src address fail"); src4->sin_family = AF_INET; src4->sin_len = sizeof(*src4); uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src4->sin_len); src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(src4->sin_len); } else { struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, src, &src6->sin6_addr), 1, "src address fail"); src6->sin6_family = AF_INET6; src6->sin6_len = sizeof(*src6); uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src6->sin6_len); src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(src6->sin6_len); } struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen); dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff; dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; dst_address_payload->sadb_address_prefixlen = prefixlen; dst_address_payload->sadb_address_reserved = 0; tlen += sizeof(*dst_address_payload); if (family == AF_INET) { struct sockaddr_in *dst4 = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, dst, &dst4->sin_addr), 1, "dst address fail"); dst4->sin_family = AF_INET; dst4->sin_len = sizeof(*dst4); uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst4->sin_len); dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(dst4->sin_len); } else { struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, dst, &dst6->sin6_addr), 1, "dst address fail"); dst6->sin6_family = AF_INET6; dst6->sin6_len = sizeof(*dst6); uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst6->sin6_len); dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(dst6->sin6_len); } struct sadb_key *encrypt_key_payload = (struct sadb_key *)(void *)(payload + tlen); uint16_t len = sizeof(*encrypt_key_payload) + PFKEY_ALIGN8(32); encrypt_key_payload->sadb_key_len = PFKEY_UNIT64(len); encrypt_key_payload->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; encrypt_key_payload->sadb_key_bits = (uint16_t)(32 << 3); encrypt_key_payload->sadb_key_reserved = 0; tlen += sizeof(*encrypt_key_payload); arc4random_buf(payload + tlen, 32); tlen += PFKEY_ALIGN8(32); struct sadb_key *auth_key_payload = (struct sadb_key *)(void *)(payload + tlen); len = sizeof(*auth_key_payload) + PFKEY_ALIGN8(32); auth_key_payload->sadb_key_len = PFKEY_UNIT64(len); auth_key_payload->sadb_key_exttype = SADB_EXT_KEY_AUTH; auth_key_payload->sadb_key_bits = (uint16_t)(32 << 3); auth_key_payload->sadb_key_reserved = 0; tlen += sizeof(*auth_key_payload); arc4random_buf(payload + tlen, 32); tlen += PFKEY_ALIGN8(32); struct sadb_lifetime *hard_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen); hard_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*hard_lifetime_payload)); hard_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; tlen += sizeof(*hard_lifetime_payload); struct sadb_lifetime *soft_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen); soft_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*soft_lifetime_payload)); soft_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; if (test_id == TEST_SADB_EXT_MIGRATE_AFTER_EXPIRY_134671927) { soft_lifetime_payload->sadb_lifetime_addtime = 1; } tlen += sizeof(*soft_lifetime_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send update sa"); } static void send_pkey_update_sa(int pfkey_socket, uint32_t spi) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_UPDATE; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_ESP; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (u_int32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen); sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload)); sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA; sa2_payload->sa.sadb_sa_spi = htonl(spi); sa2_payload->sa.sadb_sa_replay = 4; sa2_payload->sa.sadb_sa_state = SADB_SASTATE_LARVAL; sa2_payload->sa.sadb_sa_auth = SADB_X_AALG_SHA2_256; sa2_payload->sa.sadb_sa_encrypt = SADB_X_EALG_AESCBC; sa2_payload->sa.sadb_sa_flags |= (SADB_X_EXT_NATT | SADB_X_EXT_NATT_KEEPALIVE); sa2_payload->sadb_sa_natt_src_port = htons(4500); sa2_payload->sadb_sa_natt_port = 0; // Bad value to trigger failure sa2_payload->sadb_sa_natt_interval = 20; sa2_payload->sadb_sa_natt_offload_interval = 0; tlen += sizeof(*sa2_payload); struct sadb_x_sa2 *sa2_x_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen); sa2_x_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_x_payload)); sa2_x_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2; sa2_x_payload->sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT; sa2_x_payload->sadb_x_sa2_reqid = 0; tlen += sizeof(*sa2_x_payload); struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen); src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff; src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; src_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3); src_address_payload->sadb_address_reserved = 0; tlen += sizeof(*src_address_payload); struct sockaddr_in *src = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_SRC_ADDRESS_IPv4, &src->sin_addr), 1, "src address fail"); src->sin_family = AF_INET; src->sin_len = sizeof(*src); uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src->sin_len); src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(src->sin_len); struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen); dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff; dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; dst_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3); dst_address_payload->sadb_address_reserved = 0; tlen += sizeof(*dst_address_payload); struct sockaddr_in *dst = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_DST_ADDRESS_IPv4, &dst->sin_addr), 1, "dst address fail"); dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst->sin_len); dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(dst->sin_len); struct sadb_key *encrypt_key_payload = (struct sadb_key *)(void *)(payload + tlen); len = sizeof(*encrypt_key_payload) + PFKEY_ALIGN8(32); encrypt_key_payload->sadb_key_len = PFKEY_UNIT64(len); encrypt_key_payload->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; encrypt_key_payload->sadb_key_bits = (uint16_t)(32 << 3); encrypt_key_payload->sadb_key_reserved = 0; tlen += sizeof(*encrypt_key_payload); arc4random_buf(payload + tlen, 32); tlen += PFKEY_ALIGN8(32); struct sadb_key *auth_key_payload = (struct sadb_key *)(void *)(payload + tlen); len = sizeof(*auth_key_payload) + PFKEY_ALIGN8(32); auth_key_payload->sadb_key_len = PFKEY_UNIT64(len); auth_key_payload->sadb_key_exttype = SADB_EXT_KEY_AUTH; auth_key_payload->sadb_key_bits = (uint16_t)(32 << 3); auth_key_payload->sadb_key_reserved = 0; tlen += sizeof(*auth_key_payload); arc4random_buf(payload + tlen, 32); tlen += PFKEY_ALIGN8(32); struct sadb_lifetime *hard_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen); hard_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*hard_lifetime_payload)); hard_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; tlen += sizeof(*hard_lifetime_payload); struct sadb_lifetime *soft_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen); soft_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*soft_lifetime_payload)); soft_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; tlen += sizeof(*soft_lifetime_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send update sa"); } static void send_pkey_migrate_sa(int pfkey_socket, uint32_t spi, const char *src, const char *dst, int family, const char *migrate_src, const char *migrate_dst, int migrate_family) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_MIGRATE; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_ESP; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (u_int32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen); sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload)); sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA; sa2_payload->sa.sadb_sa_spi = htonl(spi); sa2_payload->sa.sadb_sa_replay = 4; sa2_payload->sa.sadb_sa_state = SADB_SASTATE_LARVAL; sa2_payload->sa.sadb_sa_auth = SADB_X_AALG_SHA2_256; sa2_payload->sa.sadb_sa_encrypt = SADB_X_EALG_AESCBC; sa2_payload->sa.sadb_sa_flags |= (SADB_X_EXT_NATT | SADB_X_EXT_NATT_KEEPALIVE); sa2_payload->sadb_sa_natt_src_port = htons(4500); sa2_payload->sadb_sa_natt_port = 0; // Bad value to trigger failure sa2_payload->sadb_sa_natt_interval = 20; sa2_payload->sadb_sa_natt_offload_interval = 0; tlen += sizeof(*sa2_payload); struct sadb_x_sa2 *sa2_x_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen); sa2_x_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_x_payload)); sa2_x_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2; sa2_x_payload->sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT; sa2_x_payload->sadb_x_sa2_reqid = 0; tlen += sizeof(*sa2_x_payload); uint8_t prefixlen = (family == AF_INET) ? (sizeof(struct in_addr) << 3) : (sizeof(struct in6_addr) << 3); struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen); src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff; src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; src_address_payload->sadb_address_prefixlen = prefixlen; src_address_payload->sadb_address_reserved = 0; tlen += sizeof(*src_address_payload); if (family == AF_INET) { struct sockaddr_in *src4 = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, src, &src4->sin_addr), 1, "src address fail"); src4->sin_family = AF_INET; src4->sin_len = sizeof(*src4); uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src4->sin_len); src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(src4->sin_len); } else { struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, src, &src6->sin6_addr), 1, "src address fail"); src6->sin6_family = AF_INET6; src6->sin6_len = sizeof(*src6); uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src6->sin6_len); src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(src6->sin6_len); } struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen); dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff; dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; dst_address_payload->sadb_address_prefixlen = prefixlen; dst_address_payload->sadb_address_reserved = 0; tlen += sizeof(*dst_address_payload); if (family == AF_INET) { struct sockaddr_in *dst4 = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, dst, &dst4->sin_addr), 1, "dst address fail"); dst4->sin_family = AF_INET; dst4->sin_len = sizeof(*dst4); uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst4->sin_len); dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(dst4->sin_len); } else { struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, dst, &dst6->sin6_addr), 1, "dst address fail"); dst6->sin6_family = AF_INET6; dst6->sin6_len = sizeof(*dst6); uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst6->sin6_len); dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(dst6->sin6_len); } prefixlen = (migrate_family == AF_INET) ? (sizeof(struct in_addr) << 3) : (sizeof(struct in6_addr) << 3); struct sadb_address *migrate_src_address_payload = (struct sadb_address *)(void *)(payload + tlen); migrate_src_address_payload->sadb_address_exttype = SADB_EXT_MIGRATE_ADDRESS_SRC & 0xffff; migrate_src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; migrate_src_address_payload->sadb_address_prefixlen = prefixlen; migrate_src_address_payload->sadb_address_reserved = 0; tlen += sizeof(*migrate_src_address_payload); if (migrate_family == AF_INET) { struct sockaddr_in *migrate_src4 = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, migrate_src, &migrate_src4->sin_addr), 1, "migrate src fail"); migrate_src4->sin_family = AF_INET; migrate_src4->sin_len = sizeof(*migrate_src4); uint16_t len = sizeof(*migrate_src_address_payload) + PFKEY_ALIGN8(migrate_src4->sin_len); migrate_src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(migrate_src4->sin_len); } else if (migrate_family == AF_INET6) { struct sockaddr_in6 *migrate_src6 = (struct sockaddr_in6 *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, migrate_src, &migrate_src6->sin6_addr), 1, "migrate src fail"); migrate_src6->sin6_family = AF_INET6; migrate_src6->sin6_len = sizeof(*migrate_src6); uint16_t len = sizeof(*migrate_src_address_payload) + PFKEY_ALIGN8(migrate_src6->sin6_len); migrate_src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(migrate_src6->sin6_len); } else if (migrate_family == AF_CHAOS) { struct sockaddr_in6 *migrate_src6 = (struct sockaddr_in6 *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, migrate_src, &migrate_src6->sin6_addr), 1, "migrate src fail"); migrate_src6->sin6_family = AF_INET6; migrate_src6->sin6_len = sizeof(*migrate_src6) + 100; // Bad value to trigger exploit uint16_t len = sizeof(*migrate_src_address_payload) + PFKEY_ALIGN8(migrate_src6->sin6_len); migrate_src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(migrate_src6->sin6_len); } struct sadb_address *migrate_dst_address_payload = (struct sadb_address *)(void *)(payload + tlen); migrate_dst_address_payload->sadb_address_exttype = SADB_EXT_MIGRATE_ADDRESS_DST & 0xffff; migrate_dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; migrate_dst_address_payload->sadb_address_prefixlen = prefixlen; migrate_dst_address_payload->sadb_address_reserved = 0; tlen += sizeof(*migrate_dst_address_payload); if (migrate_family == AF_INET) { struct sockaddr_in *migrate_dst4 = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, migrate_dst, &migrate_dst4->sin_addr), 1, "migrate dst fail"); migrate_dst4->sin_family = AF_INET; migrate_dst4->sin_len = sizeof(*migrate_dst4); uint16_t len = sizeof(*migrate_dst_address_payload) + PFKEY_ALIGN8(migrate_dst4->sin_len); migrate_dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(migrate_dst4->sin_len); } else if (migrate_family == AF_INET6) { struct sockaddr_in6 *migrate_dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, migrate_dst, &migrate_dst6->sin6_addr), 1, "migrate dst fail"); migrate_dst6->sin6_family = AF_INET6; migrate_dst6->sin6_len = sizeof(*migrate_dst6); uint16_t len = sizeof(*migrate_dst_address_payload) + PFKEY_ALIGN8(migrate_dst6->sin6_len); migrate_dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(migrate_dst6->sin6_len); } else if (migrate_family == AF_CHAOS) { struct sockaddr_in6 *migrate_dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, migrate_dst, &migrate_dst6->sin6_addr), 1, "migrate dst fail"); migrate_dst6->sin6_family = AF_INET6; migrate_dst6->sin6_len = sizeof(*migrate_dst6) + 100; // Bad value to trigger exploit uint16_t len = sizeof(*migrate_dst_address_payload) + PFKEY_ALIGN8(migrate_dst6->sin6_len); migrate_dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(migrate_dst6->sin6_len); } // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send migrate sa"); } static void send_pfkey_get_sa_stat(int pfkey_socket, uint32_t spi, uint32_t stat_length) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_GETSASTAT; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (u_int32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_session_id *session_id_payload = (struct sadb_session_id *)(void *)(payload + tlen); session_id_payload->sadb_session_id_len = PFKEY_UNIT64(sizeof(*session_id_payload)); session_id_payload->sadb_session_id_exttype = SADB_EXT_SESSION_ID; session_id_payload->sadb_session_id_v[0] = 1; tlen += sizeof(*session_id_payload); struct sadb_sastat *sadb_stat_payload = (struct sadb_sastat *)(void *)(payload + tlen); uint16_t length = sizeof(*sadb_stat_payload) + PFKEY_ALIGN8(sizeof(struct sastat)); sadb_stat_payload->sadb_sastat_len = PFKEY_UNIT64(length); sadb_stat_payload->sadb_sastat_exttype = SADB_EXT_SASTAT; sadb_stat_payload->sadb_sastat_dir = IPSEC_DIR_OUTBOUND; sadb_stat_payload->sadb_sastat_list_len = stat_length; tlen += sizeof(*sadb_stat_payload); struct sastat *sastat_payload = (struct sastat *)(void *)(payload + tlen); sastat_payload->spi = htonl(spi); tlen += PFKEY_ALIGN8(sizeof(*sastat_payload)); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send get sa stat"); } static void send_pkey_delete_sa(int pfkey_socket, uint32_t spi) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_DELETE; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_ESP; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (u_int32_t)getpid(); tlen += sizeof(*msg_payload); struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen); sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload)); sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA; sa2_payload->sa.sadb_sa_spi = htonl(spi); tlen += sizeof(*sa2_payload); struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen); src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff; src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; src_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3); src_address_payload->sadb_address_reserved = 0; tlen += sizeof(*src_address_payload); struct sockaddr_in *src = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_SRC_ADDRESS_IPv4, &src->sin_addr), 1, "migrate src fail"); src->sin_family = AF_INET; src->sin_len = sizeof(*src); uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src->sin_len); src_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(src->sin_len); struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen); dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff; dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff; dst_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3); dst_address_payload->sadb_address_reserved = 0; tlen += sizeof(*dst_address_payload); struct sockaddr_in *dst = (struct sockaddr_in *)(void *)(payload + tlen); T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_DST_ADDRESS_IPv4, &dst->sin_addr), 1, "migrate dst fail"); dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst->sin_len); dst_address_payload->sadb_address_len = PFKEY_UNIT64(len); tlen += PFKEY_ALIGN8(dst->sin_len); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send delete sa"); } static void send_pfkey_sa_dump_message(int pfkey_socket) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)(void *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_DUMP; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (uint32_t)getpid(); tlen += sizeof(*msg_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send sa dump failed"); } static void send_pfkey_flush_sa(int pfkey_socket) { uint8_t payload[MCLBYTES] __attribute__ ((aligned(32))); bzero(payload, sizeof(payload)); uint16_t tlen = 0; struct sadb_msg *msg_payload = (struct sadb_msg *)payload; msg_payload->sadb_msg_version = PF_KEY_V2; msg_payload->sadb_msg_type = SADB_FLUSH; msg_payload->sadb_msg_errno = 0; msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC; msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); msg_payload->sadb_msg_reserved = 0; msg_payload->sadb_msg_seq = 0; msg_payload->sadb_msg_pid = (u_int32_t)getpid(); tlen += sizeof(*msg_payload); // Update the total length msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen); T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey flush sa"); } static void pfkey_cleanup(void) { if (pfkey_source != NULL) { int pfkey_socket = (int)dispatch_source_get_handle(pfkey_source); if (pfkey_socket > 0) { send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); } dispatch_source_cancel(pfkey_source); pfkey_source = NULL; } if (oldmax != 0) { (void)sysctlbyname("kern.ipc.maxsockbuf", NULL, NULL, &oldmax, sizeof(oldmax)); } } static int pfkey_setup_socket(void) { int pfkey_socket = -1; int bufsiz = 0; const unsigned long newbufk = 1536; size_t oldmaxsize = sizeof(oldmax); unsigned long newmax = newbufk * (1024 + 128); T_QUIET; T_ASSERT_POSIX_SUCCESS(pfkey_socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2), NULL); if (sysctlbyname("kern.ipc.maxsockbuf", &oldmax, &oldmaxsize, &newmax, sizeof(newmax)) != 0) { bufsiz = 233016; /* Max allowed by default */ } else { bufsiz = newbufk * 800; } T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(pfkey_socket, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)), "pfkey set snd socket buf failed %d", bufsiz); T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(pfkey_socket, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)), "pfkey set recv socket buf failed %d", bufsiz); pfkey_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t)pfkey_socket, 0, dispatch_get_main_queue()); T_QUIET; T_ASSERT_NOTNULL(pfkey_source, "dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, ...)"); dispatch_source_set_event_handler(pfkey_source, ^{ recv_pfkey_message(pfkey_socket); }); dispatch_source_set_cancel_handler(pfkey_source, ^{ close(pfkey_socket); }); dispatch_resume(pfkey_source); return pfkey_socket; } static void pfkey_process_message_test_60822136(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static int counter = 0; static uint32_t policy_id = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } if (message->sadb_msg_errno) { T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_X_SPDDUMP, "SADB error for type %u", message->sadb_msg_type); pfkey_cleanup(); T_END; } switch (message->sadb_msg_type) { case SADB_X_SPDADD: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd add policy message is NULL"); policy_id = policy_message->sadb_x_policy_id; T_LOG("Added policy id %u", policy_id); send_pfkey_spd_get_message(pfkey_socket, policy_id); break; } case SADB_X_SPDGET: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd get policy message is NULL"); T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_get: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id); if (counter < MAX_SPD_CHECK) { counter++; send_pfkey_spd_get_message(pfkey_socket, policy_id); } else { T_LOG("Deleting policy id %u", policy_id); send_pfkey_spd_delete_message(pfkey_socket, policy_id); } break; } case SADB_X_SPDDELETE2: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd delete2 policy message is NULL"); T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_delete2: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id); T_LOG("Deleted policy id %u", policy_id); sleep(2); send_pfkey_spd_dump_message(pfkey_socket); break; } case SADB_X_SPDDUMP: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd dump policy message is NULL"); T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_dump: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id); T_FAIL("Policy id %u still exists", policy_id); pfkey_cleanup(); T_END; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_60822924(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static int counter = 0; static uint32_t policy_id = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } if (message->sadb_msg_errno) { T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_X_SPDDUMP, "SADB error for type %u", message->sadb_msg_type); pfkey_cleanup(); T_END; } switch (message->sadb_msg_type) { case SADB_X_SPDADD: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd add policy message is NULL"); policy_id = policy_message->sadb_x_policy_id; T_LOG("Added policy id %u", policy_id); send_pfkey_spd_enable_message(pfkey_socket, policy_id); break; } case SADB_X_SPDENABLE: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd enable policy message is NULL"); T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_enable: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id); if (counter < MAX_SPD_CHECK) { counter++; send_pfkey_spd_enable_message(pfkey_socket, policy_id); } else { T_LOG("Deleting policy id %u", policy_id); send_pfkey_spd_delete_message(pfkey_socket, policy_id); } break; } case SADB_X_SPDDELETE2: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd delete2 policy message is NULL"); T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_delete2: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id); T_LOG("Deleted policy id %u", policy_id); sleep(2); send_pfkey_spd_dump_message(pfkey_socket); break; } case SADB_X_SPDDUMP: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd dump policy message is NULL"); T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_dump: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id); T_FAIL("Policy id %u still exists", policy_id); pfkey_cleanup(); T_END; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_60822956(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static int counter = 0; static uint32_t policy_id = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } if (message->sadb_msg_errno) { T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_X_SPDDUMP, "SADB error for type %u", message->sadb_msg_type); pfkey_cleanup(); T_END; } switch (message->sadb_msg_type) { case SADB_X_SPDADD: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd add policy message is NULL"); policy_id = policy_message->sadb_x_policy_id; T_LOG("Added policy id %u", policy_id); send_pfkey_spd_disable_message(pfkey_socket, policy_id); break; } case SADB_X_SPDDISABLE: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd disable policy message is NULL"); T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_disable: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id); if (counter < MAX_SPD_CHECK) { counter++; send_pfkey_spd_disable_message(pfkey_socket, policy_id); } else { T_LOG("Deleting policy id %u", policy_id); send_pfkey_spd_delete_message(pfkey_socket, policy_id); } break; } case SADB_X_SPDDELETE2: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd delete2 policy message is NULL"); T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_delete2: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id); T_LOG("Deleted policy id %u", policy_id); sleep(2); send_pfkey_spd_dump_message(pfkey_socket); break; } case SADB_X_SPDDUMP: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd dump policy message is NULL"); T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_dump: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id); T_FAIL("Policy id %u still exists", policy_id); pfkey_cleanup(); T_END; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_60679513(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static uint32_t spi = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } if (message->sadb_msg_errno) { T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_UPDATE, "SADB error for type %u", message->sadb_msg_type); } switch (message->sadb_msg_type) { case SADB_GETSPI: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "sa get spi message is NULL"); spi = ntohl(sa_message->sadb_sa_spi); T_LOG("get spi 0x%x", spi); send_pkey_update_sa(pfkey_socket, spi); break; } case SADB_UPDATE: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "update sa message is NULL"); T_QUIET; T_ASSERT_EQ(spi, ntohl(sa_message->sadb_sa_spi), "sadb update: spi mismatch %u != %u", spi, ntohl(sa_message->sadb_sa_spi)); T_LOG("update sa 0x%x", spi); send_pkey_delete_sa(pfkey_socket, spi); break; } case SADB_DELETE: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "delete sa message is NULL"); T_QUIET; T_ASSERT_EQ(spi, ntohl(sa_message->sadb_sa_spi), "sadb delete: spi mismatch %u != %u", spi, ntohl(sa_message->sadb_sa_spi)); T_LOG("delete sa 0x%x", spi); pfkey_cleanup(); T_END; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_60768729(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; uint32_t spi = 0; static int counter = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u", message->sadb_msg_type); switch (message->sadb_msg_type) { case SADB_GETSPI: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "sa get spi message is NULL"); spi = ntohl(sa_message->sadb_sa_spi); counter++; if (counter <= 1000) { send_pkey_get_spi(pfkey_socket); } else { T_LOG("SADB added 1000 Larval SPIs"); send_pfkey_sa_dump_message(pfkey_socket); } break; } case SADB_DUMP: { counter--; if (counter == 0) { T_PASS("SADB dump successful"); pfkey_cleanup(); T_END; } break; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_60769680(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static uint8_t counter = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); switch (message->sadb_msg_type) { case SADB_X_SPDADD: { struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY]; T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd add policy message is NULL"); counter++; if (counter <= 240) { send_pfkey_spd_add_message(pfkey_socket, counter + 1); } else { T_LOG("SADB added 240 security policies"); send_pfkey_spd_dump_message(pfkey_socket); } break; } case SADB_X_SPDDUMP: { counter--; if (counter == 0) { T_PASS("SADB policy dump successful"); pfkey_cleanup(); T_END; } break; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_60822823(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static uint32_t spi = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } if (message->sadb_msg_errno != 0) { T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_GETSASTAT, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, EINVAL, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); T_PASS("SADB get SA Stat received EINVAL"); T_END; } switch (message->sadb_msg_type) { case SADB_ADD: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL"); spi = ntohl(sa_message->sadb_sa_spi); T_LOG("added sa 0x%x", spi); send_pfkey_get_sa_stat(pfkey_socket, spi, 5); break; } case SADB_GETSASTAT: { T_FAIL("get sa stat should fail %u", message->sadb_msg_type); T_END; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_60822823_1(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static uint32_t spi = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); switch (message->sadb_msg_type) { case SADB_ADD: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL"); spi = ntohl(sa_message->sadb_sa_spi); T_LOG("added sa 0x%x", spi); send_pfkey_get_sa_stat(pfkey_socket, spi, 1); break; } case SADB_GETSASTAT: { struct sadb_session_id *session_id = (struct sadb_session_id *)(void *)mhp[SADB_EXT_SESSION_ID]; T_QUIET; T_ASSERT_NOTNULL(session_id, "session id is NULL"); T_QUIET; T_EXPECT_EQ_ULLONG(session_id->sadb_session_id_v[0], 1ULL, "Session id is not equal"); T_PASS("get sa stat success %u", message->sadb_msg_type); T_END; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_60687183(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static uint32_t spi = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); switch (message->sadb_msg_type) { case SADB_ADD: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL"); spi = ntohl(sa_message->sadb_sa_spi); T_LOG("added sa 0x%x", spi); send_pkey_migrate_sa(pfkey_socket, spi, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET, TEST_MIGRATE_SRC_ADDRESS_IPv4, TEST_MIGRATE_DST_ADDRESS_IPv4, AF_INET); break; } case SADB_MIGRATE: { T_PASS("migrate SA success"); T_END; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_60687183_1(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static uint32_t spi = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); switch (message->sadb_msg_type) { case SADB_ADD: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL"); spi = ntohl(sa_message->sadb_sa_spi); T_LOG("added sa 0x%x", spi); send_pkey_migrate_sa(pfkey_socket, spi, TEST_SRC_ADDRESS_IPv6, TEST_DST_ADDRESS_IPv6, AF_INET6, TEST_MIGRATE_SRC_ADDRESS_IPv6, TEST_MIGRATE_DST_ADDRESS_IPv6, AF_INET6); break; } case SADB_MIGRATE: { T_PASS("migrate SA success"); T_END; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_60687183_2(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static uint32_t spi = 0; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } if (message->sadb_msg_errno != 0) { T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_MIGRATE, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, EINVAL, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); T_PASS("SADB migrate SA received EINVAL"); T_END; } T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); switch (message->sadb_msg_type) { case SADB_ADD: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL"); spi = ntohl(sa_message->sadb_sa_spi); T_LOG("added sa 0x%x", spi); send_pkey_migrate_sa(pfkey_socket, spi, TEST_SRC_ADDRESS_IPv6, TEST_DST_ADDRESS_IPv6, AF_INET6, TEST_MIGRATE_SRC_ADDRESS_IPv6, TEST_MIGRATE_DST_ADDRESS_IPv6, AF_CHAOS); break; } case SADB_MIGRATE: { T_FAIL("migrate SA test for bad address failed"); T_END; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_78944570(uint8_t **mhp, __unused int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; if (message->sadb_msg_pid != (uint32_t)getpid()) { return; } switch (message->sadb_msg_type) { case SADB_X_SPDADD: { if (message->sadb_msg_errno != 0) { T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, EINVAL, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); T_PASS("SADB spd add received EINVAL"); } else { T_FAIL("SADB spd add received success"); } T_END; break; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static void pfkey_process_message_test_134671927(uint8_t **mhp, int pfkey_socket) { struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0]; static uint32_t spi = 0; if (message->sadb_msg_type != SADB_EXPIRE && message->sadb_msg_pid != (uint32_t)getpid()) { return; } T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno); switch (message->sadb_msg_type) { case SADB_REGISTER: { T_LOG("registered for SA updates"); send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv6, TEST_DST_ADDRESS_IPv6, AF_INET6); break; } case SADB_ADD: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL"); spi = ntohl(sa_message->sadb_sa_spi); T_LOG("added sa 0x%x", spi); break; } case SADB_EXPIRE: { struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA]; T_QUIET; T_ASSERT_NOTNULL(sa_message, "expire sa message is NULL"); if (spi == 0 || spi != ntohl(sa_message->sadb_sa_spi)) { break; } T_LOG("expire sa 0x%x", spi); send_pkey_migrate_sa(pfkey_socket, spi, TEST_SRC_ADDRESS_IPv6, TEST_DST_ADDRESS_IPv6, AF_INET6, TEST_MIGRATE_SRC_ADDRESS_IPv6, TEST_MIGRATE_DST_ADDRESS_IPv6, AF_INET6); break; } case SADB_MIGRATE: { T_PASS("migrate SA success"); T_END; } case SADB_FLUSH: case SADB_X_SPDFLUSH: break; default: T_FAIL("bad SADB message type %u", message->sadb_msg_type); T_END; } return; } static int setup_tcp_server(uint16_t port) { struct sockaddr_in server_addr = {}; int server_fd = -1; T_QUIET; T_ASSERT_POSIX_SUCCESS(server_fd = socket(AF_INET, SOCK_STREAM, 0), "tcp server socket creation failed"); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(port); T_QUIET; T_ASSERT_POSIX_SUCCESS(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)), "tcp server bind failed"); T_QUIET; T_ASSERT_POSIX_SUCCESS(listen(server_fd, 2), "tcp server listen failed"); return server_fd; } static int setup_loopback_tcp_client(uint16_t server_port) { struct sockaddr_in conn_addr = {}; int client_fd = -1; T_QUIET; T_ASSERT_POSIX_SUCCESS(client_fd = socket(AF_INET, SOCK_STREAM, 0), "tcp client socket creation failed"); T_QUIET; T_ASSERT_POSIX_SUCCESS(inet_pton(AF_INET, "127.0.0.1", &conn_addr.sin_addr), "loopback address inet_pton failed"); conn_addr.sin_family = AF_INET; conn_addr.sin_port = htons(server_port); T_QUIET; T_ASSERT_POSIX_SUCCESS(connect(client_fd, (struct sockaddr *)&conn_addr, sizeof(conn_addr)), "tcp loopback client connect failed"); return client_fd; } static void setup_socket_policy(int socket_fd) { uint8_t __attribute__((aligned(4))) buf[ sizeof(struct sadb_x_policy) + sizeof(struct sadb_x_ipsecrequest) + sizeof(struct sockaddr_in) + sizeof(struct sockaddr_in) ]; struct sadb_x_policy *xpl = (struct sadb_x_policy *)buf; struct sadb_x_ipsecrequest *xisr = (struct sadb_x_ipsecrequest *)(xpl + 1); struct sockaddr *sa; bzero(buf, sizeof(buf)); /* xpl: */ xpl->sadb_x_policy_len = sizeof(buf) >> 3; xpl->sadb_x_policy_dir = IPSEC_DIR_INBOUND; xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC; /* xisr: */ xisr->sadb_x_ipsecrequest_len = sizeof(buf) - sizeof(*xpl); xisr->sadb_x_ipsecrequest_proto = IPPROTO_ESP; xisr->sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT; xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_DEFAULT; /* src sockaddr: */ sa = (struct sockaddr *)(xisr + 1); sa->sa_len = sizeof(struct sockaddr_in); /* dst sockaddr: */ sa = (struct sockaddr *)((char *)(xisr + 1) + sa->sa_len); sa->sa_len = sizeof(struct sockaddr_in); T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(socket_fd, IPPROTO_IP, IP_IPSEC_POLICY, buf, sizeof(buf)), "tcp server listen failed"); } T_DECL(sadb_x_get_60822136, "security policy reference count overflow", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_X_GET_OVERFLOW_60822136; int pfkey_socket = pfkey_setup_socket(); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pfkey_spd_add_message(pfkey_socket, IPSEC_ULPROTO_ANY); dispatch_main(); } T_DECL(sadb_x_spd_enable_60822924, "security policy reference count overflow", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_X_SPDENABLE_OVERFLOW_60822924; int pfkey_socket = pfkey_setup_socket(); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pfkey_spd_add_message(pfkey_socket, IPSEC_ULPROTO_ANY); dispatch_main(); } T_DECL(sadb_x_spd_disable_60822956, "security policy reference count overflow", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_X_SPDDISABLE_OVERFLOW_60822956; int pfkey_socket = pfkey_setup_socket(); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pfkey_spd_add_message(pfkey_socket, IPSEC_ULPROTO_ANY); dispatch_main(); } T_DECL(sadb_update_60679513, "security association use after free", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_UPDATE_USE_AFTER_FREE_60679513; int pfkey_socket = pfkey_setup_socket(); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pkey_get_spi(pfkey_socket); dispatch_main(); } T_DECL(sadb_dump_60768729, "security association sa dump heap overflow", T_META_ENABLED(false), T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_DUMP_HEAP_OVERFLOW_60768729; int pfkey_socket = pfkey_setup_socket(); T_ATEND(pfkey_cleanup); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pkey_get_spi(pfkey_socket); dispatch_main(); } // Disabled due to rdar://92910783 T_DECL(sadb_policy_dump_60769680, "security association sa policy dump heap overflow", T_META_ENABLED(false), T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_POLICY_DUMP_HEAP_OVERFLOW_60769680; int pfkey_socket = pfkey_setup_socket(); T_ATEND(pfkey_cleanup); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pfkey_spd_add_message(pfkey_socket, 1); dispatch_main(); } T_DECL(sadb_get_sastat_oob_60769680, "security association get sa stat oob read", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_GETSASTAT_OOB_READ_60822823; int pfkey_socket = pfkey_setup_socket(); T_ATEND(pfkey_cleanup); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET); dispatch_main(); } T_DECL(sadb_get_sastat_success, "security association get sa stat", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_GETSASTAT_OOB_READ_SUCCESS; int pfkey_socket = pfkey_setup_socket(); T_ATEND(pfkey_cleanup); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET); dispatch_main(); } T_DECL(sadb_key_migrate_address_ipv4, "security association migrate address ipv4", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_EXT_MIGRATE_ADDRESS_IPv4; int pfkey_socket = pfkey_setup_socket(); T_ATEND(pfkey_cleanup); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET); dispatch_main(); } T_DECL(sadb_key_migrate_address_ipv6, "security association migrate address ipv6", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_EXT_MIGRATE_ADDRESS_IPv6; int pfkey_socket = pfkey_setup_socket(); T_ATEND(pfkey_cleanup); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv6, TEST_DST_ADDRESS_IPv6, AF_INET6); dispatch_main(); } T_DECL(sadb_key_migrate_bad_address, "security association migrate bad address", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_EXT_MIGRATE_BAD_ADDRESS; int pfkey_socket = pfkey_setup_socket(); T_ATEND(pfkey_cleanup); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv6, TEST_DST_ADDRESS_IPv6, AF_INET6); dispatch_main(); } T_DECL(tcp_input_ipsec_copy_policy, "listener policy copied to child", T_META_TAG_VM_PREFERRED) { test_id = TEST_TCP_INPUT_IPSEC_COPY_POLICY; int server_fd = setup_tcp_server(4000); setup_socket_policy(server_fd); int client_fd = setup_loopback_tcp_client(4000); sleep(3); close(client_fd); close(server_fd); T_PASS("listener policy copied to child"); } T_DECL(sadb_x_spd_add_78944570, "security policy add failure", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_X_SPDADD_MEMORY_LEAK_78944570; int pfkey_socket = pfkey_setup_socket(); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pfkey_spd_add_message(pfkey_socket, IPSEC_ULPROTO_ANY); dispatch_main(); } T_DECL(sadb_key_migrate_after_expiry_134671927, "security association migrate after expiry", T_META_TAG_VM_PREFERRED) { test_id = TEST_SADB_EXT_MIGRATE_AFTER_EXPIRY_134671927; int pfkey_socket = pfkey_setup_socket(); T_ATEND(pfkey_cleanup); send_pfkey_flush_sa(pfkey_socket); send_pfkey_flush_sp(pfkey_socket); send_pfkey_register(pfkey_socket); dispatch_main(); }