diff -ruNa old_ss7/config.c new_ss7/config.c --- old_ss7/config.c 2007-09-26 14:20:02.000000000 +0800 +++ new_ss7/config.c 2007-11-09 13:55:33.000000000 +0800 @@ -59,6 +59,7 @@ int clusterlistenport; + /* Lookup linkset for destination point code */ struct linkset* find_linkset_for_dpc(int pc) { @@ -224,8 +225,16 @@ } else if(0 == strcasecmp(v->name, "language")) { language = v->value; has_language = 1; - } - else if(0 == strcasecmp(v->name, "hunting_policy")) { + } else if(0 == strcasecmp(v->name, "variant")) { + if(0 == strcasecmp(v->value, "CHINA")) { + linkset->variant = CHINA_SS7; + } else if(0 == strcasecmp(v->value, "ITU")) { + linkset->variant = ITU_SS7; + } else { + ast_log(LOG_ERROR, "Error invalid SS7 variant '%s'.\n", v->value); + return -1; + } + } else if(0 == strcasecmp(v->name, "hunting_policy")) { if(0 == strcasecmp(v->value, "odd_lru")) { linkset->hunt_policy = HUNT_ODD_LRU; } else if(0 == strcasecmp(v->value, "even_mru")) { diff -ruNa old_ss7/config.h new_ss7/config.h --- old_ss7/config.h 2007-09-26 14:20:02.000000000 +0800 +++ new_ss7/config.h 2007-11-09 13:56:30.000000000 +0800 @@ -22,6 +22,9 @@ */ +/* SS7 Variants */ +typedef enum {ITU_SS7, CHINA_SS7} ss7_variant; + /* Hunting policy. */ typedef enum { HUNT_ODD_LRU, HUNT_EVEN_MRU, HUNT_SEQ_LTH, HUNT_SEQ_HTL } hunting_policy; @@ -47,6 +50,7 @@ struct link* links[MAX_LINKS_PER_LINKSET]; char* context; char* language; + ss7_variant variant; hunting_policy hunt_policy; int dpc; int enabled; @@ -144,3 +148,5 @@ struct host* lookup_host_by_addr(struct in_addr); struct host* lookup_host_by_id(int hostix); + +//extern ss7_variant own_variant; diff -ruNa old_ss7/COPYING new_ss7/COPYING --- old_ss7/COPYING 2007-09-26 13:59:44.000000000 +0800 +++ new_ss7/COPYING 2005-12-02 21:17:39.000000000 +0800 @@ -55,7 +55,7 @@ The precise terms and conditions for copying, distribution and modification follow. - + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION @@ -110,7 +110,7 @@ License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in @@ -168,7 +168,7 @@ access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - + 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is @@ -225,7 +225,7 @@ This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License @@ -278,7 +278,7 @@ POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS - + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest diff -ruNa old_ss7/fasthdlc.h new_ss7/fasthdlc.h --- old_ss7/fasthdlc.h 1970-01-01 07:00:00.000000000 +0700 +++ new_ss7/fasthdlc.h 2007-11-09 13:56:40.000000000 +0800 @@ -0,0 +1,462 @@ +/* + * Mark's Mythical Table-based raw HDLC implementation + * + * This is designed to be a very fast, but memory efficient + * implementation of standard HDLC protocol. + * + * This table based HDLC technology is PATENT PENDING, but will always be + * remain freely distributable under the terms of the GPL version 2.0. + * + * For non-GPL licensing, please contact Mark Spencer at + * the below e-mail address. + * + * Copyright (C) 2001, Linux Support Services, Inc. + * + * Written by Mark Spencer + * + * Distributed under the terms of the GNU General Public License + * Version 2.0. + * + */ + +#ifndef _FASTHDLC_H +#define _FASTHDLC_H + +struct fasthdlc_state { + int state; /* What state we are in */ + unsigned int data; /* Our current data queue */ + int bits; /* Number of bits in our data queue */ + int ones; /* Number of ones */ +}; + +#ifdef FAST_HDLC_NEED_TABLES +#define RETURN_COMPLETE_FLAG (0x1000) +#define RETURN_DISCARD_FLAG (0x2000) +#define RETURN_EMPTY_FLAG (0x4000) + +/* Unlike most HDLC implementations, we define only two states, + when we are in a valid frame, and when we are searching for + a frame header */ + +#define FRAME_SEARCH 0 +#define PROCESS_FRAME 1 + +/* + + HDLC Search State table -- Look for a frame header. The return value + of this table is as follows: + + |---8---|---7---|---6---|---5---|---4---|---3---|---2---|---1---| + | Z E R O E S | Next | Bits Consumed | + |-------|-------|-------|-------|-------|-------|-------|-------| + + The indexes for this table are the state (0 or 1) and the next 8 + bits of the stream. + + Note that this table is only used for state 0 and 1. + + The user should discard the top "bits consumed" bits of data before + the next call. "Next state" represents the actual next state for + decoding. + +*/ +static unsigned char hdlc_search[256]; + +/* + HDLC Data Table + + The indexes to this table are the number of one's we've seen so far (0-5) and + the next 10 bits of input (which is enough to guarantee us that we + will retrieve at least one byte of data (or frame or whatever). + + The format for the return value is: + + Bits 15: Status (1=Valid Data, 0=Control Frame (see bits 7-0 for type)) + Bits 14-12: Number of ones in a row, so far + Bits 11-8: The number of bits consumed (0-10) + Bits 7-0: The return data (if appropriate) + + The next state is simply bit #15 + +*/ + +#define CONTROL_COMPLETE 1 +#define CONTROL_ABORT 2 + +#define STATUS_MASK (1 << 15) +#define STATUS_VALID (1 << 15) +#define STATUS_CONTROL (0 << 15) +#define STATE_MASK (1 << 15) +#define ONES_MASK (7 << 12) +#define DATA_MASK (0xff) + +static unsigned short hdlc_frame[6][1024]; + +static unsigned int minbits[2] = { 8, 10 }; + +/* + Last, but not least, we have the encoder table. It takes + as its indices the number of ones so far and a byte of data + and returns an int composed of the following fields: + + Bots 31-22: Actual Data + Bits 21-16: Unused + Bits 15-8: Number of ones + Bits 3-0: Number of bits of output (13-4) to use + + Of course we could optimize by reducing to two tables, but I don't + really think it's worth the trouble at this point. + */ + +static unsigned int hdlc_encode[6][256]; + +static inline char hdlc_search_precalc(unsigned char c) +{ + int x, p=0; + /* Look for a flag. If this isn't a flag, + line us up for the next possible shot at + a flag */ + + /* If it's a flag, we go to state 1, and have + consumed 8 bits */ + if (c == 0x7e) + return 0x10 | 8; + + /* If it's an abort, we stay in the same state + and have consumed 8 bits */ + if (c == 0x7f) + return 0x00 | 8; + + /* If it's all 1's, we state in the same state and + have consumed 8 bits */ + if (c == 0xff) + return 0x00 | 8; + + /* If we get here, we must have at least one zero in us + but we're not the flag. So, start at the end (LSB) and + work our way to the top (MSB) looking for a zero. The + position of that 0 is most optimistic start of a real + frame header */ + x=1; + p=7; + while(p && (c & x)) { + x <<= 1; + p--; + } + return p; +} + +#ifdef DEBUG_PRECALC +static inline void hdlc_search_print(char c, char r) +{ + int x=0x80; + while(x) { + printf("%s", c & x ? "1" : "0"); + x >>= 1; + } + printf(" => State %d, Consume %d\n", (r & 0x10) >> 4, r & 0xf); +} +#endif + +#define HFP(status, ones, bits, data) \ + ((status) | ((ones) << 12) | ((bits) << 8) | (data)) + +static inline unsigned int hdlc_frame_precalc(unsigned char x, unsigned short c) +{ + /* Assume we have seen 'x' one's so far, and have read the + bottom 10 bytes of c (MSB first). Now, we HAVE to have + a byte of data or a frame or something. We are assumed + to be at the beginning of a byte of data or something */ + unsigned char ones = x; + unsigned char data=0; + int bits=0; + int consumed=0; + while(bits < 8) { + data >>=1; + consumed++; + if (ones == 5) { + /* We've seen five ones */ + if (c & 0x0200) { + /* Another one -- Some sort of signal frame */ + if ((!(c & 0x0100)) && (bits == 6)) { + /* This is a frame terminator (10) */ + return HFP(0, + 0, 8, CONTROL_COMPLETE); + } else { + /* Yuck! It's something else... + Abort this entire frame, and + start looking for a good frame */ + return HFP(0, + 0, consumed+1, CONTROL_ABORT); + } + } else { + /* It's an inserted zero, just skip it */ + ones = 0; + data <<= 1; + } + } else { + /* Add it to our bit list, LSB to + MSB */ + if (c & 0x0200) { + data |= 0x80; + ones++; + } else + ones=0; + bits++; + } + c <<= 1; + } + /* Consume the extra 0 now rather than later. */ + if (ones == 5) { + ones = 0; + consumed++; + } + return HFP(STATUS_VALID, ones, consumed, data); +} + +#ifdef DEBUG_PRECALC + +static inline void hdlc_frame_print(unsigned char x, unsigned short c, unsigned int res) +{ + int z=0x0200; + char *status[] = { + "Control", + "Valid", + }; + printf("%d one's then ", x); + while(z) { + printf("%s", c & z ? "1" : "0"); + z >>= 1; + } + printf(" => Status %s, ", res & STATUS_MASK ? "1" : "0"); + printf("Consumed: %d, ", (res & 0x0f00) >> 8); + printf("Status: %s, ", status[(res & STATUS_MASK) >> 15]); + printf("Ones: %d, ", (res & ONES_MASK) >> 12); + printf("Data: %02x\n", res & 0xff); + +} + +#endif + +static inline unsigned int hdlc_encode_precalc(int x, unsigned char y) +{ + int bits=0; + int ones=x; + unsigned short data=0; + int z; + for (z=0;z<8;z++) { + /* Zero-stuff if needed */ + if (ones == 5) { + /* Stuff a zero */ + data <<= 1; + ones=0; + bits++; + } + if (y & 0x01) { + /* There's a one */ + data <<= 1; + data |= 0x1; + ones++; + bits++; + } else { + data <<= 1; + ones = 0; + bits++; + } + y >>= 1; + } + /* Special case -- Stuff the zero at the end if appropriate */ + if (ones == 5) { + /* Stuff a zero */ + data <<= 1; + ones=0; + bits++; + } + data <<= (10-bits); + return (data << 22) | (ones << 8) | (bits); +} + +#ifdef DEBUG_PRECALC +static inline void hdlc_encode_print(int x, unsigned char y, unsigned int val) +{ + unsigned int z; + unsigned short c; + printf("%d ones, %02x (", x, y); + z = 0x80; + while(z) { + printf("%s", y & z ? "1" : "0"); + z >>= 1; + } + printf(") encoded as "); + z = 1 << 31; + for (x=0;x<(val & 0xf);x++) { + printf("%s", val & z ? "1" : "0"); + z >>= 1; + } + printf(" with %d ones now, %d bits in len\n", (val & 0xf00) >> 8, val & 0xf); + + +} +#endif + +static inline void fasthdlc_precalc(void) +{ + int x; + int y; + /* First the easy part -- the searching */ + for (x=0;x<256;x++) { + hdlc_search[x] = hdlc_search_precalc(x); +#ifdef DEBUG_PRECALC + hdlc_search_print(x, hdlc_search[x]); +#endif + } + /* Now the hard part -- the frame tables */ + for (x=0;x<6;x++) { + /* Given the # of preceeding ones, process the next + byte of input (up to 10 actual bits) */ + for (y=0;y<1024;y++) { + hdlc_frame[x][y] = hdlc_frame_precalc(x, y); +#ifdef DEBUG_PRECALC + hdlc_frame_print(x, y, hdlc_frame[x][y]); +#endif + } + } + /* Now another not-so-hard part, the encoding table */ + for (x=0;x<6;x++) { + for (y=0;y<256;y++) { + hdlc_encode[x][y] = hdlc_encode_precalc(x,y); +#ifdef DEBUG_PRECALC + hdlc_encode_print(x,y,hdlc_encode[x][y]); +#endif + } + } +} + + +static inline void fasthdlc_init(struct fasthdlc_state *h) +{ + /* Initializes all states appropriately */ + h->state = 0; + h->bits = 0; + h->data = 0; + h->ones = 0; + +} + +static inline int fasthdlc_tx_load_nocheck(struct fasthdlc_state *h, unsigned char c) +{ + unsigned int res; + res = hdlc_encode[h->ones][c]; + h->ones = (res & 0xf00) >> 8; + h->data |= (res & 0xffc00000) >> h->bits; + h->bits += (res & 0xf); + return 0; +} + +static inline int fasthdlc_tx_load(struct fasthdlc_state *h, unsigned char c) +{ + /* Gotta have at least 10 bits left */ + if (h->bits > 22) + return -1; + return fasthdlc_tx_load_nocheck(h, c); +} + +static inline int fasthdlc_tx_frame_nocheck(struct fasthdlc_state *h) +{ + h->ones = 0; + h->data |= ( 0x7e000000 >> h->bits); + h->bits += 8; + return 0; +} + +static inline int fasthdlc_tx_frame(struct fasthdlc_state *h) +{ + if (h->bits > 24) + return -1; + return fasthdlc_tx_frame_nocheck(h); +} + +static inline int fasthdlc_tx_run_nocheck(struct fasthdlc_state *h) +{ + unsigned char b; + b = h->data >> 24; + h->bits -= 8; + h->data <<= 8; + return b; +} + +static inline int fasthdlc_tx_run(struct fasthdlc_state *h) +{ + if (h->bits < 8) + return -1; + return fasthdlc_tx_run_nocheck(h); +} + +static inline int fasthdlc_rx_load_nocheck(struct fasthdlc_state *h, unsigned char b) +{ + /* Put the new byte in the data stream */ + h->data |= b << (24-h->bits); + h->bits += 8; + return 0; +} + +static inline int fasthdlc_rx_load(struct fasthdlc_state *h, unsigned char b) +{ + /* Make sure we have enough space */ + if (h->bits > 24) + return -1; + return fasthdlc_rx_load_nocheck(h, b); +} + +/* + Returns a data character if available, logical OR'd with + zero or more of RETURN_COMPLETE_FLAG, RETURN_DISCARD_FLAG, + and RETURN_EMPTY_FLAG, signifying a complete frame, a + discarded frame, or there is nothing to return. + */ + +static inline int fasthdlc_rx_run(struct fasthdlc_state *h) +{ + unsigned short next; + int retval=RETURN_EMPTY_FLAG; + while ((h->bits >= minbits[h->state]) && (retval == RETURN_EMPTY_FLAG)) { + /* Run until we can no longer be assured that we will + have enough bits to continue */ + switch(h->state) { + case FRAME_SEARCH: + /* Look for an HDLC frame, keying from + the top byte. */ + next = hdlc_search[h->data >> 24]; + h->bits -= next & 0x0f; + h->data <<= next & 0x0f; + h->state = next >> 4; + h->ones = 0; + break; + case PROCESS_FRAME: + /* Process as much as the next ten bits */ + next = hdlc_frame[h->ones][h->data >> 22]; + h->bits -= ((next & 0x0f00) >> 8); + h->data <<= ((next & 0x0f00) >> 8); + h->state = (next & STATE_MASK) >> 15; + h->ones = (next & ONES_MASK) >> 12; + switch(next & STATUS_MASK) { + case STATUS_CONTROL: + if (next & CONTROL_COMPLETE) { + /* A complete, valid frame received */ + retval = (RETURN_COMPLETE_FLAG); + /* Stay in this state */ + h->state = 1; + } else { + /* An abort (either out of sync of explicit) */ + retval = (RETURN_DISCARD_FLAG); + } + break; + case STATUS_VALID: + retval = (next & DATA_MASK); + } + } + } + return retval; +} +#endif /* FAST_HDLC_NEED_TABLES */ +#endif diff -ruNa old_ss7/isup.c new_ss7/isup.c --- old_ss7/isup.c 2007-09-26 14:20:02.000000000 +0800 +++ new_ss7/isup.c 2007-11-09 13:55:44.000000000 +0800 @@ -28,6 +28,24 @@ #include "asterisk/logger.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" #include "isup.h" #include "mtp.h" @@ -542,22 +560,34 @@ /* Decode raw SIF field into ISUP message. Returns true on success, false on error. */ -int decode_isup_msg(struct isup_msg *msg, unsigned char *buf, int len) { +int decode_isup_msg(struct isup_msg *msg, ss7_variant variant, unsigned char *buf, int len) { memset(msg, 0, sizeof(*msg)); if(len < 7) { ast_log(LOG_NOTICE, "Got short ISUP message (len=%d < 7).\n", len); return 0; } - 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; + 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 { /* 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[4] | ((buf[5] & 0x0f) << 8); - msg->typ = buf[6]; + msg->cic = buf[7] | ((buf[8] & 0x0f) << 8); + msg->typ = buf[9]; - buf += 7; - len -= 7; + buf += 10; + len -= 10; + } switch(msg->typ) { case ISUP_IAM: /* Must initialize optional parameters, in case they are no @@ -743,7 +773,7 @@ } } -void isup_msg_init(unsigned char *buf, int buflen, int opc, int dpc, int cic, +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); @@ -751,11 +781,18 @@ } *current = 0; - mtp3_put_label((cic & 0x000f), opc, dpc, &(buf[*current])); - *current += 4; - buf[(*current)++] = cic & 0xff; - buf[(*current)++] = (cic & 0x0f00) >> 8; - buf[(*current)++] = msg_type; + mtp3_put_label((cic & 0x000f), variant, opc, dpc, &(buf[*current])); + if(variant==ITU_SS7) { + *current += 4; + 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; + } } void isup_msg_add_fixed(unsigned char *buf, int buflen, int *current, diff -ruNa old_ss7/isup.h new_ss7/isup.h --- old_ss7/isup.h 2007-09-26 14:20:02.000000000 +0800 +++ new_ss7/isup.h 2007-11-09 13:56:52.000000000 +0800 @@ -182,7 +182,7 @@ }; -int decode_isup_msg(struct isup_msg *msg, unsigned char *buf, int len); +int decode_isup_msg(struct isup_msg *msg, ss7_variant variant, unsigned char *buf, int len); /* Contruction of ISUP messages. Typical usage: @@ -206,8 +206,11 @@ // Now current holds the total size of the message. */ -void isup_msg_init(unsigned char *buf, int buflen, int opc, int dpc, int cic, +/*void isup_msg_init(unsigned char *buf, int buflen, int opc, int dpc, int cic, + enum isup_msg_type msg_type, int *current);*/ +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); + void isup_msg_add_fixed(unsigned char *buf, int buflen, int *current, unsigned char *param, int param_len); void isup_msg_start_variable_part(unsigned char *buf, int buflen, diff -ruNa old_ss7/l4isup.c new_ss7/l4isup.c --- old_ss7/l4isup.c 2007-09-26 14:20:02.000000000 +0800 +++ new_ss7/l4isup.c 2007-11-09 13:55:58.000000000 +0800 @@ -54,7 +54,7 @@ #include "asterisk/indications.h" #include "asterisk/module.h" -#include "zaptel.h" +#include "linux/zaptel.h" #include "config.h" #include "lffifo.h" @@ -235,6 +235,13 @@ } +/* Lookup variant for circuit */ +static inline ss7_variant variant(struct ss7_chan* pvt) +{ + return pvt->link->linkset->variant; +} + + static void mtp_enqueue_isup_packet(int lsi, struct link* link, unsigned char *msg, int msglen, int reqtyp) { int res; unsigned char req_buf[MTP_REQ_MAX_SIZE]; @@ -441,7 +448,7 @@ int current, varptr; unsigned char param[2]; - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), pvt->cic, ISUP_REL, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), pvt->cic, ISUP_REL, ¤t); isup_msg_start_variable_part(msg, sizeof(msg), &varptr, ¤t, 1, 1); param[0] = 0x85; /* Last octet, ITU-T coding, private network */ param[1] = 0x80 | (cause & 0x7f); /* Last octet */ @@ -457,7 +464,7 @@ int current, varptr; int cic = pvt->cic; - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), cic, ISUP_RLC, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), cic, ISUP_RLC, ¤t); isup_msg_start_variable_part(msg, sizeof(msg), &varptr, ¤t, 0, 1); isup_msg_start_optional_part(msg, sizeof(msg), &varptr, ¤t); isup_msg_end_optional_part(msg, sizeof(msg), ¤t); @@ -470,7 +477,7 @@ int current, varptr; int cic = pvt->cic; - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), cic, ISUP_RSC, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), cic, ISUP_RSC, ¤t); isup_msg_start_variable_part(msg, sizeof(msg), &varptr, ¤t, 0, 0); mtp_enqueue_isup(pvt, msg, current); } @@ -482,7 +489,7 @@ unsigned char param[2]; int cic = pvt->cic; - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), cic, ISUP_ACM, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), cic, ISUP_ACM, ¤t); param[0] = 0x12; param[1] = 0x14; @@ -532,7 +539,7 @@ unsigned char msg[MTP_MAX_PCK_SIZE]; int current, varptr; - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), pvt->cic, ISUP_BLK, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), pvt->cic, ISUP_BLK, ¤t); isup_msg_start_variable_part(msg, sizeof(msg), &varptr, ¤t, 0, 0); mtp_enqueue_isup(pvt, msg, current); } @@ -712,7 +719,7 @@ unsigned char param_backward_ind[2]; unsigned char param_opt_backw_ind[1]; - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), pvt->cic, ISUP_CPR, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), pvt->cic, ISUP_CPR, ¤t); param[0] = value; /* Event information */ param_backward_ind[0] = 0x16; /* Charge, subscriber free, ordinary subscriber, no end-to-end */ param_backward_ind[1] = 0x14; /* No interworking, no end-to-end, ISDN all the way, no @@ -1175,12 +1182,15 @@ "circuits (need at least 2).\n", pvt->cic, count); return; } - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), pvt->cic, ISUP_GRS, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), pvt->cic, ISUP_GRS, ¤t); isup_msg_start_variable_part(msg, sizeof(msg), &varptr, ¤t, 1, 0); param[0] = count - 1; isup_msg_add_variable(msg, sizeof(msg), &varptr, ¤t, param, 1); mtp_enqueue_isup(pvt, msg, current); + //ast_log(LOG_NOTICE, "Sending GRS count[%d],do_timers[%d],varptr[%d],param[0][%d],current[%d].\n", + // count, do_timers, varptr, param[0], current); + if(do_timers) { t22_start(pvt); t23_start(pvt); @@ -1541,7 +1551,7 @@ unsigned char param[2 + PHONENUM_MAX]; int res; - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), pvt->cic, ISUP_SAM, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), pvt->cic, ISUP_SAM, ¤t); if (complete) res = isup_called_party_num_encode(addr, param, sizeof(param)); else @@ -1568,7 +1578,7 @@ int pres_restr; int res; - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), pvt->cic, ISUP_IAM, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), pvt->cic, ISUP_IAM, ¤t); /* Nature of connection indicators Q.763 (3.35). */ param[0] = 0x00; /* No sattelite, no continuity check, no echo control */ @@ -1777,7 +1787,7 @@ /* Send ANM instead of CON if previously sent ACM. */ if (pvt->state == ST_SENT_ACM) { - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), pvt->cic, ISUP_ANM, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), pvt->cic, ISUP_ANM, ¤t); param[0] = 0x14; /* Subscriber free, ordinary subscriber, no end-to-end */ param[1] = 0x14; /* No interworking, no end-to-end, ISDN all the way, no hold, terminating access ISDN, no echo control */ @@ -1787,7 +1797,7 @@ isup_msg_end_optional_part(msg, sizeof(msg), ¤t); mtp_enqueue_isup(pvt, msg, current); } else if (pvt->state == ST_GOT_IAM) { - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), pvt->cic, ISUP_CON, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), pvt->cic, ISUP_CON, ¤t); param[0] = 0x14; /* Subscriber free, ordinary subscriber, no end-to-end */ param[1] = 0x14; /* No interworking, no end-to-end, ISDN all the way, no hold, terminating access ISDN, no echo control */ @@ -2090,7 +2100,7 @@ lock_global(); /* First send hardware blocked, if required. */ - isup_msg_init(msg, sizeof(msg), own_pc, grs_msg->opc, grs_msg->cic, ISUP_CGB, ¤t); + isup_msg_init(msg, sizeof(msg), variant(ipvt), own_pc, grs_msg->opc, grs_msg->cic, ISUP_CGB, ¤t); param[0] = 0x01; /* Hardware failure oriented */ isup_msg_add_fixed(msg, sizeof(msg), ¤t, param, 1); isup_msg_start_variable_part(msg, sizeof(msg), &varpart, ¤t, 1, 0); @@ -2144,7 +2154,8 @@ } /* Now send a GRA (group reset acknowledgement). */ - isup_msg_init(msg, sizeof(msg), own_pc, grs_msg->opc, grs_msg->cic, ISUP_GRA, ¤t); + //ast_log(LOG_NOTICE, "==ML====== Sending GRA from 0x%x to 0x%x variant 0x%x,\n", own_pc, grs_msg->opc, variant(linkset->cic_list[grs_msg->cic])); + isup_msg_init(msg, sizeof(msg), variant(linkset->cic_list[grs_msg->cic]), own_pc, grs_msg->opc, grs_msg->cic, ISUP_GRA, ¤t); isup_msg_start_variable_part(msg, sizeof(msg), &varpart, ¤t, 1, 0); i = 0; range = grs_msg->grs.range; @@ -2230,11 +2241,13 @@ } /* Send an "unequipped CIC" message. See Q.764 (2.12) and Q.763 table 39. */ -static void isup_send_unequipped(int lsi, int cic, int dpc) { +static void isup_send_unequipped(ss7_variant variant, int lsi, int cic, int dpc) { unsigned char msg[MTP_MAX_PCK_SIZE]; int current, varptr; - isup_msg_init(msg, sizeof(msg), own_pc, dpc, cic, ISUP_UEC, ¤t); + + + isup_msg_init(msg, sizeof(msg), variant, own_pc, dpc, cic, ISUP_UEC, ¤t); isup_msg_start_variable_part(msg, sizeof(msg), &varptr, ¤t, 0, 0); mtp_enqueue_isup_packet(lsi, NULL, msg, current, MTP_REQ_ISUP); } @@ -2275,7 +2288,7 @@ response to a specific list of message types. But don't know what else to do with an unequipped CIC, so for now we send the message in response to all messages with unequipped CIC. */ - isup_send_unequipped(slink->linkset->lsi, cic, inmsg->opc); + isup_send_unequipped(variant(pvt), slink->linkset->lsi, cic, inmsg->opc); return; } if(!pvt->reset_done) { @@ -2341,7 +2354,7 @@ response to a specific list of message types. But don't know what else to do with an unequipped CIC, so for now we send the message in response to all messages with unequipped CIC. */ - isup_send_unequipped(slink->linkset->lsi, cic, inmsg->opc); + isup_send_unequipped(variant(pvt), slink->linkset->lsi, cic, inmsg->opc); return; } if(!pvt->reset_done && pvt->equipped) { @@ -2876,7 +2889,7 @@ pvt->blocked |= BL_RM; /* Reply with blocking acknowledge. */ - isup_msg_init(msg, sizeof(msg), own_pc, inmsg->opc, inmsg->cic, ISUP_BLA, + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, inmsg->opc, inmsg->cic, ISUP_BLA, ¤t); isup_msg_start_variable_part(msg, sizeof(msg), &varptr, ¤t, 0, 0); @@ -2898,7 +2911,7 @@ pvt->blocked &= ~BL_RM; /* Reply with unblocking acknowledge. */ - isup_msg_init(msg, sizeof(msg), own_pc, inmsg->opc, inmsg->cic, ISUP_UBA, + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, inmsg->opc, inmsg->cic, ISUP_UBA, ¤t); isup_msg_start_variable_part(msg, sizeof(msg), &varptr, ¤t, 0, 0); @@ -3093,7 +3106,7 @@ } /* Reply with circuit group blocking acknowledge. */ - isup_msg_init(msg, sizeof(msg), own_pc, inmsg->opc, inmsg->cic, ISUP_CGA, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, inmsg->opc, inmsg->cic, ISUP_CGA, ¤t); param[0] = inmsg->cgb.cgsmti; isup_msg_add_fixed(msg, sizeof(msg), ¤t, param, 1); isup_msg_start_variable_part(msg, sizeof(msg), &varpart, ¤t, 1, 0); @@ -3273,7 +3286,7 @@ } /* Reply with circuit group unblocking acknowledge. */ - isup_msg_init(msg, sizeof(msg), own_pc, inmsg->opc, inmsg->cic, ISUP_CUA, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, inmsg->opc, inmsg->cic, ISUP_CUA, ¤t); param[0] = inmsg->cgu.cgsmti; isup_msg_add_fixed(msg, sizeof(msg), ¤t, param, 1); isup_msg_start_variable_part(msg, sizeof(msg), &varpart, ¤t, 1, 0); @@ -3287,7 +3300,7 @@ { if (inmsg->opc != slink->linkset->dpc) { ast_log(LOG_DEBUG, "Got ISUP message from unconfigured PC=%d, typ=%s, CIC=%d\n", inmsg->opc, isupmsg(inmsg->typ), inmsg->cic); - isup_send_unequipped(slink->linkset->lsi, inmsg->cic, inmsg->opc); + isup_send_unequipped(slink->linkset->variant, slink->linkset->lsi, inmsg->cic, inmsg->opc); return; } @@ -3601,7 +3614,7 @@ ast_mutex_lock(&pvt->lock); pvt->cgb_mask = cgb_mask; - isup_msg_init(msg, sizeof(msg), own_pc, peerpc(pvt), firstcic, do_block ? ISUP_CGB : ISUP_CGU, ¤t); + isup_msg_init(msg, sizeof(msg), variant(pvt), own_pc, peerpc(pvt), firstcic, do_block ? ISUP_CGB : ISUP_CGU, ¤t); cir_group_sup_type_ind = sup_type_ind; isup_msg_add_fixed(msg, sizeof(msg), ¤t, &cir_group_sup_type_ind, 1); @@ -3988,11 +4001,11 @@ int res; if (event->typ == MTP_EVENT_ISUP) { - res = decode_isup_msg(&isup_msg, event->buf, event->len); + res = decode_isup_msg(&isup_msg, event->isup.link->linkset->variant, event->buf, event->len); dpc = isup_msg.opc; } else if (event->typ == MTP_REQ_ISUP_FORWARD) { - res = decode_isup_msg(&isup_msg, req->buf, req->len); + res = decode_isup_msg(&isup_msg, event->isup.link->linkset->variant, req->buf, req->len); dpc = isup_msg.dpc; } else { @@ -4054,7 +4067,7 @@ struct isup_msg isup_msg; int res; - res = decode_isup_msg(&isup_msg, event->buf, event->len); + res = decode_isup_msg(&isup_msg, event->isup.link->linkset->variant, event->buf, event->len); if(!res) { /* Q.764 (2.9.5): Discard invalid message.*/ ast_log(LOG_NOTICE, "ISUP decoding error, message discarded. (typ=%d)\n", isup_msg.typ); @@ -4067,7 +4080,7 @@ proxy_process_isup_message(event->isup.link, &isup_msg); } else { - isup_send_unequipped(event->isup.link->linkset->lsi, isup_msg.cic, isup_msg.opc); + isup_send_unequipped(event->isup.link->linkset->variant, event->isup.link->linkset->lsi, isup_msg.cic, isup_msg.opc); ast_log(LOG_WARNING, "Received CIC=%d for unequipped circuit (typ=%s), link '%s'.\n", isup_msg.cic, isupmsg(isup_msg.typ), event->isup.link->name); } } diff -ruNa old_ss7/mtp.c new_ss7/mtp.c --- old_ss7/mtp.c 2007-09-26 14:20:02.000000000 +0800 +++ new_ss7/mtp.c 2007-11-07 13:09:01.000000000 +0800 @@ -42,7 +42,7 @@ #include "asterisk/utils.h" #include "asterisk/sched.h" -#include "zaptel.h" +#include "linux/zaptel.h" #define FAST_HDLC_NEED_TABLES #include "fasthdlc.h" @@ -80,7 +80,7 @@ size is the minimum allowed, giving maximum responsiveness. */ enum { - NUM_ZAP_BUF = 2, + NUM_ZAP_BUF = 4, ZAP_BUF_SIZE = 16, }; @@ -292,6 +292,12 @@ return m->link->linkset->dpc; } +static inline ss7_variant variant(mtp2_t* m) +{ + return m->link->linkset->variant; +} + + static void mtp_put(mtp2_t *m, struct mtp_event *event) { static int log_safe_count = 0; int res; @@ -769,15 +775,28 @@ } } -void mtp3_put_label(int sls, int opc, int dpc, unsigned char *buf) { - buf[0] = dpc & 0xff; - buf[1] = ((dpc & 0x3f00) >> 8) | ((opc & 0x0003) << 6); - buf[2] = ((opc & 0x03fc) >> 2); - buf[3] = ((opc & 0x3c00) >> 10) | (sls << 4); +void mtp3_put_label(int sls, ss7_variant variant, int opc, int dpc, unsigned char *buf) { + if(variant==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); + } else { /* CHINA SS7 */ + 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; + } } -static void mtp3_set_sls(int sls, unsigned char *buf) { - buf[3] = (buf[3] & 0xff0f) | (sls << 4); +static void mtp3_set_sls(ss7_variant variant, int sls, unsigned char *buf) { + if(variant==ITU_SS7) + buf[3] = (buf[3] & 0xff0f) | (sls << 4); + else /* CHINESE SS7 */ + buf[6] = sls & 0x0f; } /* Handle Q.707 test-and-maintenance procedure. @@ -805,18 +824,25 @@ 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; static int mtp3_send_sltm(void *data) { - unsigned char message_sltm[21]; + unsigned char message_sltm[24]; //MiaoLin increased to 24 to fit China variant. mtp2_t *m = data; int subservice = m->subservice; if (subservice == -1) subservice = 0x8; mtp_log(m, LOG_EVENT, "Sending SLTM to peer on link '%s'....\n", m->name); - mtp3_put_label(m->sls, own_pc, peerpc(m), message_sltm); - 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)); + mtp3_put_label(m->sls, variant(m), own_pc, peerpc(m), message_sltm); + if(variant(m)==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)); + } else { /* CHINA SS7 */ + 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)); + } /* Set up a timer to wait for SLTA. */ if(m->sltm_t1 == -1) { /* Only if it is not already running */ @@ -966,15 +992,20 @@ /* Send TRA (traffic restart allowed) immediately, since we have no routing capabilities that could be prohibited/restricted. */ { - unsigned char message_tra[5]; + unsigned char message_tra[8]; int subservice = m->subservice; if (subservice == -1) subservice = 0x8; mtp_log(m, LOG_EVENT, "Sending TRA to peer on link '%s'....\n", m->name); - mtp3_put_label(m->sls, own_pc, peerpc(m), message_tra); - message_tra[4] = 0x17; /* TRA */ - mtp2_queue_msu(m, (subservice << 4) | 0, message_tra, 5); + mtp3_put_label(m->sls, variant(m), own_pc, peerpc(m), message_tra); + if(variant(m)==ITU_SS7) { + message_tra[4] = 0x17; /* TRA */ + mtp2_queue_msu(m, (subservice << 4) | 0, message_tra, 5); + } else { /* CHINA SS7 */ + message_tra[7] = 0x17; /* TRA */ + mtp2_queue_msu(m, (subservice << 4) | 0, message_tra, 8); + } } /* Send an initial SLTM message, and send it periodic afterwards. */ @@ -1046,7 +1077,8 @@ int h0, h1; int slt_pattern_len; int dpc, opc, slc; - + int i, j, k; + /* Process the FSN of the received frame. */ if(fsn == m->send_bsn) { /* Q.703 (5.2.2.c.i): Redundant retransmission. */ @@ -1079,18 +1111,24 @@ service_indicator = buf[3] & 0xf; subservice_field = (buf[3] & 0xf0) >> 4; - dpc = buf[4] | ((buf[5] & 0x3f) << 8); - opc = ((buf[5] & 0xc0) >> 6) | (buf[6] << 2) | ((buf[7] & 0x0f) << 10); - slc = (buf[7] & 0xf0) >> 4; + if(variant(m)==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; + } else { /* CHINA SS7 */ + 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; + } { char pbuf[1000], hex[30]; int i; strcpy(pbuf, ""); for(i = 0; i < li - 1 && i + 4 < len; i++) { - sprintf(hex, " %02x", buf[i + 4]); - strcat(pbuf, hex); - } + sprintf(hex, " %02x", buf[i + 4]); + strcat(pbuf, hex); + } mtp_log(m, LOG_DEBUG, "Got MSU on link '%s' sio=%d slc=%d m.sls=%d bsn=%d/%d, fsn=%d/%d, sio=%02x, len=%d:%s\n", m->name, service_indicator, slc, m->sls, bib, bsn, fib, fsn, buf[3], li, pbuf); } if (m->subservice == -1) { @@ -1098,6 +1136,7 @@ mtp_log(m, LOG_NOTICE, " Using subservice field from incoming MSU: 0x%x\n", subservice_field); } + switch(service_indicator) { case 0x0: /* Signalling network management messages. */ @@ -1109,9 +1148,16 @@ mtp_log(m, LOG_NOTICE, "Got short SLTM/SLTA (no h0/h1/len), li=%d on link '%s'.\n", li, m->name); return; } - h0 = buf[8] & 0xf; - h1 = (buf[8] & 0xf0) >> 4; - slt_pattern_len = (buf[9] & 0xf0) >> 4; + + if(variant(m)==ITU_SS7) { + h0 = buf[8] & 0xf; + h1 = (buf[8] & 0xf0) >> 4; + slt_pattern_len = (buf[9] & 0xf0) >> 4; + } else { /* CHINA SS7 */ + h0 = buf[11] & 0xf; + h1 = (buf[11] & 0xf0) >> 4; + slt_pattern_len = (buf[12] & 0xf0) >> 4; + } if(li < 7 + slt_pattern_len) { mtp_log(m, LOG_NOTICE, "Got short SLTM/SLTA (short pattern), li=%d, " @@ -1128,12 +1174,18 @@ if (subservice == -1) subservice = 0x8; - mtp3_put_label(slc, dpc, opc, message_slta); - 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); - + mtp3_put_label(slc, variant(m), dpc, opc, message_slta); + if(variant(m)==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); + } else { /* Chinese SS7 */ + 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); + } } else if(h0 == 0x1 && h1 == 0x2) { /* signalling link test acknowledgement message. */ @@ -1144,9 +1196,14 @@ } /* Q.707 (2.2) conditions for acceptance of SLTA. */ + if(variant(m)==ITU_SS7) + i = memcmp(sltm_pattern, &(buf[10]), sizeof(sltm_pattern)); + else /* CHINESE SS7 */ + i = memcmp(sltm_pattern, &(buf[13]), sizeof(sltm_pattern)); + if(slc == m->sls && opc == peerpc(m) && dpc == own_pc && - 0 == memcmp(sltm_pattern, &(buf[10]), sizeof(sltm_pattern))) { + 0 == i ) { int n_level4_up = 0; int i; for (i = 0; i < this_hosts_linkset.n_schannels; i++) { @@ -1187,6 +1244,13 @@ /* Spare. */ mtp_log(m, LOG_NOTICE, "Got unknown/spare signalling network testing " "and maintenance message code H0=0x%x/H1=0x%x on link '%s'.\n", h0, h1, m->name); + + mtp_log(m, LOG_NOTICE, "Fake msg is %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x \n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15], + buf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23]); } break; @@ -1615,7 +1679,7 @@ case MTP_REQ_ISUP: case MTP_REQ_ISUP_FORWARD: { int subservice = 0x5 /* ISUP */ | (m->subservice << 4); - mtp3_set_sls(m->sls, req->buf); // xxx is this necessary? + mtp3_set_sls(variant(m), m->sls, req->buf); // xxx is this necessary? mtp_log(m, LOG_DEBUG, "Queue MSU, lsi=%d, last_send_ix=%d, linkset=%s, m->link=%s\n", lsi, last_send_ix, linksets[lsi].name, m->link->name); mtp2_queue_msu(m, subservice, req->buf, req->len); #if 1 @@ -1836,7 +1900,8 @@ mtp_init_link_data(m); m->link = link; mtp_log(m, LOG_DEBUG, "init link %s, linkset %s, schannel %d, zapid %d.\n", link->name, link->linkset->name, link->schannel, zapid); - if(peerpc(m) < 0 || peerpc(m) >= (1<<14)) { + //if(peerpc(m) < 0 || peerpc(m) >= (1<<14)) { // MiaoLin modify to fit china variant + if(peerpc(m) < 0 || peerpc(m) >= (1<<24)) { ast_log(LOG_ERROR, "Invalid value 0x%x for peerpc.\n", peerpc(m)); goto fail; } @@ -1911,7 +1976,8 @@ controlbuf = NULL; receivepipe[0] = receivepipe[1] = -1; - if(own_pc < 0 || own_pc >= (1<<14)) { + //if(own_pc < 0 || own_pc >= (1<<14)) { // MiaoLin modify for china variant + if(own_pc < 0 || own_pc >= (1<<24)) { ast_log(LOG_ERROR, "Invalid value 0x%x for own_pc.\n", own_pc); return -1; } diff -ruNa old_ss7/mtp.h new_ss7/mtp.h --- old_ss7/mtp.h 2007-09-26 14:20:02.000000000 +0800 +++ new_ss7/mtp.h 2007-11-09 13:57:13.000000000 +0800 @@ -114,7 +114,7 @@ struct lffifo *mtp_get_receive_fifo(void); struct lffifo **mtp_get_send_fifo(void); struct lffifo *mtp_get_control_fifo(void); -void mtp3_put_label(int sls, int opc, int dpc, unsigned char *buf); +void mtp3_put_label(int sls, ss7_variant variant, int opc, int dpc, unsigned char *buf); int mtp_cmd_linkstatus(char* buff, int timeslot); int mtp_cmd_data(int fd, int argc, char *argv[]); int cmd_testfailover(int fd, int argc, char *argv[]); diff -ruNa old_ss7/ss7.conf.template.single-link.CHINA new_ss7/ss7.conf.template.single-link.CHINA --- old_ss7/ss7.conf.template.single-link.CHINA 1970-01-01 07:00:00.000000000 +0700 +++ new_ss7/ss7.conf.template.single-link.CHINA 2007-09-20 13:06:32.000000000 +0800 @@ -0,0 +1,27 @@ +[linkset-siuc] +enabled => yes +enable_st => no +use_connect => yes +hunting_policy => even_mru +context => default +language => us +;t35 => 15000,timeout +subservice => auto +variant => CHINA + +[link-l1] +linkset => siuc +channels => 1-15,17-31 +schannel => 16 +firstcic => 1 +enabled => yes +echocancel => no +echocan_train => 350 +echocan_taps => 128 + +[host-Magiclink] +enabled => yes +opc => 0x8e0 +dpc => siuc:0x3fff +links => l1:1 + diff -ruNa old_ss7/ss7.conf.template.two-links-one-signalling.CHINA new_ss7/ss7.conf.template.two-links-one-signalling.CHINA --- old_ss7/ss7.conf.template.two-links-one-signalling.CHINA 1970-01-01 07:00:00.000000000 +0700 +++ new_ss7/ss7.conf.template.two-links-one-signalling.CHINA 2007-11-09 11:35:11.000000000 +0800 @@ -0,0 +1,36 @@ +[linkset-siuc] +enabled => yes +enable_st => no +use_connect => yes +hunting_policy => even_mru +context => incoming +language => us +;t35 => 15000,timeout +subservice => auto +variant => CHINA + +[link-l1] +linkset => siuc +channels => 1-15,17-31 +schannel => 16 + +firstcic => 1 +enabled => yes +echocancel => no +echocan_train => 350 +echocan_taps => 128 + +[link-l2] +linkset => siuc +channels=> 1-30 +schannel => +firstcic => 97 +enabled => yes + + +[host-asteriskservice1] +enabled => yes +opc => 0x2b1475 +dpc => siuc:0x2b1464 +links => l1:1,l2:2 +if-1 => 127.0.0.1 diff -ruNa old_ss7/utils.c new_ss7/utils.c --- old_ss7/utils.c 2007-09-26 14:20:02.000000000 +0800 +++ new_ss7/utils.c 2007-11-07 11:41:46.000000000 +0800 @@ -36,6 +36,20 @@ #include "asterisk/utils.h" #include "asterisk/sched.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" #include "mtp.h" #include "utils.h"