📄 pri_facility.c
字号:
/* * libpri: An implementation of Primary Rate ISDN * * Written by Matthew Fredrickson <creslin@digium.com> * * Copyright (C) 2004-2005, Digium * All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "compat.h"#include "libpri.h"#include "pri_internal.h"#include "pri_q921.h"#include "pri_q931.h"#include "pri_facility.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <limits.h>static char *asn1id2text(int id){ static char data[32]; static char *strings[] = { "none", "Boolean", "Integer", "Bit String", "Octet String", "NULL", "Object Identifier", "Object Descriptor", "External Reference", "Real Number", "Enumerated", "Embedded PDV", "UTF-8 String", "Relative Object ID", "Reserved (0e)", "Reserved (0f)", "Sequence", "Set", "Numeric String", "Printable String", "Tele-Text String", "IA-5 String", "UTC Time", "Generalized Time", }; if (id > 0 && id <= 0x18) { return strings[id]; } else { sprintf(data, "Unknown (%02x)", id); return data; }}static int asn1_dumprecursive(struct pri *pri, void *comp_ptr, int len, int level){ unsigned char *vdata = (unsigned char *)comp_ptr; struct rose_component *comp; int i = 0; int j, k, l; int clen = 0; while (len > 0) { GET_COMPONENT(comp, i, vdata, len); pri_message(pri, "%*s%02X %04X", 2 * level, "", comp->type, comp->len); if ((comp->type == 0) && (comp->len == 0)) return clen + 2; if ((comp->type & ASN1_PC_MASK) == ASN1_PRIMITIVE) { for (j = 0; j < comp->len; ++j) pri_message(pri, " %02X", comp->data[j]); } if ((comp->type & ASN1_CLAN_MASK) == ASN1_UNIVERSAL) { switch (comp->type & ASN1_TYPE_MASK) { case 0: pri_message(pri, " (none)"); break; case ASN1_BOOLEAN: pri_message(pri, " (BOOLEAN: %d)", comp->data[0]); break; case ASN1_INTEGER: for (k = l = 0; k < comp->len; ++k) l = (l << 8) | comp->data[k]; pri_message(pri, " (INTEGER: %d)", l); break; case ASN1_BITSTRING: pri_message(pri, " (BITSTRING:"); for (k = 0; k < comp->len; ++k) pri_message(pri, " %02x", comp->data[k]); pri_message(pri, ")"); break; case ASN1_OCTETSTRING: pri_message(pri, " (OCTETSTRING:"); for (k = 0; k < comp->len; ++k) pri_message(pri, " %02x", comp->data[k]); pri_message(pri, ")"); break; case ASN1_NULL: pri_message(pri, " (NULL)"); break; case ASN1_OBJECTIDENTIFIER: pri_message(pri, " (OBJECTIDENTIFIER:"); for (k = 0; k < comp->len; ++k) pri_message(pri, " %02x", comp->data[k]); pri_message(pri, ")"); break; case ASN1_ENUMERATED: for (k = l = 0; k < comp->len; ++k) l = (l << 8) | comp->data[k]; pri_message(pri, " (ENUMERATED: %d)", l); break; case ASN1_SEQUENCE: pri_message(pri, " (SEQUENCE)"); break; default: pri_message(pri, " (component %02x - %s)", comp->type, asn1id2text(comp->type & ASN1_TYPE_MASK)); break; } } else if ((comp->type & ASN1_CLAN_MASK) == ASN1_CONTEXT_SPECIFIC) { pri_message(pri, " (CONTEXT SPECIFIC [%d])", comp->type & ASN1_TYPE_MASK); } else { pri_message(pri, " (component %02x)", comp->type); } pri_message(pri, "\n"); if ((comp->type & ASN1_PC_MASK) == ASN1_CONSTRUCTOR) j = asn1_dumprecursive(pri, comp->data, (comp->len ? comp->len : INT_MAX), level+1); else j = comp->len; j += 2; len -= j; vdata += j; clen += j; } return clen;}int asn1_dump(struct pri *pri, void *comp, int len){ return asn1_dumprecursive(pri, comp, len, 0);}static unsigned char get_invokeid(struct pri *pri){ return ++pri->last_invoke;}struct addressingdataelements_presentednumberunscreened { char partyaddress[21]; char partysubaddress[21]; int npi; int ton; int pres;};#define PRI_CHECKOVERFLOW(size) \ if (msgptr - message + (size) >= sizeof(message)) { \ *msgptr = '\0'; \ pri_message(pri, "%s", message); \ msgptr = message; \ }static void dump_apdu(struct pri *pri, unsigned char *c, int len) { #define MAX_APDU_LENGTH 255 static char hexs[16] = "0123456789ABCDEF"; int i; char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; /* please adjust here, if you make changes below! */ char *msgptr; msgptr = message; *msgptr++ = ' '; *msgptr++ = '['; for (i=0; i<len; i++) { PRI_CHECKOVERFLOW(3); *msgptr++ = ' '; *msgptr++ = hexs[(c[i] >> 4) & 0x0f]; *msgptr++ = hexs[(c[i]) & 0x0f]; } PRI_CHECKOVERFLOW(6); strcpy(msgptr, " ] - ["); msgptr += strlen(msgptr); for (i=0; i<len; i++) { PRI_CHECKOVERFLOW(1); *msgptr++ = ((c[i] < ' ') || (c[i] > '~')) ? '.' : c[i]; } PRI_CHECKOVERFLOW(2); *msgptr++ = ']'; *msgptr++ = '\n'; *msgptr = '\0'; pri_message(pri, "%s", message);}#undef PRI_CHECKOVERFLOWint redirectingreason_from_q931(struct pri *pri, int redirectingreason){ switch(pri->switchtype) { case PRI_SWITCH_QSIG: switch(redirectingreason) { case PRI_REDIR_UNKNOWN: return QSIG_DIVERT_REASON_UNKNOWN; case PRI_REDIR_FORWARD_ON_BUSY: return QSIG_DIVERT_REASON_CFB; case PRI_REDIR_FORWARD_ON_NO_REPLY: return QSIG_DIVERT_REASON_CFNR; case PRI_REDIR_UNCONDITIONAL: return QSIG_DIVERT_REASON_CFU; case PRI_REDIR_DEFLECTION: case PRI_REDIR_DTE_OUT_OF_ORDER: case PRI_REDIR_FORWARDED_BY_DTE: pri_message(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n", redirectingreason); /* Fall through */ default: return QSIG_DIVERT_REASON_UNKNOWN; } default: switch(redirectingreason) { case PRI_REDIR_UNKNOWN: return Q952_DIVERT_REASON_UNKNOWN; case PRI_REDIR_FORWARD_ON_BUSY: return Q952_DIVERT_REASON_CFB; case PRI_REDIR_FORWARD_ON_NO_REPLY: return Q952_DIVERT_REASON_CFNR; case PRI_REDIR_DEFLECTION: return Q952_DIVERT_REASON_CD; case PRI_REDIR_UNCONDITIONAL: return Q952_DIVERT_REASON_CFU; case PRI_REDIR_DTE_OUT_OF_ORDER: case PRI_REDIR_FORWARDED_BY_DTE: pri_message(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.952\n", redirectingreason); /* Fall through */ default: return Q952_DIVERT_REASON_UNKNOWN; } }}static int redirectingreason_for_q931(struct pri *pri, int redirectingreason){ switch(pri->switchtype) { case PRI_SWITCH_QSIG: switch(redirectingreason) { case QSIG_DIVERT_REASON_UNKNOWN: return PRI_REDIR_UNKNOWN; case QSIG_DIVERT_REASON_CFU: return PRI_REDIR_UNCONDITIONAL; case QSIG_DIVERT_REASON_CFB: return PRI_REDIR_FORWARD_ON_BUSY; case QSIG_DIVERT_REASON_CFNR: return PRI_REDIR_FORWARD_ON_NO_REPLY; default: pri_message(pri, "!! Unknown Q.SIG diversion reason %d\n", redirectingreason); return PRI_REDIR_UNKNOWN; } default: switch(redirectingreason) { case Q952_DIVERT_REASON_UNKNOWN: return PRI_REDIR_UNKNOWN; case Q952_DIVERT_REASON_CFU: return PRI_REDIR_UNCONDITIONAL; case Q952_DIVERT_REASON_CFB: return PRI_REDIR_FORWARD_ON_BUSY; case Q952_DIVERT_REASON_CFNR: return PRI_REDIR_FORWARD_ON_NO_REPLY; case Q952_DIVERT_REASON_CD: return PRI_REDIR_DEFLECTION; case Q952_DIVERT_REASON_IMMEDIATE: pri_message(pri, "!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n"); return PRI_REDIR_UNKNOWN; /* ??? */ default: pri_message(pri, "!! Unknown Q.952 diversion reason %d\n", redirectingreason); return PRI_REDIR_UNKNOWN; } }}int typeofnumber_from_q931(struct pri *pri, int ton){ switch(ton) { case PRI_TON_INTERNATIONAL: return Q932_TON_INTERNATIONAL; case PRI_TON_NATIONAL: return Q932_TON_NATIONAL; case PRI_TON_NET_SPECIFIC: return Q932_TON_NET_SPECIFIC; case PRI_TON_SUBSCRIBER: return Q932_TON_SUBSCRIBER; case PRI_TON_ABBREVIATED: return Q932_TON_ABBREVIATED; case PRI_TON_RESERVED: default: pri_message(pri, "!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton); /* fall through */ case PRI_TON_UNKNOWN: return Q932_TON_UNKNOWN; }}static int typeofnumber_for_q931(struct pri *pri, int ton){ switch (ton) { case Q932_TON_UNKNOWN: return PRI_TON_UNKNOWN; case Q932_TON_INTERNATIONAL: return PRI_TON_INTERNATIONAL; case Q932_TON_NATIONAL: return PRI_TON_NATIONAL; case Q932_TON_NET_SPECIFIC: return PRI_TON_NET_SPECIFIC; case Q932_TON_SUBSCRIBER: return PRI_TON_SUBSCRIBER; case Q932_TON_ABBREVIATED: return PRI_TON_ABBREVIATED; default: pri_message(pri, "!! Invalid Q.932 TypeOfNumber %d\n", ton); return PRI_TON_UNKNOWN; }}int asn1_name_decode(void * data, int len, char *namebuf, int buflen){ struct rose_component *comp = (struct rose_component*)data; int datalen = 0, res = 0; if (comp->len == ASN1_LEN_INDEF) { datalen = strlen((char *)comp->data); res = datalen + 2; } else datalen = res = comp->len; if (datalen > buflen) { /* Truncate */ datalen = buflen; } memcpy(namebuf, comp->data, datalen); return res + 2;}int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len){ struct rose_component *comp = NULL; if (len < 2 + src_len) return -1; if (max_len && (src_len > max_len)) src_len = max_len; comp = (struct rose_component *)data; comp->type = asn1_type; comp->len = src_len; memcpy(comp->data, src, src_len); return 2 + src_len;}int asn1_copy_string(char * buf, int buflen, struct rose_component *comp){ int res; int datalen; if ((comp->len > buflen) && (comp->len != ASN1_LEN_INDEF)) return -1; if (comp->len == ASN1_LEN_INDEF) { datalen = strlen((char*)comp->data); res = datalen + 2; } else res = datalen = comp->len; memcpy(buf, comp->data, datalen); buf[datalen] = 0; return res;}static int rose_number_digits_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value){ int i = 0; struct rose_component *comp = NULL; unsigned char *vdata = data; int datalen = 0; int res = 0; do { GET_COMPONENT(comp, i, vdata, len); CHECK_COMPONENT(comp, ASN1_NUMERICSTRING, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n"); if(comp->len > 20 && comp->len != ASN1_LEN_INDEF) { pri_message(pri, "!! Oversized NumberDigits component (%d)\n", comp->len); return -1; } if (comp->len == ASN1_LEN_INDEF) { datalen = strlen((char *)comp->data); res = datalen + 2; } else res = datalen = comp->len; memcpy(value->partyaddress, comp->data, datalen); value->partyaddress[datalen] = '\0'; return res + 2; } while(0); return -1;}static int rose_public_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value){ int i = 0; struct rose_component *comp = NULL; unsigned char *vdata = data; int ton; int res = 0; if (len < 2) return -1; do { GET_COMPONENT(comp, i, vdata, len); CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n"); ASN1_GET_INTEGER(comp, ton);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -