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

📄 isup.c

📁 asterisk1.4.6版本下 7#信令驱动 源码
💻 C
📖 第 1 页 / 共 2 页
字号:

  /* Two digits per byte, but only one digit in last byte if odd number of
     digits. */
  num_dig = (len - 2)*2 - (p[0] & 0x80 ? 1 : 0);

  i = 0;
  // Handle international number.
  nature_of_adr_ind = p[0] & 0x7f;
  switch(nature_of_adr_ind) {
    case 0x03:                  // National (significant) number.
      break;
    case 0x01:                  // Subscriber local number. Getting this has
      ast_log(LOG_NOTICE,"Subscriber local number nature of address "
              "indicator (%d), assuming Subscriber.\n", nature_of_adr_ind);                         // got to be wrong, but we've seen it 'in the
                                // wild' where they looked like international.
		break;
    case 0x02:                  // Unknown; again experience suggests
                                // this should be international.
      ast_log(LOG_NOTICE,"National (significant) or unknown nature of address "
              "indicator (%d), assuming international.\n", nature_of_adr_ind);
      // Intentionally fall-through.

    case 0x04:                  // International -> add '00'.
      num_dig++;
      n->num[i++] = '0';
      num_dig++;
      n->num[i++] = '0';
      break;
    default:
      ast_log(LOG_NOTICE, "unknown nature of address indicator 0x%0x.\n",
              nature_of_adr_ind);
      return 0;
  }

  if(num_dig > PHONENUM_MAX) {
    ast_log(LOG_NOTICE, "Too many digits in phone number %d > %d, truncated.\n",
            num_dig, PHONENUM_MAX);
    num_dig = PHONENUM_MAX;
  }

  j = 2;
  while(i < num_dig) {
    int dig = p[j] & 0x0f;
    if(dig == 0xf) {
      n->complete = 1;
      break;
    }
    n->num[i++] = digits[dig];
    if(i < num_dig) {
      int dig = (p[j++] >> 4) & 0xf;
      if(dig == 0xf) {
        n->complete = 1;
        break;
      }
      n->num[i++] = digits[dig];
    }
  }
  n->num[i] = '\0';

  return 1;
}

static int decode_dni(unsigned char *p, int len, void *data) {
  return decode_isup_phonenum(0, p, len, data);
}

static int decode_sni(unsigned char *p, int len, void *data) {
  return decode_isup_sni(p, len, data);
}

static int decode_ani_rni(unsigned char *p, int len, void *data) {
  return decode_isup_phonenum(1, p, len, data);
}

/* Decode raw SIF field into ISUP message.
   Returns true on success, false on error. */	/* by lin.miao@openvox.cn */
int decode_isup_msg(struct isup_msg *msg, ss7_variant variant, unsigned char *buf, int len) {
  
  int i;
  memset(msg, 0, sizeof(*msg));
  
  if(variant==ITU_SS7) 	/* by lin.miao@openvox.cn */
  	i = 7;
  else
  	i =10;
  
  if(len < i) {
    ast_log(LOG_NOTICE, "Got short ISUP message (len=%d < %d).\n", len, i);
    return 0;
  }

  if(variant==ITU_SS7) {	/* by lin.miao@openvox.cn */
    msg->dpc = buf[0] | ((buf[1] & 0x3f) << 8);
    msg->opc = ((buf[1] & 0xc0) >> 6) | (buf[2] << 2) | ((buf[3] & 0x0f) << 10);
    msg->sls = (buf[3] & 0xf0) >> 4;

    msg->cic = buf[4] | ((buf[5] & 0x0f) << 8);
    msg->typ = buf[6];
    buf += 7;
    len -= 7;
  } else {	/* CHINA SS7 */  /* by lin.miao@openvox.cn */
    msg->dpc = buf[0] | ((buf[1] & 0xff) << 8) | ((buf[2] & 0xff) << 16);
    msg->opc = buf[3] | ((buf[4] & 0xff) << 8) | ((buf[5] & 0xff) << 16);
    msg->sls = buf[6] & 0x0f;

    msg->cic = buf[7] | ((buf[8] & 0x0f) << 8);
    msg->typ = buf[9];

    buf += 10;
    len -= 10;
  }

  switch(msg->typ) {
    case ISUP_IAM:
      /* Must initialize optional parameters, in case they are no
         present in message. */
      ast_log(LOG_DEBUG,"decode_isup_msg=============IS %s,%s.\n",msg->iam.ani.num,msg->iam.dni.num);
      clear_isup_phonenum(&msg->iam.ani);
      clear_isup_phonenum(&msg->iam.rni);
      msg->iam.redir_inf.is_redirect = 0;
      msg->iam.redir_inf.reason = 0;
      return param_decode(buf, len,
                          IP_NATURE_OF_CONNECTION_INDICATORS, 1, decode_noci_contcheck, &msg->iam,
                          IP_FORWARD_CALL_INDICATORS, 2, NULL, NULL,
                          IP_CALLING_PARTYS_CATEGORY, 1, NULL, NULL,
                          IP_TRANSMISSION_MEDIUM_REQUIREMENT, 1, decode_transmission_medium, &msg->iam,
                          0,
                          IP_CALLED_PARTY_NUMBER, decode_dni, &msg->iam.dni,
                          0,
                          IP_CALLING_PARTY_NUMBER, decode_ani_rni, &msg->iam.ani,
                          IP_REDIRECTING_NUMBER, decode_ani_rni, &msg->iam.rni,
                          IP_REDIRECTION_INFORMATION, decode_redir_inf, &msg->iam.redir_inf,
                          0);

    case ISUP_SAM:
      /* Must initialize optional parameters, in case they are not
	 present in message. */
      clear_isup_phonenum(&msg->sam.sni);
      return param_decode(buf, len,
			  0,
			  IP_SUBSEQUENT_NUMBER, decode_sni, &msg->sam.sni,
			  0,
			  0);

    case ISUP_ACM:
      return param_decode(buf, len,
                          IP_BACKWARD_CALL_INDICATORS, 2, decode_backwards_ind, &(msg->acm.back_ind),
                          0,
                          0,
			  IP_OPTIONAL_BACKWARD_CALL_INDICATORS, decode_optional_backward_call_indicators, &(msg->acm.obc_ind),
                          0);

    case ISUP_BLK:
      return param_decode(buf, len,
                          0,
                          0,
                          0);

    case ISUP_BLA:
      return param_decode(buf, len,
                          0,
                          0,
                          0);

    case ISUP_CON:
      return param_decode(buf, len,
                          IP_BACKWARD_CALL_INDICATORS, 2, decode_backwards_ind, &(msg->con.back_ind),
                          0,
                          0,
			  IP_OPTIONAL_BACKWARD_CALL_INDICATORS, decode_optional_backward_call_indicators, &(msg->anm.obc_ind),
                          0);

    case ISUP_ANM:
      return param_decode(buf, len,
                          0,
                          0,
                          IP_BACKWARD_CALL_INDICATORS, NULL, NULL,
			  IP_OPTIONAL_BACKWARD_CALL_INDICATORS, decode_optional_backward_call_indicators, &(msg->anm.obc_ind),
                          0);

    case ISUP_REL:
      return param_decode(buf, len,
                          0,
                          IP_CAUSE_INDICATORS, decode_rel_cause, &(msg->rel.cause),
                          0,
                          0);

    case ISUP_RLC:
      return param_decode(buf, len,
                          0,
                          0,
                          IP_CAUSE_INDICATORS, NULL, NULL,
                          0);

    case ISUP_SUS:
      return param_decode(buf, len,
                          IP_SUSPEND_RESUME_INDICATORS, 1, decode_suspend_resume, &(msg->sus.indicator),
                          0,
                          0,
                          0);

    case ISUP_RES:
      return param_decode(buf, len,
                          IP_SUSPEND_RESUME_INDICATORS, 1, decode_suspend_resume, &(msg->sus.indicator),
                          0,
                          0,
                          0);

    case ISUP_RSC:
      return param_decode(buf, len,
                          0,
                          0,
                          0);

    case ISUP_GRS:
      return param_decode(buf, len,
                          0,    /* End of mandatory fixed part */
                          IP_RANGE_AND_STATUS, decode_range_no_status, &(msg->grs.range),
                          0,    /* End of mandatory variable part */
                          0);   /* End of optional part */

    case ISUP_GRA:
      return param_decode(buf, len,
                          0,
                          IP_RANGE_AND_STATUS, decode_range_and_status, &(msg->gra.range_status),
                          0,
                          0);

    case ISUP_CGB:
      return param_decode(buf, len,
                          IP_CIRCUIT_GROUP_SUPERVISION_MESSAGE_TYPE_INDICATOR, 1, decode_cgsmti, &(msg->cgb.cgsmti),
                          0,
                          IP_RANGE_AND_STATUS, decode_range_and_status, &(msg->cgb.range_status),
                          0,
                          0);

    case ISUP_CGA:
      return param_decode(buf, len,
                          IP_CIRCUIT_GROUP_SUPERVISION_MESSAGE_TYPE_INDICATOR, 1, decode_cgsmti, &(msg->cgb.cgsmti),
                          0,
                          IP_RANGE_AND_STATUS, decode_range_and_status, &(msg->cgb.range_status),
                          0,
                          0);

    case ISUP_CGU:
      return param_decode(buf, len,
                          IP_CIRCUIT_GROUP_SUPERVISION_MESSAGE_TYPE_INDICATOR, 1, decode_cgsmti, &(msg->cgu.cgsmti),
                          0,
                          IP_RANGE_AND_STATUS, decode_range_and_status, &(msg->cgu.range_status),
                          0,
                          0);

    case ISUP_CUA:
      return param_decode(buf, len,
                          IP_CIRCUIT_GROUP_SUPERVISION_MESSAGE_TYPE_INDICATOR, 1, decode_cgsmti, &(msg->cua.cgsmti),
                          0,
                          IP_RANGE_AND_STATUS, decode_range_and_status, &(msg->cua.range_status),
                          0,
                          0);

    case ISUP_CPR:
      return param_decode(buf, len,
                          IP_EVENT_INFORMATION, 1, decode_event_info, &(msg->cpr.event_info),
                          0,
                          0,
			  IP_OPTIONAL_BACKWARD_CALL_INDICATORS, decode_optional_backward_call_indicators, &(msg->cpr.obc_ind),
                          0);

    case ISUP_UBL:
      return param_decode(buf, len,
                          0,
                          0,
                          0);

    case ISUP_UEC:
      return param_decode(buf, len,
                          0,
                          0,
                          0);

    case ISUP_CCR:
      return param_decode(buf, len,
                          0,
                          0,
                          0);

    case ISUP_COT:
      return param_decode(buf, len,
                          0,
                          0,
                          0);

    default:
      ast_log(LOG_DEBUG, "Got unknown ISUP message type %d.\n", msg->typ);
      return 0;
  }
}

