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

📄 pri_facility.c

📁 Q921的LINUX下的驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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 + -