StunUsageTurnReturn stun_usage_turn_process (StunMessage *msg, struct sockaddr *relay_addr, socklen_t *relay_addrlen, struct sockaddr *addr, socklen_t *addrlen, struct sockaddr *alternate_server, socklen_t *alternate_server_len, uint32_t *bandwidth, uint32_t *lifetime, StunUsageTurnCompatibility compatibility) { int val, code = -1; StunUsageTurnReturn ret = STUN_USAGE_TURN_RETURN_RELAY_SUCCESS; if (stun_message_get_method (msg) != STUN_ALLOCATE) return STUN_USAGE_TURN_RETURN_INVALID; switch (stun_message_get_class (msg)) { case STUN_REQUEST: case STUN_INDICATION: return STUN_USAGE_TURN_RETURN_INVALID; case STUN_RESPONSE: break; case STUN_ERROR: if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) { /* missing ERROR-CODE: ignore message */ return STUN_USAGE_TURN_RETURN_INVALID; } /* NOTE: currently we ignore unauthenticated messages if the context * is authenticated, for security reasons. */ stun_debug (" STUN error message received (code: %d)\n", code); /* ALTERNATE-SERVER mechanism */ if ((code / 100) == 3) { if (alternate_server && alternate_server_len) { if (stun_message_find_addr (msg, STUN_ATTRIBUTE_ALTERNATE_SERVER, alternate_server, alternate_server_len) != STUN_MESSAGE_RETURN_SUCCESS) { stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute\n"); return STUN_USAGE_TURN_RETURN_ERROR; } } else { if (!stun_message_has_attribute (msg, STUN_ATTRIBUTE_ALTERNATE_SERVER)) { stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute\n"); return STUN_USAGE_TURN_RETURN_ERROR; } } stun_debug ("Found alternate server\n"); return STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER; } return STUN_USAGE_TURN_RETURN_ERROR; } stun_debug ("Received %u-bytes STUN message\n", stun_message_length (msg)); if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_DRAFT9) { val = stun_message_find_xor_addr (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen); if (val == STUN_MESSAGE_RETURN_SUCCESS) ret = STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS; val = stun_message_find_xor_addr (msg, STUN_ATTRIBUTE_RELAY_ADDRESS, relay_addr, relay_addrlen); if (val != STUN_MESSAGE_RETURN_SUCCESS) { stun_debug (" No RELAYED-ADDRESS: %d\n", val); return STUN_USAGE_TURN_RETURN_ERROR; } } else if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_GOOGLE) { val = stun_message_find_addr (msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, relay_addr, relay_addrlen); if (val != STUN_MESSAGE_RETURN_SUCCESS) { stun_debug (" No MAPPED-ADDRESS: %d\n", val); return STUN_USAGE_TURN_RETURN_ERROR; } } else if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_MSN) { val = stun_message_find_addr (msg, STUN_ATTRIBUTE_MSN_MAPPED_ADDRESS, addr, addrlen); if (val == STUN_MESSAGE_RETURN_SUCCESS) ret = STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS; val = stun_message_find_addr (msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, relay_addr, relay_addrlen); if (val != STUN_MESSAGE_RETURN_SUCCESS) { stun_debug (" No MAPPED-ADDRESS: %d\n", val); return STUN_USAGE_TURN_RETURN_ERROR; } } stun_message_find32 (msg, STUN_ATTRIBUTE_LIFETIME, lifetime); stun_message_find32 (msg, STUN_ATTRIBUTE_BANDWIDTH, bandwidth); stun_debug (" Mapped address found!\n"); return ret; }
StunUsageIceReturn stun_usage_ice_conncheck_process (StunMessage *msg, struct sockaddr *addr, socklen_t *addrlen, StunUsageIceCompatibility compatibility) { int code = -1; StunMessageReturn val; if (stun_message_get_method (msg) != STUN_BINDING) return STUN_USAGE_ICE_RETURN_INVALID; switch (stun_message_get_class (msg)) { case STUN_REQUEST: case STUN_INDICATION: return STUN_USAGE_ICE_RETURN_INVALID; case STUN_RESPONSE: break; case STUN_ERROR: if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) { /* missing ERROR-CODE: ignore message */ return STUN_USAGE_ICE_RETURN_INVALID; } if (code == STUN_ERROR_ROLE_CONFLICT) return STUN_USAGE_ICE_RETURN_ROLE_CONFLICT; /* NOTE: currently we ignore unauthenticated messages if the context * is authenticated, for security reasons. */ stun_debug (" STUN error message received (code: %d)\n", code); return STUN_USAGE_ICE_RETURN_ERROR; } stun_debug ("Received %u-bytes STUN message\n", stun_message_length (msg)); if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSN) { StunTransactionId transid; uint32_t magic_cookie; stun_message_id (msg, transid); magic_cookie = *((uint32_t *) transid); val = stun_message_find_xor_addr_full (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen, htonl (magic_cookie)); } else { val = stun_message_find_xor_addr (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen); } if (val != STUN_MESSAGE_RETURN_SUCCESS) { stun_debug (" No XOR-MAPPED-ADDRESS: %d\n", val); val = stun_message_find_addr (msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, addr, addrlen); if (val != STUN_MESSAGE_RETURN_SUCCESS) { stun_debug (" No MAPPED-ADDRESS: %d\n", val); return STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS; } } stun_debug ("Mapped address found!\n"); return STUN_USAGE_ICE_RETURN_SUCCESS; }
static void test_vectors (void) { /* Request message */ static unsigned char req[] = {0x00, 0x01, 0x00, 0x44, 0x21, 0x12, 0xa4, 0x42, 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, 0x00, 0x24, 0x00, 0x04, // PRIORITY 0x6e, 0x00, 0x01, 0xff, 0x80, 0x29, 0x00, 0x08, // ICE_CONTROLLED 0x93, 0x2f, 0xf9, 0xb1, 0x51, 0x26, 0x3b, 0x36, 0x00, 0x06, 0x00, 0x09, // USERNAME 0x65, 0x76, 0x74, 0x6a, 0x3a, 0x68, 0x36, 0x76, 0x59, 0x20, 0x20, 0x20, 0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY 0x62, 0x4e, 0xeb, 0xdc, 0x3c, 0xc9, 0x2d, 0xd8, 0x4b, 0x74, 0xbf, 0x85, 0xd1, 0xc0, 0xf5, 0xde, 0x36, 0x87, 0xbd, 0x33, 0x80, 0x28, 0x00, 0x04, // FINGERPRINT 0xad, 0x8a, 0x85, 0xff}; static const unsigned char req2[] = {0x00, 0x01, 0x00, 0x44, 0x21, 0x12, 0xa4, 0x42, 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, 0x00, 0x24, 0x00, 0x04, // PRIORITY 0x6e, 0x00, 0x01, 0xff, 0x80, 0x29, 0x00, 0x08, // ICE_CONTROLLED 0x93, 0x2f, 0xf9, 0xb1, 0x51, 0x26, 0x3b, 0x36, 0x00, 0x06, 0x00, 0x09, // USERNAME 0x65, 0x76, 0x74, 0x6a, 0x3a, 0x68, 0x36, 0x76, 0x59, 0x20, 0x20, 0x20, 0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY 0x62, 0x4e, 0xeb, 0xdc, 0x3c, 0xc9, 0x2d, 0xd8, 0x4b, 0x74, 0xbf, 0x85, 0xd1, 0xc0, 0xf5, 0xde, 0x36, 0x87, 0xbd, 0x33, 0x80, 0x28, 0x00, 0x04, // FINGERPRINT 0xad, 0x8a, 0x85, 0xff}; /* Response message */ static const unsigned char respv4[] = {0x01, 0x01, 0x00, 0x4c, 0x21, 0x12, 0xa4, 0x42, 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, 0x80, 0x22, 0x00, 0x0b, // SERVER 0x74, 0x65, 0x73, 0x74, 0x20, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x00, 0x20, 0x00, 0x08, // XOR_MAPPED_ADDRESS 0x00, 0x01, 0xa1, 0x47, 0xe1, 0x12, 0xa6, 0x43, 0x00, 0x06, 0x00, 0x09, // USERNAME 0x65, 0x76, 0x74, 0x6a, 0x3a, 0x68, 0x36, 0x76, 0x59, 0x20, 0x20, 0x20, 0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY 0x7d, 0xb7, 0xfc, 0x52, 0x70, 0xc6, 0xdb, 0x1f, 0xc3, 0x26, 0x34, 0xbb, 0x4c, 0x64, 0x6e, 0xe7, 0x1d, 0xb3, 0x78, 0x4a, 0x80, 0x28, 0x00, 0x04, // FINGERPRINT 0xf0, 0x60, 0x66, 0xa9}; static const unsigned char respv6[] = {0x01, 0x01, 0x00, 0x58, 0x21, 0x12, 0xa4, 0x42, 0xb7, 0xe7, 0xa7, 0x01, 0xbc, 0x34, 0xd6, 0x86, 0xfa, 0x87, 0xdf, 0xae, 0x80, 0x22, 0x00, 0x0b, // SERVER 0x74, 0x65, 0x73, 0x74, 0x20, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x00, 0x20, 0x00, 0x14, // XOR_MAPPED_ADDRESS 0x00, 0x02, 0xa1, 0x47, 0x01, 0x13, 0xa9, 0xfa, 0xa5, 0xd3, 0xf1, 0x79, 0xbc, 0x25, 0xf4, 0xb5, 0xbe, 0xd2, 0xb9, 0xd9, 0x00, 0x06, 0x00, 0x09, // USERNAME 0x65, 0x76, 0x74, 0x6a, 0x3a, 0x68, 0x36, 0x76, 0x59, 0x20, 0x20, 0x20, 0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY 0x21, 0xcb, 0xbd, 0x25, 0x1a, 0x8c, 0x4c, 0x38, 0x8c, 0xc5, 0xcd, 0xb3, 0x27, 0x6a, 0xf5, 0x61, 0xb2, 0x21, 0xc8, 0x2b, 0x80, 0x28, 0x00, 0x04, // FINGERPRINT 0xec, 0x27, 0xae, 0xb7}; struct sockaddr_in ip4; struct sockaddr_in6 ip6; socklen_t addrlen; StunAgent agent; StunMessage msg; StunMessage msg2; uint16_t known_attributes[] = { STUN_ATTRIBUTE_MESSAGE_INTEGRITY, STUN_ATTRIBUTE_USERNAME, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, STUN_ATTRIBUTE_PRIORITY, 0}; stun_agent_init (&agent, known_attributes, STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS | STUN_AGENT_USAGE_USE_FINGERPRINT); memset (&ip4, 0, sizeof (ip4)); memset (&ip6, 0, sizeof (ip6)); puts ("Checking test vectors..."); if (stun_agent_validate (&agent, &msg2, req2, sizeof(req2), test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS) fatal ("Request test vector authentication failed"); if (stun_agent_validate (&agent, &msg, req, sizeof(req), test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS) fatal ("Request test vector authentication failed"); /* Remove the message-integrity and fingerprint attributes */ req[3] = 0x24; if (stun_message_length (&msg) != sizeof(req) - 32) fatal ("vector test: removing attributes failed"); stun_agent_finish_message (&agent, &msg, vector_password, strlen (vector_password)); if (stun_message_length (&msg) != stun_message_length (&msg2) || memcmp (req, req2, sizeof(req)) != 0) fatal ("vector test : req and req2 are different"); if (stun_agent_validate (&agent, &msg, respv4, sizeof(respv4), test_vector_validater, (void *) 0) != STUN_VALIDATION_SUCCESS) fatal ("Response ipv4 test vector authentication failed"); if (stun_agent_validate (&agent, &msg, respv4, sizeof(respv4), test_vector_validater, (void *) 0) != STUN_VALIDATION_UNMATCHED_RESPONSE) fatal ("Response ipv4 test vector authentication failed"); addrlen = sizeof (ip4); if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, (struct sockaddr *)&ip4, &addrlen) != STUN_MESSAGE_RETURN_SUCCESS) fatal ("Response test vector IPv4 extraction failed"); if (ip4.sin_family != AF_INET) fatal ("Response test vector IPv4 family failed"); if (ntohl (ip4.sin_addr.s_addr) != 0xC0000201) fatal ("Response test vector IPv4 address failed"); if (ntohs (ip4.sin_port) != 32853) fatal ("Response test vector IPv6 port failed"); if (stun_agent_validate (&agent, &msg, req, sizeof(req), test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS) fatal ("Request test vector second authentication failed"); /* Remove the fingerprint attributes */ msg.key = NULL; msg.key_len = 0; req[3] = 0x3C; if (stun_message_length (&msg) != sizeof(req) - 8) fatal ("vector test: removing attributes failed"); stun_agent_finish_message (&agent, &msg, NULL, 0); if (stun_message_length (&msg) != stun_message_length (&msg2) || memcmp (req, req2, sizeof(req)) != 0) fatal ("vector test : req and req2 are different"); if (stun_agent_validate (&agent, &msg, respv6, sizeof(respv6), test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS) fatal ("Response ipv6 test vector authentication failed"); addrlen = sizeof (ip6); if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, (struct sockaddr *)&ip6, &addrlen) != STUN_MESSAGE_RETURN_SUCCESS) fatal ("Response test vector IPv6 extraction failed"); if (ip6.sin6_family != AF_INET6) fatal ("Response test vector IPv6 family failed"); if (memcmp (ip6.sin6_addr.s6_addr, "\x20\x01\x0d\xb8\x12\x34\x56\x78" "\x00\x11\x22\x33\x44\x55\x66\x77", 16) != 0) fatal ("Response test vector IPv6 address failed"); if (ntohs (ip6.sin6_port) != 32853) fatal ("Response test vector IPv6 port failed"); puts ("Done."); }
StunUsageBindReturn stun_usage_bind_process (StunMessage *msg, struct sockaddr *addr, socklen_t *addrlen, struct sockaddr *alternate_server, socklen_t *alternate_server_len) { int code = -1; StunMessageReturn val; if (stun_message_get_method (msg) != STUN_BINDING) return STUN_USAGE_BIND_RETURN_INVALID; switch (stun_message_get_class (msg)) { case STUN_REQUEST: case STUN_INDICATION: return STUN_USAGE_BIND_RETURN_INVALID; case STUN_RESPONSE: break; case STUN_ERROR: if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) { /* missing ERROR-CODE: ignore message */ return STUN_USAGE_BIND_RETURN_INVALID; } /* NOTE: currently we ignore unauthenticated messages if the context * is authenticated, for security reasons. */ stun_debug (" STUN error message received (code: %d)", code); /* ALTERNATE-SERVER mechanism */ if ((code / 100) == 3) { if (alternate_server && alternate_server_len) { if (stun_message_find_addr (msg, STUN_ATTRIBUTE_ALTERNATE_SERVER, (struct sockaddr_storage *) alternate_server, alternate_server_len) != STUN_MESSAGE_RETURN_SUCCESS) { stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute"); return STUN_USAGE_BIND_RETURN_ERROR; } } else { if (!stun_message_has_attribute (msg, STUN_ATTRIBUTE_ALTERNATE_SERVER)) { stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute"); return STUN_USAGE_BIND_RETURN_ERROR; } } stun_debug ("Found alternate server"); return STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER; } return STUN_USAGE_BIND_RETURN_ERROR; default: /* Fall through. */ break; } stun_debug ("Received %u-bytes STUN message", stun_message_length (msg)); val = stun_message_find_xor_addr (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, (struct sockaddr_storage *)addr, addrlen); if (val != STUN_MESSAGE_RETURN_SUCCESS) { stun_debug (" No XOR-MAPPED-ADDRESS: %d", val); val = stun_message_find_addr (msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, (struct sockaddr_storage *)addr, addrlen); if (val != STUN_MESSAGE_RETURN_SUCCESS) { stun_debug (" No MAPPED-ADDRESS: %d", val); return STUN_USAGE_BIND_RETURN_ERROR; } } stun_debug (" Mapped address found!"); return STUN_USAGE_BIND_RETURN_SUCCESS; }
/* Tests for message attribute parsing */ static void test_attribute (void) { static const uint8_t acme[] = {0x04, 0x55, 0x00, 0x6C, // <-- update message length if needed!! 0x21, 0x12, 0xA4, 0x42, // cookie 0x76, 0x54, 0x32, 0x10, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, /* FF01: empty */ 0xff, 0x01, 0x00, 0x00, /* FF02: address of unknown family, 32-bits */ 0xff, 0x02, 0x00, 0x04, 0x41, 0x42, 0x43, 0x44, /* FF03: too short IPv6 address */ 0xff, 0x03, 0x00, 0x06, 0x00, 0x02, 0x12, 0x34, 0x20, 0x01, 0x0d, 0xb8, /* FF04: valid IPv4 address, 64-bits */ 0xff, 0x04, 0x00, 0x08, 0x00, 0x01, 0x12, 0x34, 0xc0, 0x00, 0x02, 0x01, /* FF05: too long IPv4 address */ 0xff, 0x05, 0x00, 0x0A, 0x00, 0x01, 0x12, 0x34, 0xc0, 0x00, 0x02, 0x01, 0x66, 0x60, 0x00, 0x00, /* FF06: valid xor'd IPv6 address, 160-bits */ 0xff, 0x06, 0x00, 0x14, 0x00, 0x02, 0x12, 0x34, 0x01, 0x13, 0xa9, 0xfa, 0xa8, 0xf9, 0x8c, 0xff, 0x20, 0x26, 0x74, 0x48, 0x8c, 0x9a, 0xec, 0xfd, /* dummy USERNAME header */ 0x00, 0x06, 0x00, 0x04, 0x41, 0x42, 0x43, 0x44, /* MESSAGE-INTEGRITY attribute */ 0x00, 0x08, 0x00, 0x14, 0x0b, 0xc4, 0xb2, 0x0c, 0x94, 0x58, 0xbb, 0x25, 0xa3, 0x22, 0x1a, 0xc8, 0xe1, 0x87, 0x32, 0x36, 0x3a, 0xfc, 0xe2, 0xc3}; union { struct sockaddr sa; struct sockaddr_in6 s6; } addr; socklen_t addrlen; uint32_t dword; uint64_t qword; char str[STUN_MAX_STR]; StunAgent agent; StunMessage msg; uint16_t known_attributes[] = {STUN_ATTRIBUTE_MESSAGE_INTEGRITY, STUN_ATTRIBUTE_USERNAME, 0}; printf ("Attribute test message length: %lu\n", sizeof (acme)); stun_agent_init (&agent, known_attributes, STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS); if (stun_agent_validate (&agent, &msg, acme, sizeof(acme), NULL, NULL) != STUN_VALIDATION_UNAUTHORIZED) fatal ("Unauthorized validation failed"); if (stun_agent_validate (&agent, &msg, acme, sizeof(acme), test_attribute_validater, "bad__guy") != STUN_VALIDATION_UNAUTHORIZED) fatal ("invalid password validation failed"); if (stun_agent_validate (&agent, &msg, acme, sizeof(acme), test_attribute_validater, "good_guy") != STUN_VALIDATION_SUCCESS) fatal ("good password validation failed"); if (stun_message_has_attribute (&msg, 0xff00)) fatal ("Absent attribute test failed"); if (!stun_message_has_attribute (&msg, 0xff01)) fatal ("Present attribute test failed"); if (stun_message_find_flag (&msg, 0xff00) != STUN_MESSAGE_RETURN_NOT_FOUND) fatal ("Absent flag test failed"); if (stun_message_find_flag (&msg, 0xff01) != STUN_MESSAGE_RETURN_SUCCESS) fatal ("Flag test failed"); if (stun_message_find_flag (&msg, 0xff02) != STUN_MESSAGE_RETURN_INVALID) fatal ("Too big flag test failed"); if (stun_message_find32 (&msg, 0xff00, &dword) != STUN_MESSAGE_RETURN_NOT_FOUND) fatal ("Absent dword test failed"); if (stun_message_find32 (&msg, 0xff01, &dword) != STUN_MESSAGE_RETURN_INVALID) fatal ("Bad dword test failed"); if (stun_message_find32 (&msg, 0xff02, &dword) != STUN_MESSAGE_RETURN_SUCCESS) fatal ("Double-word test failed"); if (stun_message_find64 (&msg, 0xff00, &qword) != STUN_MESSAGE_RETURN_NOT_FOUND) fatal ("Absent qword test failed"); if (stun_message_find64 (&msg, 0xff01, &qword) != STUN_MESSAGE_RETURN_INVALID) fatal ("Bad qword test failed"); if (stun_message_find64 (&msg, 0xff04, &qword) != STUN_MESSAGE_RETURN_SUCCESS) fatal ("Quad-word test failed"); if (stun_message_find_string (&msg, 0xff00, str, STUN_MAX_CP) != STUN_MESSAGE_RETURN_NOT_FOUND) fatal ("Absent string test failed"); if ((stun_message_find_string (&msg, 0xff02, str, STUN_MAX_CP) != STUN_MESSAGE_RETURN_SUCCESS) || strcmp (str, "ABCD")) fatal ("String test failed"); addrlen = sizeof (addr); if (stun_message_find_addr (&msg, 0xff01, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_INVALID) fatal ("Too short addres test failed"); addrlen = sizeof (addr); if (stun_message_find_addr (&msg, 0xff02, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS) fatal ("Unknown address family test failed"); addrlen = sizeof (addr); if (stun_message_find_addr (&msg, 0xff03, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_INVALID) fatal ("Too short IPv6 address test failed"); addrlen = sizeof (addr); if (stun_message_find_addr (&msg, 0xff04, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_SUCCESS) fatal ("IPv4 address test failed"); addrlen = sizeof (addr); if (stun_message_find_addr (&msg, 0xff05, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_INVALID) fatal ("Too big IPv4 address test failed"); addrlen = sizeof (addr); if (stun_message_find_xor_addr (&msg, 0xff06, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_SUCCESS || memcmp (&addr.s6.sin6_addr, "\x20\x01\x0d\xb8""\xde\xad\xbe\xef" "\xde\xfa\xce\xd0""\xfa\xce\xde\xed", 16)) fatal ("IPv6 address test failed"); }