mirror of https://github.com/asterisk/asterisk
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39807 65c4cc65-6c06-0410-ace0-fbb531ad65f31.4
parent
e648f4ddb4
commit
0b579cf152
@ -1,181 +0,0 @@
|
||||
|
||||
#include "asn1.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
** ASN.1 Encoding
|
||||
*/
|
||||
|
||||
int _enc_null (__u8 *dest, int tag)
|
||||
{
|
||||
dest[0] = tag;
|
||||
dest[1] = 0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
int _enc_bool (__u8 *dest, __u32 i, int tag)
|
||||
{
|
||||
dest[0] = tag;
|
||||
dest[1] = 1;
|
||||
dest[2] = i ? 1:0;
|
||||
return 3;
|
||||
}
|
||||
|
||||
int _enc_int (__u8 *dest, __u32 i, int tag)
|
||||
{
|
||||
__u8 *p;
|
||||
dest[0] = tag;
|
||||
p = &dest[2];
|
||||
do {
|
||||
*p++ = i;
|
||||
i >>= 8;
|
||||
} while (i);
|
||||
dest[1] = p - &dest[2];
|
||||
return p - dest;
|
||||
}
|
||||
|
||||
int _enc_enum (__u8 *dest, __u32 i, int tag)
|
||||
{
|
||||
__u8 *p;
|
||||
|
||||
dest[0] = tag;
|
||||
p = &dest[2];
|
||||
do {
|
||||
*p++ = i;
|
||||
i >>= 8;
|
||||
} while (i);
|
||||
dest[1] = p - &dest[2];
|
||||
return p - dest;
|
||||
}
|
||||
|
||||
int _enc_num_string (__u8 *dest, char *nd, __u8 len, int tag)
|
||||
{
|
||||
__u8 *p;
|
||||
int i;
|
||||
|
||||
dest[0] = tag;
|
||||
p = &dest[2];
|
||||
for (i = 0; i < len; i++)
|
||||
*p++ = *nd++;
|
||||
dest[1] = p - &dest[2];
|
||||
return p - dest;
|
||||
}
|
||||
|
||||
int _enc_sequence_start (__u8 *dest, __u8 **id, int tag)
|
||||
{
|
||||
dest[0] = tag;
|
||||
*id = &dest[1];
|
||||
return 2;
|
||||
}
|
||||
|
||||
int _enc_sequence_end (__u8 *dest, __u8 *id, int tag_dummy)
|
||||
{
|
||||
*id = dest - id - 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** ASN.1 Decoding
|
||||
*/
|
||||
|
||||
#define CHECK_P \
|
||||
do { \
|
||||
if (p >= end) \
|
||||
return -1; \
|
||||
} while (0)
|
||||
|
||||
#define CallASN1(ret, p, end, todo) \
|
||||
do { \
|
||||
ret = todo; \
|
||||
if (ret < 0) { \
|
||||
return -1; \
|
||||
} \
|
||||
p += ret; \
|
||||
} while (0)
|
||||
|
||||
#define INIT \
|
||||
int len, ret; \
|
||||
__u8 *begin = p; \
|
||||
if (tag) \
|
||||
*tag = *p; \
|
||||
p++; \
|
||||
CallASN1(ret, p, end, dec_len(p, &len)); \
|
||||
if (len >= 0) { \
|
||||
if (p + len > end) \
|
||||
return -1; \
|
||||
end = p + len; \
|
||||
}
|
||||
|
||||
int _dec_null (__u8 *p, __u8 *end, int *tag)
|
||||
{
|
||||
INIT;
|
||||
return p - begin;
|
||||
}
|
||||
|
||||
int _dec_bool (__u8 *p, __u8 *end, int *i, int *tag)
|
||||
{
|
||||
INIT;
|
||||
*i = 0;
|
||||
while (len--) {
|
||||
CHECK_P;
|
||||
*i = (*i >> 8) + *p;
|
||||
p++;
|
||||
}
|
||||
return p - begin;
|
||||
}
|
||||
|
||||
int _dec_int (__u8 *p, __u8 *end, int *i, int *tag)
|
||||
{
|
||||
INIT;
|
||||
|
||||
*i = 0;
|
||||
while (len--) {
|
||||
CHECK_P;
|
||||
*i = (*i << 8) + *p;
|
||||
p++;
|
||||
}
|
||||
return p - begin;
|
||||
}
|
||||
|
||||
int _dec_enum (__u8 *p, __u8 *end, int *i, int *tag)
|
||||
{
|
||||
INIT;
|
||||
|
||||
*i = 0;
|
||||
while (len--) {
|
||||
CHECK_P;
|
||||
*i = (*i << 8) + *p;
|
||||
p++;
|
||||
}
|
||||
return p - begin;
|
||||
}
|
||||
|
||||
int _dec_num_string (__u8 *p, __u8 *end, char *str, int *tag)
|
||||
{
|
||||
INIT;
|
||||
|
||||
while (len--) {
|
||||
CHECK_P;
|
||||
*str++ = *p;
|
||||
p++;
|
||||
}
|
||||
*str = 0;
|
||||
return p - begin;
|
||||
}
|
||||
|
||||
int _dec_octet_string (__u8 *p, __u8 *end, char *str, int *tag)
|
||||
{
|
||||
return _dec_num_string(p, end, str, tag);
|
||||
}
|
||||
|
||||
int _dec_sequence (__u8 *p, __u8 *end, int *tag)
|
||||
{
|
||||
INIT;
|
||||
return p - begin;
|
||||
}
|
||||
|
||||
int dec_len (__u8 *p, int *len)
|
||||
{
|
||||
*len = *p;
|
||||
return 1;
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
#ifndef __ASN1_H__
|
||||
#define __ASN1_H__
|
||||
|
||||
#include <asm/types.h>
|
||||
|
||||
/*
|
||||
** ASN.1 Tags
|
||||
*/
|
||||
|
||||
#define ASN1_TAG_BOOLEAN (0x01)
|
||||
#define ASN1_TAG_INTEGER (0x02)
|
||||
#define ASN1_TAG_BIT_STRING (0x03)
|
||||
#define ASN1_TAG_OCTET_STRING (0x04)
|
||||
#define ASN1_TAG_NULL (0x05)
|
||||
#define ASN1_TAG_OBJECT_IDENTIFIER (0x06)
|
||||
#define ASN1_TAG_ENUM (0x0a)
|
||||
#define ASN1_TAG_SEQUENCE (0x30)
|
||||
#define ASN1_TAG_SET (0x31)
|
||||
#define ASN1_TAG_NUMERIC_STRING (0x12)
|
||||
#define ASN1_TAG_PRINTABLE_STRING (0x13)
|
||||
#define ASN1_TAG_IA5_STRING (0x16)
|
||||
#define ASN1_TAG_UTC_TIME (0x17)
|
||||
#define ASN1_TAG_CONSTRUCTED (0x20)
|
||||
#define ASN1_TAG_CONTEXT_SPECIFIC (0x80)
|
||||
#define ASN1_TAG_EXPLICIT (0x100)
|
||||
#define ASN1_TAG_OPT (0x200)
|
||||
#define ASN1_NOT_TAGGED (0x400)
|
||||
|
||||
/*
|
||||
** ASN.1 Encoding
|
||||
*/
|
||||
|
||||
#define enc_null(dest) _enc_null(dest,ASN1_TAG_NULL)
|
||||
#define enc_bool(dest,i) _enc_bool(dest,i,ASN1_TAG_BOOLEAN)
|
||||
#define enc_int(dest,i) _enc_int(dest,i,ASN1_TAG_INTEGER)
|
||||
#define enc_enum(dest,i) _enc_enum(dest,i,ASN1_TAG_ENUM)
|
||||
#define enc_num_string(dest,num,len) _enc_num_string(dest,num,len,ASN1_TAG_NUMERIC_STRING)
|
||||
#define enc_sequence_start(dest,id) _enc_sequence_start(dest,id,ASN1_TAG_SEQUENCE)
|
||||
#define enc_sequence_end(dest,id) _enc_sequence_end(dest,id,ASN1_TAG_SEQUENCE)
|
||||
|
||||
int _enc_null (__u8 *dest, int tag);
|
||||
int _enc_bool (__u8 *dest, __u32 i, int tag);
|
||||
int _enc_int (__u8 *dest, __u32 i, int tag);
|
||||
int _enc_enum (__u8 *dest, __u32 i, int tag);
|
||||
int _enc_num_string (__u8 *dest, char *nd, __u8 len, int tag);
|
||||
int _enc_sequence_start (__u8 *dest, __u8 **id, int tag);
|
||||
int _enc_sequence_end (__u8 *dest, __u8 *id, int tag_dummy);
|
||||
|
||||
/*
|
||||
** ASN.1 Decoding
|
||||
*/
|
||||
|
||||
#define dec_null(p, end) _dec_null (p, end, NULL);
|
||||
#define dec_bool(p, end,i) _dec_bool (p, end, i, NULL)
|
||||
#define dec_int(p, end,i) _dec_int (p, end, i, NULL)
|
||||
#define dec_enum(p, end,i) _dec_enum (p, end, i, NULL)
|
||||
#define dec_num_string(p, end,str) _dec_num_string (p, end, str, NULL)
|
||||
#define dec_octet_string(p, end,str) _dec_octet_string (p, end, str, NULL)
|
||||
#define dec_sequence(p, end) _dec_sequence (p, end, NULL)
|
||||
|
||||
int _dec_null (__u8 *p, __u8 *end, int *tag);
|
||||
int _dec_bool (__u8 *p, __u8 *end, int *i, int *tag);
|
||||
int _dec_int (__u8 *p, __u8 *end, int *i, int *tag);
|
||||
int _dec_enum (__u8 *p, __u8 *end, int *i, int *tag);
|
||||
int _dec_num_string (__u8 *p, __u8 *end, char *str, int *tag);
|
||||
int _dec_octet_string (__u8 *p, __u8 *end, char *str, int *tag);
|
||||
int _dec_sequence (__u8 *p, __u8 *end, int *tag);
|
||||
|
||||
int dec_len (__u8 *p, int *len);
|
||||
|
||||
#endif
|
||||
|
@ -1,267 +0,0 @@
|
||||
|
||||
#include "fac.h"
|
||||
#include "asn1.h"
|
||||
|
||||
#if 0
|
||||
+-------------------------------
|
||||
| IE_IDENTIFIER
|
||||
+-------------------------------
|
||||
| {length}
|
||||
+-------------------------------
|
||||
| +---------------------------
|
||||
| | SERVICE_DISCRIMINATOR
|
||||
| +---------------------------
|
||||
| | COMPONENT_TYPE_TAG
|
||||
| +---------------------------
|
||||
| | {length}
|
||||
| +---------------------------
|
||||
| | +-----------------------
|
||||
| | | INVOKE_IDENTIFIER_TAG (0x2)
|
||||
| | +-----------------------
|
||||
| | | {length} (0x1)
|
||||
| | +-----------------------
|
||||
| | | {value} (odd integer 0-127)
|
||||
| | +-----------------------
|
||||
| | +-----------------------
|
||||
| | | OPERATION_VALUE_TAG (0x2)
|
||||
| | +-----------------------
|
||||
| | | {length} (0x1)
|
||||
| | +-----------------------
|
||||
| | | {value}
|
||||
| | +-----------------------
|
||||
| | +-----------------------
|
||||
| | | ASN.1 data
|
||||
+---+---+-----------------------
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SUPPLEMENTARY_SERVICE = 0x91,
|
||||
} SERVICE_DISCRIMINATOR;
|
||||
|
||||
enum {
|
||||
INVOKE = 0xa1,
|
||||
RETURN_RESULT = 0xa2,
|
||||
RETURN_ERROR = 0xa3,
|
||||
REJECT = 0xa4,
|
||||
} COMPONENT_TYPE_TAG;
|
||||
|
||||
enum {
|
||||
INVOKE_IDENTIFIER = 0x02,
|
||||
LINKED_IDENTIFIER = 0x80,
|
||||
NULL_IDENTIFIER = 0x05,
|
||||
} INVOKE_IDENTIFIER_TAG;
|
||||
|
||||
enum {
|
||||
OPERATION_VALUE = 0x02,
|
||||
} OPERATION_VALUE_TAG;
|
||||
|
||||
enum {
|
||||
VALUE_QUERY = 0x8c,
|
||||
SET_VALUE = 0x8d,
|
||||
REQUEST_FEATURE = 0x8f,
|
||||
ABORT = 0xbe,
|
||||
REDIRECT_CALL = 0xce,
|
||||
CALLING_PARTY_TO_HOLD = 0xcf,
|
||||
CALLING_PARTY_FROM_HOLD = 0x50,
|
||||
DROP_TARGET_PARTY = 0xd1,
|
||||
USER_DATA_TRANSFER = 0xd3,
|
||||
APP_SPECIFIC_STATUS = 0xd2,
|
||||
|
||||
/* not from document */
|
||||
CALL_DEFLECT = 0x0d,
|
||||
AOC = 0x22,
|
||||
} OPERATION_CODE;
|
||||
|
||||
enum {
|
||||
Q931_IE_TAG = 0x40,
|
||||
} ARGUMENT_TAG;
|
||||
|
||||
#ifdef FACILITY_DEBUG
|
||||
#define FAC_DUMP(fac,len,bc) fac_dump(fac,len,bc)
|
||||
#include <ctype.h>
|
||||
static void fac_dump (__u8 *facility, unsigned int fac_len, struct misdn_bchannel *bc)
|
||||
{
|
||||
int i;
|
||||
cb_log(0, bc->port, " --- facility dump start. length:%d\n", fac_len);
|
||||
for (i = 0; i < fac_len; ++i)
|
||||
if (isprint(facility[i]))
|
||||
cb_log(0, bc->port, " --- %d: %04p (char:%c)\n", i, facility[i], facility[i]);
|
||||
else
|
||||
cb_log(0, bc->port, " --- %d: %04p\n", i, facility[i]);
|
||||
cb_log(0, bc->port, " --- facility dump end\n");
|
||||
}
|
||||
#else
|
||||
#define FAC_DUMP(fac,len,bc)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Facility Encoding
|
||||
*/
|
||||
|
||||
static int enc_fac_calldeflect (__u8 *dest, char *number, int pres)
|
||||
{
|
||||
__u8 *body_len,
|
||||
*p = dest,
|
||||
*seq1, *seq2;
|
||||
|
||||
*p++ = SUPPLEMENTARY_SERVICE;
|
||||
*p++ = INVOKE;
|
||||
|
||||
body_len = p++;
|
||||
|
||||
p += _enc_int(p, 0x1 /* some odd integer in (0..127) */, INVOKE_IDENTIFIER);
|
||||
p += _enc_int(p, CALL_DEFLECT, OPERATION_VALUE);
|
||||
p += enc_sequence_start(p, &seq1);
|
||||
p += enc_sequence_start(p, &seq2);
|
||||
p += _enc_num_string(p, number, strlen(number), ASN1_TAG_CONTEXT_SPECIFIC);
|
||||
p += enc_sequence_end(p, seq2);
|
||||
p += enc_bool(p, pres);
|
||||
p += enc_sequence_end(p, seq1);
|
||||
|
||||
*body_len = p - &body_len[1];
|
||||
|
||||
return p - dest;
|
||||
}
|
||||
|
||||
static void enc_ie_facility (__u8 **ntmode, msg_t *msg, __u8 *facility, int facility_len, struct misdn_bchannel *bc)
|
||||
{
|
||||
__u8 *ie_fac;
|
||||
|
||||
Q931_info_t *qi;
|
||||
|
||||
ie_fac = msg_put(msg, facility_len + 2);
|
||||
if (bc->nt) {
|
||||
*ntmode = ie_fac + 1;
|
||||
} else {
|
||||
qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
|
||||
qi->QI_ELEMENT(facility) = ie_fac - (__u8 *)qi - sizeof(Q931_info_t);
|
||||
}
|
||||
|
||||
ie_fac[0] = IE_FACILITY;
|
||||
ie_fac[1] = facility_len;
|
||||
memcpy(ie_fac + 2, facility, facility_len);
|
||||
|
||||
FAC_DUMP(ie_fac, facility_len + 2, bc);
|
||||
}
|
||||
|
||||
void fac_enc (__u8 **ntmsg, msg_t *msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc)
|
||||
{
|
||||
__u8 facility[256];
|
||||
int len;
|
||||
|
||||
switch (type) {
|
||||
case FACILITY_CALLDEFLECT:
|
||||
len = enc_fac_calldeflect(facility, fac.calldeflect_nr, 1);
|
||||
enc_ie_facility(ntmsg, msg, facility, len, bc);
|
||||
break;
|
||||
case FACILITY_CENTREX:
|
||||
case FACILITY_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Facility Decoding
|
||||
*/
|
||||
|
||||
static int dec_fac_calldeflect (__u8 *p, int len, struct misdn_bchannel *bc)
|
||||
{
|
||||
__u8 *end = p + len;
|
||||
int offset,
|
||||
pres;
|
||||
|
||||
if ((offset = dec_sequence(p, end)) < 0)
|
||||
return -1;
|
||||
p += offset;
|
||||
|
||||
if ((offset = dec_sequence(p, end)) < 0)
|
||||
return -1;
|
||||
p += offset;
|
||||
|
||||
if ((offset = dec_num_string(p, end, bc->fac.calldeflect_nr)) < 0)
|
||||
return -1;
|
||||
p += offset;
|
||||
|
||||
if ((offset = dec_bool(p, end, &pres)) < 0)
|
||||
return -1;
|
||||
|
||||
cb_log(0, 0, "CALLDEFLECT: dest:%s pres:%s (not implemented yet)\n", bc->fac.calldeflect_nr, pres ? "yes" : "no");
|
||||
bc->fac_type = FACILITY_CALLDEFLECT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fac_dec (__u8 *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc)
|
||||
{
|
||||
int len,
|
||||
offset,
|
||||
inner_len,
|
||||
invoke_id,
|
||||
op_tag,
|
||||
op_val;
|
||||
__u8 *end,
|
||||
*begin = p;
|
||||
|
||||
if (!bc->nt) {
|
||||
if (qi->QI_ELEMENT(facility))
|
||||
p = (__u8 *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
|
||||
else
|
||||
p = NULL;
|
||||
}
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
offset = dec_len (p, &len);
|
||||
if (offset < 0) {
|
||||
cb_log(0, bc->port, "Could not decode FACILITY: dec_len failed!\n");
|
||||
return;
|
||||
}
|
||||
p += offset;
|
||||
end = p + len;
|
||||
|
||||
FAC_DUMP(p, len, bc);
|
||||
|
||||
if (len < 3 || p[0] != SUPPLEMENTARY_SERVICE || p[1] != INVOKE) {
|
||||
cb_log(0, bc->port, "Could not decode FACILITY: invalid or not supported!\n");
|
||||
return;
|
||||
}
|
||||
p += 2;
|
||||
|
||||
offset = dec_len (p, &inner_len);
|
||||
if (offset < 0) {
|
||||
cb_log(0, bc->port, "Could not decode FACILITY: failed parsing inner length!\n");
|
||||
return;
|
||||
}
|
||||
p += offset;
|
||||
|
||||
offset = dec_int (p, end, &invoke_id);
|
||||
if (offset < 0) {
|
||||
cb_log(0, bc->port, "Could not decode FACILITY: failed parsing invoke identifier!\n");
|
||||
return;
|
||||
}
|
||||
p += offset;
|
||||
|
||||
offset = _dec_int (p, end, &op_val, &op_tag);
|
||||
if (offset < 0) {
|
||||
cb_log(0, bc->port, "Could not decode FACILITY: failed parsing operation value!\n");
|
||||
return;
|
||||
}
|
||||
p += offset;
|
||||
|
||||
if (op_tag != OPERATION_VALUE || offset != 3) {
|
||||
cb_log(0, bc->port, "Could not decode FACILITY: operation value tag 0x%x unknown!\n", op_tag);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (op_val) {
|
||||
case CALL_DEFLECT:
|
||||
cb_log(0, bc->port, "FACILITY: Call Deflect\n");
|
||||
dec_fac_calldeflect(p, len - (p - begin) + 1, bc);
|
||||
break;
|
||||
case AOC:
|
||||
cb_log(0, bc->port, "FACILITY: AOC\n");
|
||||
break;
|
||||
default:
|
||||
cb_log(0, bc->port, "FACILITY unknown: operation value 0x%x, ignoring ...\n", op_val);
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#ifndef __FAC_H__
|
||||
#define __FAC_H__
|
||||
|
||||
#include "isdn_lib_intern.h"
|
||||
|
||||
void fac_enc (__u8 **ntmsg, msg_t *msg, enum facility_type type, union facility fac, struct misdn_bchannel *bc);
|
||||
void fac_dec (__u8 *p, Q931_info_t *qi, enum facility_type *type, union facility *fac, struct misdn_bchannel *bc);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in new issue