/* by lin.miao@openvox.cn */
void isup_msg_init(unsigned char *buf, int buflen, ss7_variant variant, int opc, int dpc, int cic,
                   enum isup_msg_type msg_type, int *current) {
  if(buflen < 7) {
    ast_log(LOG_ERROR, "Buffer too small, size %d < 7.\n", buflen);
    return;
  }

  *current = 0;
  mtp3_put_label((cic & 0x000f), variant, opc, dpc, &(buf[*current]));	/* by lin.miao@openvox.cn */
  if(variant==ITU_SS7) {	/* by lin.miao@openvox.cn */
    *current += 4;
    buf[(*current)++] = cic & 0xff;
    buf[(*current)++] = (cic & 0x0f00) >> 8;
    buf[(*current)++] = msg_type;
  } else { /* CHINA SS7 */	/* by lin.miao@openvox.cn */
    *current += 7;
    buf[(*current)++] = cic & 0xff;
    buf[(*current)++] = (cic & 0x0f00) >> 8;
    buf[(*current)++] = msg_type;
  }
}

void isup_msg_add_fixed(unsigned char *buf, int buflen, int *current,
                        unsigned char *param, int param_len) {
  if(param_len < 0 || param_len > 255) {
    ast_log(LOG_ERROR, "Unreasonable size of parameter %d.\n", param_len);
    return;
  }
  if(*current + param_len > buflen) {
    ast_log(LOG_ERROR, "Buffer too small for fixed parameter, size "
            "%d < %d.\n", buflen, *current + param_len);
    return;
  }
  memcpy(&(buf[*current]), param, param_len);
  *current += param_len;
}

void isup_msg_start_variable_part(unsigned char *buf, int buflen,
                                  int *variable_ptr, int *current,
                                  int num_variable, int optional) {
  int needed_size = num_variable + (optional ? 1 : 0);
  if(*current + needed_size > buflen) {
    ast_log(LOG_ERROR, "Buffer too small for variable part of ISUP message, "
            "size %d < %d.\n", buflen, *current + needed_size);
    return;
  }
  *variable_ptr = *current;
  memset(&(buf[*current]), 0, needed_size);
  *current += needed_size;
}

/* The value to be passed for VARIABLE_PTR is initalized by the call
   to isup_msg_start_variable_part(). */
