[asterisk-dev] libss7 does not support china!
toasterisk
toasterisk at gmail.com
Fri Dec 9 05:58:32 CST 2011
hello:
I am not familiar with libss7, i give some code from chan_ss7. there are
few places
are different between CHINA and ITU, here, i list out the deference, some
developers can implement
in libss7. there are few bits are different: routing lable, MTP timer, SI,
SLS, SLTA, TRA and MSU.
please refer the code taken out from chan_ss7, modify libss7 and add that.
hope it works.
check with attached file!
On Fri, Dec 9, 2011 at 9:36 AM, toasterisk <toasterisk at gmail.com> wrote:
> hi:
> ok, i will come out some code to submit to you.
>
>
> On Thu, Dec 8, 2011 at 11:26 PM, Tilghman Lesher <tilghman at meg.abyt.es>wrote:
>
>> On Thu, Dec 8, 2011 at 3:58 AM, toasterisk <toasterisk at gmail.com> wrote:
>> > since the ss7 in china is little different from other standard.
>> > is there any plan to add libss7. i think it will be good.
>>
>> Do you have a source for the specification on what exactly is different
>> (or the
>> whole specification)? That would be necessary in order to implement.
>>
>> --
>> Tilghman
>>
>> --
>> _____________________________________________________________________
>> -- Bandwidth and Colocation Provided by http://www.api-digital.com --
>>
>> asterisk-dev mailing list
>> To UNSUBSCRIBE or update options visit:
>> http://lists.digium.com/mailman/listinfo/asterisk-dev
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-dev/attachments/20111209/3a0b73ee/attachment.htm>
-------------- next part --------------
// the code is from chan_ss7-2.2, support ISUP for CHINA
========in chan_ss7-2.0, mtp.c =================
static void t1_start(mtp2_t *m)
{
int v;
t1_stop(m);
switch (variant(m)) {
case ITU_SS7: v = 45000; break;
case ANSI_SS7: v = 16000; break;
case CHINA_SS7: v = 45000; break; // set china to 45000
}
m->mtp2_t1 = mtp_sched_add(mtp2_sched, v, t1_timeout, m);
}
static void t2_start(mtp2_t *m)
{
int v;
t2_stop(m);
switch (variant(m)) {
case ITU_SS7: v = 75000; break;
case ANSI_SS7: v = 11500; break;
case CHINA_SS7: v = 75000; break; // set china to 75000
}
m->mtp2_t2 = mtp_sched_add(mtp2_sched, v, t2_timeout, m);
}
static void t3_start(mtp2_t *m)
{
int v;
t3_stop(m);
switch (variant(m)) {
case ITU_SS7: v = 1500; break;
case ANSI_SS7: v = 11500; break;
case CHINA_SS7: v = 1500; break; // for china
}
m->mtp2_t3 = mtp_sched_add(mtp2_sched, v, t3_timeout, m);
}
static void t4_start(mtp2_t *m)
{
int v;
t4_stop(m);
switch (variant(m)) {
case ITU_SS7: v = 500; break;
case ANSI_SS7: v = 600; break;
case CHINA_SS7: v = 500; break; // for china
}
m->mtp2_t4 = mtp_sched_add(mtp2_sched, v, t4_timeout, m);
}
static void mtp2_t7_start(mtp2_t *m)
{
int v;
t7_stop(m);
switch (variant(m)) {
case ITU_SS7: v = 1500; break;
case ANSI_SS7: v = 1400; break;
case CHINA_SS7: v = 1500; break; // for china
}
m->mtp2_t7 = mtp_sched_add(mtp2_sched, v, timeout_t7, m);
}
// this is a main difference between china and ITU
void mtp3_put_label(int sls, ss7_variant variant, int opc, int dpc, unsigned char *buf)
{
switch (variant) {
case ITU_SS7:
buf[0] = dpc & 0xff;
buf[1] = ((dpc & 0x3f00) >> 8) | ((opc & 0x0003) << 6);
buf[2] = ((opc & 0x03fc) >> 2);
buf[3] = ((opc & 0x3c00) >> 10) | (sls << 4);
break;
case ANSI_SS7:
case CHINA_SS7: // for china
buf[0] = dpc & 0xff;
buf[1] = (dpc & 0xff00) >> 8;
buf[2] = (dpc & 0xff0000) >> 16;
buf[3] = opc & 0xff;
buf[4] = (opc & 0xff00) >> 8;
buf[5] = (opc & 0xff0000) >> 16;
buf[6] = sls & 0x0f;
break;
}
}
static void mtp3_set_sls(ss7_variant variant, int sls, unsigned char *buf)
{
switch (variant) {
case ITU_SS7:
buf[3] = (buf[3] & 0xff0f) | (sls << 4);
break;
case ANSI_SS7:
case CHINA_SS7:
buf[6] = sls & 0x0f; // for china
}
}
static int mtp3_send_sltm(const void *data) {
unsigned char message_sltm[24];
mtp2_t *m = (mtp2_t*) data;
int subservice = m->subservice;
if (subservice == -1)
subservice = 0x8;
fifo_log(m, LOG_EVENT, "Sending SLTM to peer on link '%s'....\n", m->name);
mtp3_put_label(m->sls, variant(m), peeropc(m), linkpeerdpc(m), message_sltm);
switch (variant(m)) {
case ITU_SS7:
message_sltm[4] = 0x11; /* SLTM */
message_sltm[5] = 0xf0; /* Length: 15 */
memcpy(&(message_sltm[6]), sltm_pattern, sizeof(sltm_pattern));
mtp2_queue_msu(m, (subservice << 4) | 1, message_sltm, 6 + sizeof(sltm_pattern));
break;
case ANSI_SS7:
case CHINA_SS7: // for china
message_sltm[7] = 0x11; /* SLTM */
message_sltm[8] = 0xf0; /* Length: 15 */
memcpy(&(message_sltm[9]), sltm_pattern, sizeof(sltm_pattern));
mtp2_queue_msu(m, (subservice << 4) | 1, message_sltm, 9 + sizeof(sltm_pattern));
break;
}
static void mtp2_good_frame(mtp2_t *m, unsigned char *buf, int len) {
int fsn, fib, bsn, bib;
int li;
/* Count this frame into the error rate monitor counters. */
mtp2_error_mon_count_frame(m);
#ifdef DROP_PACKETS_PCT
if(rand() <= DROP_PACKETS_PCT/100.0*RAND_MAX) {
return;
}
#endif
if(m->state == MTP2_DOWN) {
return;
}
log_frame(m, 0, buf, len);
bsn = buf[0] & 0x7f;
bib = buf[0] >> 7;
fsn = buf[1] & 0x7f;
fib = buf[1] >> 7;
li = buf[2] & 0x3f;
if (option_debug > 2) {
if (m->hwmtp2 || m->hwhdlcfcs || (li > 2)) {
char pbuf[1000], hex[30];
int i;
int slc;
if(variant(m) == ITU_SS7)
slc = (buf[7] & 0xf0) >> 4;
else if(variant(m) == CHINA_SS7) // for china SLC
slc = (buf[10] & 0xf0) >> 4;
else
slc = (buf[10] & 0xf0) >> 4;
strcpy(pbuf, "");
for(i = 0; i < li - 1 && i + 4 < len; i++) {
sprintf(hex, " %02x", buf[i + 4]);
strcat(pbuf, hex);
}
fifo_log(m, LOG_DEBUG, "Got MSU on link '%s/%d' sio=%d slc=%d m.sls=%d bsn=%d/%d, fsn=%d/%d, sio=%02x, len=%d:%s\n", m->name, m->schannel+1, buf[3] & 0xf, slc, m->sls, bib, bsn, fib, fsn, buf[3], li, pbuf);
}
}
if(li + 3 > len) {
fifo_log(m, LOG_NOTICE, "Got unreasonable length indicator %d (len=%d) on link '%s'.\n",
li, len, m->name);
return;
}
if(li == 1 || li == 2) {
/* Link status signal unit. */
mtp2_process_lssu(m, buf, fsn, fib);
return;
}
/* Send TRA (traffic restart allowed) immediately, since we have no
routing capabilities that could be prohibited/restricted. */
m->state = MTP2_INSERVICE;
unsigned char message_tra[8];
int subservice = m->subservice;
if (subservice == -1)
subservice = 0x8;
l4up(m);
fifo_log(m, LOG_NOTICE, "Sending TRA to peer on link '%s'....\n", m->name);
mtp3_put_label(m->sls, variant(m), peeropc(m), linkpeerdpc(m), message_tra);
switch (variant(m)) {
case ITU_SS7:
message_tra[4] = 0x17; /* TRA */
mtp2_queue_msu(m, (subservice << 4) | 0, message_tra, 5);
break;
case ANSI_SS7:
case CHINA_SS7: // for china
message_tra[7] = 0x17; /* TRA */
mtp2_queue_msu(m, (subservice << 4) | 0, message_tra, 8);
break;
}
/* Length indicator (li) is number of bytes in MSU after LI, so the valid
bytes are buf[0] through buf[(li + 3) - 1]. */
if(li < 5) {
fifo_log(m, LOG_NOTICE, "Got short MSU (no label), li=%d on link '%s'.\n", li, m->name);
return;
}
{
char pbuf[1000], hex[30];
int i;
int slc;
switch (variant(m)) {
case ITU_SS7:
slc = (buf[7] & 0xf0) >> 4;
break;
case ANSI_SS7:
case CHINA_SS7: // for china SLC
slc = (buf[10] & 0xf0) >> 4;
break;
static void process_msu(struct mtp2_state* m, unsigned char* buf, int len)
{
mtp2_t* tm;
int service_indicator, subservice_field;
int h0, h1;
int slt_pattern_len;
int dpc, opc, slc;
int li;
int i;
li = buf[2] & 0x3f;
service_indicator = buf[3] & 0xf;
subservice_field = (buf[3] & 0xf0) >> 4;
switch (variant(m)) {
case ITU_SS7:
dpc = buf[4] | ((buf[5] & 0x3f) << 8);
opc = ((buf[5] & 0xc0) >> 6) | (buf[6] << 2) | ((buf[7] & 0x0f) << 10);
slc = (buf[7] & 0xf0) >> 4;
break;
case ANSI_SS7:
case CHINA_SS7: // for china MSU
dpc = buf[4] | ((buf[5] & 0xff) << 8) | ((buf[6] & 0xff) << 16);
opc = buf[7] | ((buf[8] & 0xff) << 8) | ((buf[9] & 0xff) << 16);
slc = buf[10] & 0x0f;
break;
}
switch(service_indicator) {
case 0x0:
/* Signalling network management messages. */
switch (variant(m)) {
case ITU_SS7:
h0 = buf[8] & 0xf;
h1 = (buf[8] & 0xf0) >> 4;
break;
case ANSI_SS7:
case CHINA_SS7: // for china service indicator
h0 = buf[11] & 0xf;
h1 = (buf[11] & 0xf0) >> 4;
break;
}
case 0x1: /* maintenance regular message */
case 0x2: /* maintenance special message */
if(li < 7) {
fifo_log(m, LOG_NOTICE, "Got short SLTM/SLTA (no h0/h1/len), li=%d on link '%s'.\n", li, m->name);
return;
}
switch (variant(m)) {
case ITU_SS7:
h0 = buf[8] & 0xf;
h1 = (buf[8] & 0xf0) >> 4;
slt_pattern_len = (buf[9] & 0xf0) >> 4;
break;
case ANSI_SS7:
case CHINA_SS7: // for china H0, H1
h0 = buf[11] & 0xf;
h1 = (buf[11] & 0xf0) >> 4;
slt_pattern_len = (buf[12] & 0xf0) >> 4;
break;
}
if (subservice == -1)
subservice = 0x8;
mtp3_put_label(slc, variant(m), dpc, opc, message_slta);
if (slc != m->sls) {
fifo_log(m, LOG_WARNING, "Got SLTM with unexpected sls=%d, OPC=%d DPC=%d on '%s/%d' sls=%d, state=%d.\n", slc, opc, dpc, m->name, m->schannel+1, m->sls, m->state);
//m->sls = slc;
}
fifo_log(m, LOG_DEBUG, "Got SLTM, OPC=%d DPC=%d, sending SLTA '%s', state=%d.\n", opc, dpc, m->name, m->state);
switch (variant(m)) {
case ITU_SS7:
message_slta[4] = 0x21;
message_slta[5] = slt_pattern_len << 4;
memcpy(&(message_slta[6]), &(buf[10]), slt_pattern_len);
mtp2_queue_msu(m, (subservice << 4) | 1, message_slta, 6 + slt_pattern_len);
break;
case ANSI_SS7:
case CHINA_SS7: // for china SLTA
message_slta[7] = 0x21;
message_slta[8] = slt_pattern_len << 4;
memcpy(&(message_slta[9]), &(buf[13]), slt_pattern_len);
mtp2_queue_msu(m, (subservice << 4) | 1, message_slta, 9 + slt_pattern_len);
break;
/* Q.707 (2.2) conditions for acceptance of SLTA. */
switch (variant(m)) {
case ITU_SS7:
i = memcmp(sltm_pattern, &(buf[10]), sizeof(sltm_pattern));
break;
case ANSI_SS7:
case CHINA_SS7: // for china SLTA
i = memcmp(sltm_pattern, &(buf[13]), sizeof(sltm_pattern));
break;
}
==========isup.c================================
int decode_isup_msg(struct isup_msg *msg, ss7_variant variant, unsigned char *buf, int len) {
int i;
memset(msg, 0, sizeof(*msg));
if(variant==ITU_SS7)
i = 7;
else if(variant==ANSI_SS7)
i = 10;
else
i =10;
if(len < i) {
ast_log(LOG_NOTICE, "Got short ISUP message (len=%d < %d).\n", len, i);
return 0;
}
if(variant==ITU_SS7) {
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;
}
else if(variant==ANSI_SS7) {
msg->dpc = buf[0] | ((buf[1] & 0xff) << 8) | ((buf[2] & 0xff) << 16);
msg->opc = buf[3] | ((buf[4] & 0xff) << 8) | ((buf[5] & 0xff) << 16);
msg->sls = buf[6] & 0x0f;
msg->cic = buf[7] | ((buf[8] & 0x0f) << 8);
msg->typ = buf[9];
buf += 10;
len -= 10;
} else { /* CHINA SS7 */
msg->dpc = buf[0] | ((buf[1] & 0xff) << 8) | ((buf[2] & 0xff) << 16);
msg->opc = buf[3] | ((buf[4] & 0xff) << 8) | ((buf[5] & 0xff) << 16);
msg->sls = buf[6] & 0x0f;
msg->cic = buf[7] | ((buf[8] & 0x0f) << 8);
msg->typ = buf[9];
buf += 10;
len -= 10;
}
void isup_msg_init(unsigned char *buf, int buflen, ss7_variant variant, 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), variant, opc, dpc, &(buf[*current]));
if(variant==ITU_SS7) { // CHINA
*current += 4;
buf[(*current)++] = cic & 0xff;
buf[(*current)++] = (cic & 0x0f00) >> 8;
buf[(*current)++] = msg_type;
}
else if(variant==ANSI_SS7) {
*current += 7;
buf[(*current)++] = cic & 0xff;
buf[(*current)++] = (cic & 0x0f00) >> 8;
buf[(*current)++] = msg_type;
} else { /* CHINA SS7 */
*current += 7;
buf[(*current)++] = cic & 0xff;
buf[(*current)++] = (cic & 0x0f00) >> 8;
buf[(*current)++] = msg_type;
}
}
===========config.c==================
static int load_config_linkset(struct ast_config *cfg, const char* cat)
{
struct ast_variable *v;
const char *context = "default";
const char *language = "";
const char *linkset_name = &cat[strlen("linkset-")];
struct linkset* linkset = &linksets[n_linksets];
int has_context = 0, has_language = 0, has_hunt_policy = 0, has_use_connect = 0, has_enable_st = 0, has_subservice = 0;
int i;
if (n_linksets == MAX_LINKSETS) {
ast_log(LOG_ERROR, "Too many linksets defined. Max %d\n", MAX_LINKSETS);
return -1;
}
linkset->enabled = 1;
linkset->n_slinks = 0;
linkset->n_schannels = 0;
linkset->t35_value = 15000;
linkset->t35_action = 0;
linkset->context = NULL;
linkset->language = NULL;
linkset->opc = 0;
linkset->dpc = 0;
linkset->dni_chunk_limit = 0;
linkset->loadshare = LOADSHARE_COMBINED_LINKSET;
linkset->inservice = 0;
linkset->combined = 0;
linkset->group = 0;
linkset->group_linkset = NULL;
linkset->variant = ITU_SS7;
linkset->noa = -1;
linkset->grs = 1;
for (i = 0; i < MAX_CIC; i++)
linkset->blocked[i] = 0;
context = "default";
language = "";
v = ast_variable_browse(cfg, cat);
while(v != NULL) {
if(0 == strcasecmp(v->name, "context")) {
context = v->value;
has_context = 1;
} else if(0 == strcasecmp(v->name, "language")) {
language = v->value;
has_language = 1;
} else if(0 == strcasecmp(v->name, "variant")) {
if(0 == strcasecmp(v->value, "CHINA")) {
linkset->variant = CHINA_SS7; // for CHINA, set variant=CHINA in chan_ss7.conf
} else if(0 == strcasecmp(v->value, "ITU")) {
linkset->variant = ITU_SS7;
} else if(0 == strcasecmp(v->value, "ANSI")) {
linkset->variant = ANSI_SS7;
} else {
ast_log(LOG_ERROR, "Error invalid SS7 variant '%s'.\n", v->value);
return -1;
}
More information about the asterisk-dev
mailing list