⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stun_common.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@internal * @file stun_common.c * @brief  *  * @author Tat Chan <Tat.Chan@nokia.com> * @author Kai Vehmanen <kai.vehmanen@nokia.com> *   * @date Created: Fri Oct  3 13:40:41 2003 ppessi *  */#include "config.h"#ifdef USE_TURN#include "../turn/turn_common.h"#undef STUN_A_LAST_MANDATORY#define STUN_A_LAST_MANDATORY TURN_LARGEST_ATTRIBUTE#endif#include "stun_internal.h"#include <string.h>#include <stdlib.h>#include <assert.h>#if HAVE_FUNC#elif HAVE_FUNCTION#define __func__ __FUNCTION__#else#define __func__ "stun_common"#endifconst char stun_400_Bad_request[] = "Bad Request",  stun_401_Unauthorized[] = "Unauthorized",  stun_420_Unknown_attribute[] = "Unknown Attribute",  stun_430_Stale_credentials[] = "Stale Credentials",  stun_431_Integrity_check_failure[] = "Integrity Check Failure",  stun_432_Missing_username[] = "Missing Username",  stun_433_Use_tls[] = "Use TLS",#ifdef USE_TURN  turn_434_Missing_realm[] = "Missing Realm",  turn_435_Missing_nonce[] = "Missing Nonce",  turn_436_Unknown_username[] = "Unknown Username",  turn_437_No_binding[] = "No Binding",  turn_439_Illegal_port[] = "Illegal Port",#endif  stun_500_Server_error[] = "Server Error",  stun_600_Global_failure[] = "Global Failure";#define set16(b, offset, value)			\  (((b)[(offset) + 0] = ((value) >> 8) & 255),	\   ((b)[(offset) + 1] = (value) & 255))#define get16(b, offset)	\  (((b)[(offset) + 0] << 8) |	\   ((b)[(offset) + 1] << 0))int stun_parse_message(stun_msg_t *msg){  unsigned len;  int i;  unsigned char *p;  /* parse header first */  p = msg->enc_buf.data;  msg->stun_hdr.msg_type = get16(p, 0);  msg->stun_hdr.msg_len = get16(p, 2);   memcpy(msg->stun_hdr.tran_id, p + 4, STUN_TID_BYTES);  SU_DEBUG_5(("%s: Parse STUN message: Length = %d\n", __func__,	      msg->stun_hdr.msg_len));  /* parse attributes */  len = msg->stun_hdr.msg_len;  p = msg->enc_buf.data + 20;  msg->stun_attr = NULL;  while (len > 0) {    i = stun_parse_attribute(msg, p);    if (i <= 0) {      SU_DEBUG_3(("%s: Error parsing attribute.\n", __func__));      return -1;    }    p += i;    len -= i;  }  return 0;}int stun_parse_attribute(stun_msg_t *msg, unsigned char *p){  int len;  uint16_t attr_type;  stun_attr_t *attr, *next;  attr_type = get16(p, 0);  len = get16(p, 2);  SU_DEBUG_5(("%s: received attribute: Type %02X, Length %d - %s\n", 	      __func__, attr_type, len, stun_attr_phrase(attr_type)));  if (attr_type > STUN_A_LAST_MANDATORY && attr_type < STUN_A_OPTIONAL) {    return -1;  }  attr = (stun_attr_t *)calloc(1, sizeof(stun_attr_t));  if (!attr)    return -1;  attr->next = NULL;  attr->attr_type = attr_type;  p += 4;  switch (attr->attr_type) {  case MAPPED_ADDRESS:  case RESPONSE_ADDRESS:  case SOURCE_ADDRESS:  case CHANGED_ADDRESS:  case REFLECTED_FROM:#ifdef USE_TURN  case TURN_ALTERNATE_SERVER:  case TURN_DESTINATION_ADDRESS:  case TURN_SOURCE_ADDRESS:#endif    if (stun_parse_attr_address(attr, p, len) < 0) {      free(attr);      return -1;    }    break;  case ERROR_CODE:    if (stun_parse_attr_error_code(attr, p, len) <0) { free(attr); return -1; }    break;  case UNKNOWN_ATTRIBUTES:    if(stun_parse_attr_unknown_attributes(attr, p, len) <0) { free(attr); return -1; }    break;  case CHANGE_REQUEST:#ifdef USE_TURN  case TURN_LIFETIME:  case TURN_MAGIC_COOKIE:  case TURN_BANDWIDTH:#endif    if (stun_parse_attr_uint32(attr, p, len) <0) { free(attr); return -1; }    break;  case USERNAME:  case PASSWORD:  case STUN_A_REALM:  case STUN_A_NONCE:#ifdef USE_TURN  case TURN_DATA:  case TURN_NONCE:#endif    if (stun_parse_attr_buffer(attr, p, len) <0) { free(attr); return -1; }    break;  default:    /* just copy as is */    attr->pattr = NULL;    attr->enc_buf.size = len;    attr->enc_buf.data = (unsigned char *) malloc(len);    memcpy(attr->enc_buf.data, p, len);    break;  }  /* skip to end of list */  if(msg->stun_attr==NULL) {    msg->stun_attr = attr;  }  else {    next = msg->stun_attr;    while(next->next!=NULL) {      next = next->next;    }    next->next = attr;  }  return len+4;}int stun_parse_attr_address(stun_attr_t *attr, 			    const unsigned char *p, 			    unsigned len){  su_sockaddr_t *addr;  int addrlen;  char ipaddr[SU_ADDRSIZE + 2];  if (len != 8) {    return -1;  }  addrlen = sizeof(su_sockaddr_t);  addr = (su_sockaddr_t *) malloc(addrlen);  if (*(p+1) == 1) { /* expected value for IPv4 */    addr->su_sin.sin_family = AF_INET;  }  else {    free(addr);    return -1;  }  memcpy(&addr->su_sin.sin_port, p + 2, 2);  memcpy(&addr->su_sin.sin_addr.s_addr, p + 4, 4);  SU_DEBUG_5(("%s: address attribute: %s:%d\n", __func__,	      su_inet_ntop(addr->su_family, SU_ADDR(addr), ipaddr, sizeof(ipaddr)),	      (unsigned) ntohs(addr->su_sin.sin_port)));  attr->pattr = addr;  stun_init_buffer(&attr->enc_buf);  return 0;}int stun_parse_attr_error_code(stun_attr_t *attr, const unsigned char *p, unsigned len) {  uint32_t tmp;  stun_attr_errorcode_t *error;  memcpy(&tmp, p, sizeof(uint32_t));  tmp = ntohl(tmp);  error = (stun_attr_errorcode_t *) malloc(sizeof(*error));  error->code = (tmp & STUN_EC_CLASS)*100 + (tmp & STUN_EC_NUM);  error->phrase = (char *) malloc(len-3);  strncpy(error->phrase, (char*)p+4, len-4);  error->phrase[len - 4] = '\0';  attr->pattr = error;  stun_init_buffer(&attr->enc_buf);  return 0;}int stun_parse_attr_uint32(stun_attr_t *attr, const unsigned char *p, unsigned len){  uint32_t tmp;  stun_attr_changerequest_t *cr;  cr = (stun_attr_changerequest_t *) malloc(sizeof(*cr));  memcpy(&tmp, p, sizeof(uint32_t));  cr->value = ntohl(tmp);  attr->pattr = cr;  stun_init_buffer(&attr->enc_buf);  return 0;}int stun_parse_attr_buffer(stun_attr_t *attr, const unsigned char *p, unsigned len){  stun_buffer_t *buf;  buf = (stun_buffer_t *) malloc(sizeof(stun_buffer_t));  buf->size = len;  buf->data = (unsigned char *) malloc(len);  memcpy(buf->data, p, len);  attr->pattr = buf;  stun_init_buffer(&attr->enc_buf);  return 0;}int stun_parse_attr_unknown_attributes(stun_attr_t *attr,				       const unsigned char *p,				       unsigned len){  return 0;}/** scan thru attribute list and return the next requested attr */stun_attr_t *stun_get_attr(stun_attr_t *attr, uint16_t attr_type) {  stun_attr_t *p;  for (p = attr; p != NULL; p = p->next) {    if (p->attr_type == attr_type)      break;  }  return p;}void stun_init_buffer(stun_buffer_t *p) {  p->data = NULL;  p->size = 0;}int stun_free_buffer(stun_buffer_t *p) {  if (p->data)    free(p->data), p->data = NULL;  p->size = 0;  return 0;}int stun_copy_buffer(stun_buffer_t *p, stun_buffer_t *p2) {  stun_free_buffer(p); /* clean up existing data */  p->size = p2->size;  p->data = (unsigned char *) malloc(p->size);  memcpy(p->data, p2->data, p->size);  return p->size;}const char *stun_response_phrase(int status) {  if (status <100 || status >600)    return NULL;  switch (status) {  case STUN_400_BAD_REQUEST: return stun_400_Bad_request;  case STUN_401_UNAUTHORIZED: return stun_401_Unauthorized;  case STUN_420_UNKNOWN_ATTRIBUTE: return stun_420_Unknown_attribute;  case STUN_430_STALE_CREDENTIALS: return stun_430_Stale_credentials;  case STUN_431_INTEGRITY_CHECK_FAILURE: return stun_431_Integrity_check_failure;  case STUN_432_MISSING_USERNAME: return stun_432_Missing_username;  case STUN_433_USE_TLS: return stun_433_Use_tls;#ifdef USE_TURN  case TURN_MISSING_REALM: return turn_434_Missing_realm;  case TURN_MISSING_NONCE: return turn_435_Missing_nonce;  case TURN_UNKNOWN_USERNAME: return turn_436_Unknown_username;  case TURN_NO_BINDING: return turn_437_No_binding;  case TURN_ILLEGAL_PORT: return turn_439_Illegal_port;#endif  case STUN_500_SERVER_ERROR: return stun_500_Server_error;  case STUN_600_GLOBAL_FAILURE: return stun_600_Global_failure;  }  return "Response";}/** The set of functions encodes the corresponding attribute to *    network format, and save the result to the enc_buf. Return the *    size of the buffer. *//* This function is used to encode any attribute of the form ADDRESS   */int stun_encode_address(stun_attr_t *attr) {  stun_attr_sockaddr_t *a;  uint16_t tmp;  a = (stun_attr_sockaddr_t *)attr->pattr;  if (stun_encode_type_len(attr, 8) < 0) {    return -1;  }  tmp = htons(0x01); /* FAMILY = 0x01 */  memcpy(attr->enc_buf.data+4, &tmp, sizeof(tmp));  memcpy(attr->enc_buf.data+6, &a->sin_port, 2);  memcpy(attr->enc_buf.data+8, &a->sin_addr.s_addr, 4);  return attr->enc_buf.size;}int stun_encode_uint32(stun_attr_t *attr) {  uint32_t tmp;  if (stun_encode_type_len(attr, 4) < 0) {    return -1;  }  tmp = htonl(((stun_attr_changerequest_t *) attr->pattr)->value);  memcpy(attr->enc_buf.data+4, &tmp, 4);  return attr->enc_buf.size;}int stun_encode_error_code(stun_attr_t *attr) {  short int class, num;  size_t phrase_len, padded;  stun_attr_errorcode_t *error;  error = (stun_attr_errorcode_t *) attr->pattr;  class = error->code / 100;  num = error->code % 100;  phrase_len = strlen(error->phrase);  if (phrase_len + 8 > 65536)    phrase_len = 65536 - 8;  /* note: align the phrase len (see RFC3489:11.2.9) */  padded = phrase_len + (phrase_len % 4 == 0 ? 0 : 4 - (phrase_len % 4));  /* note: error-code has four octets of headers plus the    *       reason field -> len+4 octets */  if (stun_encode_type_len(attr, (uint16_t)(padded + 4)) < 0) {    return -1;  }  else {    assert(attr->enc_buf.size == padded + 8);    memset(attr->enc_buf.data+4, 0, 2);    attr->enc_buf.data[6] = class;    attr->enc_buf.data[7] = num;    /* note: 4 octets of TLV header and 4 octets of error-code header */    memcpy(attr->enc_buf.data+8, error->phrase, 	   phrase_len);    memset(attr->enc_buf.data + 8 + phrase_len, 0, padded - phrase_len);  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -