Exemple #1
0
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;

}
Exemple #2
0
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;
}
Exemple #3
0
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.");
}
Exemple #4
0
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;

}
Exemple #5
0
/* 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");

}