📄 pri_facility.c
字号:
/* * libpri: An implementation of Primary Rate ISDN * * Written by Matthew Fredrickson <creslin@digium.com> * * Copyright (C) 2004-2005, Digium, Inc. * All Rights Reserved. *//* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. * * In addition, when this program is distributed with Asterisk in * any form that would qualify as a 'combined work' or as a * 'derivative work' (but not mere aggregation), you can redistribute * and/or modify the combination under the terms of the license * provided with that copy of Asterisk, instead of the license * terms granted here. */#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; /* Numbering Plan Indicator */ int ton; /* Type Of Number */ int pres; /* Presentation */};struct addressingdataelements_presentednumberscreened { char partyaddress[21]; char partysubaddress[21]; int npi; /* Numbering Plan Indicator */ int ton; /* Type Of Number */ int pres; /* Presentation */ int scrind; /* Screening Indicator */};#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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -