[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