📄 isup.c
字号:
ast_log(LOG_ERROR, "This cannot happen!?!.\n"); } } else { n->present = 1; n->restricted = 0; n->complete = 0; } memset(n->num, 0, sizeof(n->num)); if(len == 2) { ast_log(LOG_DEBUG, "No digits in phone number.\n"); return 1; } /* 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 // got to be wrong, but we've seen it 'in the // wild' where they looked like international. 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. */int decode_isup_msg(struct isup_msg *msg, unsigned char *buf, int len) { memset(msg, 0, sizeof(*msg)); if(len < 7) { ast_log(LOG_NOTICE, "Got short ISUP message (len=%d < 7).\n", len); return 0; } 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; switch(msg->typ) { case ISUP_IAM: /* Must initialize optional parameters, in case they are no present in message. */ 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, NULL, NULL, 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; }}void isup_msg_init(unsigned char *buf, int buflen, 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), opc, dpc, &(buf[*current])); *current += 4; 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 + -