void isup_msg_add_variable(unsigned char *buf, int buflen, int *variable_ptr,
                           int *current, unsigned char *param, int param_len) {
  if(param_len < 0 || param_len > 255) {
    ast_log(LOG_ERROR, "Unreasonable size of parameter length %d.\n", param_len);
    return;
  }
  if(*variable_ptr >= *current) {
    ast_log(LOG_ERROR, "Internal: variable_ptr=%d >= current=%d.\n",
            *variable_ptr, *current);
    return;
  }
  if(*current + 1 + param_len > buflen) {
    ast_log(LOG_ERROR, "Buffer too small for variable parameter, size "
            "%d < %d.\n", buflen, *current + 1 + param_len);
    return;
  }
  if(*current - *variable_ptr > 255) {
    ast_log(LOG_ERROR, "Too much data in variable part, %d > 255.\n",
            *current - *variable_ptr);
    return;
  }

  buf[*variable_ptr] = *current - *variable_ptr;
  (*variable_ptr)++;
  buf[(*current)++] = param_len;
  memcpy(&(buf[*current]), param, param_len);
  *current += param_len;
}

/* Only call this if there will follow calls to isup_msg_add_optional().
   If optional parameters are allowed for the message type, but none will be
   included in this particular message, pass 1 for OPTIONAL in the call to
   isup_msg_start_variable_part(), but do not call isup_msg_start_optional_part().
*/
void isup_msg_start_optional_part(unsigned char *buf, int buflen, int *variable_ptr,
                                int *current) {
  if(*variable_ptr >= *current) {
    ast_log(LOG_ERROR, "Internal: variable_ptr=%d >= current=%d.\n",
            *variable_ptr, *current);
    return;
  }
  if(*current + 1 > buflen) {   /* The "+1" is room for the end marker */
    ast_log(LOG_ERROR, "Buffer too small for optional parameter, size "
            "%d < %d.\n", buflen, *current + 1);
    return;
  }
  if(*current - *variable_ptr > 255) {
    ast_log(LOG_ERROR, "Too much data in variable part, %d > 255.\n",
            *current - *variable_ptr);
    return;
  }

  buf[*variable_ptr] = *current - *variable_ptr;
  (*variable_ptr)++;
}

void isup_msg_add_optional(unsigned char *buf, int buflen, int *current,
                           enum isup_parameter_code param_type,
                           unsigned char *param, int param_len) {
  if(param_len < 0 || param_len > 255) {
    ast_log(LOG_ERROR, "Unreasonable size of parameter length %d.\n", param_len);
    return;
  }
  if(*current + 2 + param_len > buflen) {
    ast_log(LOG_ERROR, "Buffer too small for optional parameter, "
            "size %d < %d.\n", buflen, *current + 2 + param_len);
    return;
  }

  buf[(*current)++] = param_type;
  buf[(*current)++] = param_len;
  memcpy(&(buf[*current]), param, param_len);
  *current += param_len;
}

/* Only call this if at least one optional parameter was added. */
void isup_msg_end_optional_part(unsigned char *buf, int buflen, int *current) {
  if(*current + 1 > buflen) {
    ast_log(LOG_ERROR, "Buffer too small for optional parameter end marker, "
            "size %d < %d.\n", buflen, *current + 1);
    return;
  }

  buf[(*current)++] = 0;
}

char* isupmsg(int typ)
{
  switch (typ) {
  case ISUP_IAM: return "IAM";
  case ISUP_SAM: return "SAM";
  case ISUP_INR: return "INR";
  case ISUP_COT: return "COT";
  case ISUP_ACM: return "ACM";
  case ISUP_CON: return "CON";
  case ISUP_ANM: return "ANM";
  case ISUP_REL: return "REL";
  case ISUP_SUS: return "SUS";
  case ISUP_RES: return "RES";
  case ISUP_RLC: return "RLC";
  case ISUP_CCR: return "CCR";
  case ISUP_RSC: return "RSC";
  case ISUP_BLK: return "BLK";
  case ISUP_UBL: return "UBL";
  case ISUP_BLA: return "BLA";
  case ISUP_UBA: return "UBA";
  case ISUP_GRS: return "GRS";
  case ISUP_CGB: return "CGB";
  case ISUP_CGU: return "CGU";
  case ISUP_CGA: return "CGA";
  case ISUP_CUA: return "CUA";
  case ISUP_GRA: return "GRA";
  case ISUP_CPR: return "CPR";
  case ISUP_UEC: return "UEC";
  default: {
    /* This is non reentrant! */
    static char buf[30];
    sprintf(buf, "unknown(%d)", typ);
    return buf;
  }
  }
}

⌨️ 快捷键说明

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