📄 isup.c
字号:
/* 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 + -